Merge branch 'dccp' of git://eden-feed.erg.abdn.ac.uk/net-next-2.6
diff --git a/.mailmap b/.mailmap
index a62e6a8..581fd39 100644
--- a/.mailmap
+++ b/.mailmap
@@ -105,3 +105,4 @@
 Uwe Kleine-König <ukl@pengutronix.de>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
+Takashi YOSHII <takashi.yoshii.zj@renesas.com>
diff --git a/CREDITS b/CREDITS
index 41d8e63..494b6e4 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2365,8 +2365,6 @@
 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
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
new file mode 100644
index 0000000..b138b66
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -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 --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 22edcbb..35447e0 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -304,6 +304,10 @@
 !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 --git a/Documentation/DocBook/v4l/func-ioctl.xml b/Documentation/DocBook/v4l/func-ioctl.xml
index 00f9690e..b60fd37 100644
--- a/Documentation/DocBook/v4l/func-ioctl.xml
+++ b/Documentation/DocBook/v4l/func-ioctl.xml
@@ -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 @@
 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 --git a/Documentation/DocBook/v4l/pixfmt.xml b/Documentation/DocBook/v4l/pixfmt.xml
index d7c4671..cfffc88 100644
--- a/Documentation/DocBook/v4l/pixfmt.xml
+++ b/Documentation/DocBook/v4l/pixfmt.xml
@@ -142,8 +142,8 @@
 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 --git a/Documentation/Makefile b/Documentation/Makefile
index 6fc7ea1..9b4bc5c 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -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 --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index a851118..6a8c73f 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -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 @@
 	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 @@
 
 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 @@
 	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 @@
 	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 --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index ecf7d04..91c24a1 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -34,3 +34,5 @@
 	- description of the virtual memory layout
 nwfpe/
 	- NWFPE floating point emulator documentation
+swp_emulation
+	- SWP/SWPB emulation handler/logging description
diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
index 5389440..9012bb0 100644
--- a/Documentation/arm/OMAP/omap_pm
+++ b/Documentation/arm/OMAP/omap_pm
@@ -127,3 +127,28 @@
 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 --git a/Documentation/arm/swp_emulation b/Documentation/arm/swp_emulation
new file mode 100644
index 0000000..af903d2
--- /dev/null
+++ b/Documentation/arm/swp_emulation
@@ -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 --git a/Documentation/dontdiff b/Documentation/dontdiff
index d9bcffd..470d3db 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -62,6 +62,10 @@
 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 @@
 build
 bvmlinux
 bzImage*
+capflags.c
 classlist.h*
 comp*.log
 compile.h*
@@ -94,6 +99,7 @@
 docproc
 elf2ecoff
 elfconfig.h*
+evergreen_reg_safe.h
 fixdep
 flask.h
 fore200e_mkfirm
@@ -108,9 +114,16 @@
 *_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 @@
 mktables
 mktree
 modpost
+modules.builtin
 modules.order
 modversions.h*
 ncscope.*
@@ -153,14 +167,23 @@
 pca200e_ecd.bin2
 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 @@
 sm_tbl*
 split-include
 syscalltab.h
+tables.c
 tags
 tftpboot.img
 timeconst.h
@@ -190,6 +214,7 @@
 vmlinux-*
 vmlinux.aout
 vmlinux.lds
+voffset.h
 vsyscall.lds
 vsyscall_32.lds
 wanxlfw.inc
@@ -200,3 +225,4 @@
 wakeup.lds
 zImage*
 zconf.hash.c
+zoffset.h
diff --git a/Documentation/dvb/lmedm04.txt b/Documentation/dvb/lmedm04.txt
index e175784..6418865 100644
--- a/Documentation/dvb/lmedm04.txt
+++ b/Documentation/dvb/lmedm04.txt
@@ -46,7 +46,7 @@
 Other LG firmware can be extracted manually from US280D.sys
 only found in windows/system32/driver.
 
-dd if=US280D.sys ibs=1 skip=42616 count=3668 of=dvb-usb-lme2510-lg.fw
+dd if=US280D.sys ibs=1 skip=42360 count=3924 of=dvb-usb-lme2510-lg.fw
 
 for DM04 LME2510C (LG Tuner)
 ---------------------------
diff --git a/drivers/staging/udlfb/udlfb.txt b/Documentation/fb/udlfb.txt
similarity index 100%
rename from drivers/staging/udlfb/udlfb.txt
rename to Documentation/fb/udlfb.txt
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 6c2f55e..22f1081 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -97,36 +97,38 @@
 
 ---------------------------
 
-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>
 
 ---------------------------
@@ -564,3 +566,13 @@
 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>
+
+----------------------------
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index b6426f1..977d891 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -9,23 +9,25 @@
 
 --------------------------- 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);
 
 locking rules:
-	none have BKL
-		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
 
 --------------------------- inode_operations --------------------------- 
@@ -42,18 +44,23 @@
 	int (*rename) (struct inode *, struct dentry *,
 			struct inode *, struct dentry *);
 	int (*readlink) (struct dentry *, char __user *,int);
-	int (*follow_link) (struct dentry *, struct nameidata *);
+	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 *, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	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:
-	all may block, none have BKL
+	all may block
 		i_mutex(inode)
 lookup:		yes
 create:		yes
@@ -66,19 +73,24 @@
 rename:		yes (all)	(see below)
 readlink:	no
 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
 getxattr:	no
 listxattr:	no
 removexattr:	yes
+truncate_range:	yes
+fallocate:	no
+fiemap:		no
 	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
 	cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
 	->truncate() is never called directly - it's a callback, not a
-method. It's called by vmtruncate() - library function normally used by
+method. It's called by vmtruncate() - deprecated library function used by
 ->setattr(). Locking information above applies to that call (i.e. is
 inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been
 passed).
@@ -91,7 +103,7 @@
 	struct inode *(*alloc_inode)(struct super_block *sb);
 	void (*destroy_inode)(struct inode *);
 	void (*dirty_inode) (struct inode *);
-	int (*write_inode) (struct inode *, int);
+	int (*write_inode) (struct inode *, struct writeback_control *wbc);
 	int (*drop_inode) (struct inode *);
 	void (*evict_inode) (struct inode *);
 	void (*put_super) (struct super_block *);
@@ -105,10 +117,10 @@
 	int (*show_options)(struct seq_file *, struct vfsmount *);
 	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
 
 locking rules:
 	All may block [not true, see below]
-	None have BKL
 			s_umount
 alloc_inode:
 destroy_inode:
@@ -127,6 +139,7 @@
 show_options:		no		(namespace_sem)
 quota_read:		no		(see below)
 quota_write:		no		(see below)
+bdev_try_to_free_page:	no		(see below)
 
 ->statfs() has s_umount (shared) when called by ustat(2) (native or
 compat), but that's an accident of bad API; s_umount is used to pin
@@ -139,19 +152,25 @@
 dqio_sem) (unless an admin really wants to screw up something and
 writes to quota files with quotas on). For other details about locking
 see also dquot_operations section.
+->bdev_try_to_free_page is called from the ->releasepage handler of
+the block device inode.  See there for more details.
 
 --------------------------- file_system_type ---------------------------
 prototypes:
 	int (*get_sb) (struct file_system_type *, int,
 		       const char *, void *, struct vfsmount *);
+	struct dentry *(*mount) (struct file_system_type *, int,
+		       const char *, void *);
 	void (*kill_sb) (struct super_block *);
 locking rules:
-		may block	BKL
-get_sb		yes		no
-kill_sb		yes		no
+		may block
+get_sb		yes
+mount		yes
+kill_sb		yes
 
 ->get_sb() returns error or 0 with locked superblock attached to the vfsmount
 (exclusive on ->s_umount).
+->mount() returns ERR_PTR or the root dentry.
 ->kill_sb() takes a write-locked superblock, does all shutdown work on it,
 unlocks and drops the reference.
 
@@ -176,27 +195,35 @@
 	void (*freepage)(struct page *);
 	int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs);
-	int (*launder_page) (struct page *);
+	int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **,
+				unsigned long *);
+	int (*migratepage)(struct address_space *, struct page *, struct page *);
+	int (*launder_page)(struct page *);
+	int (*is_partially_uptodate)(struct page *, read_descriptor_t *, unsigned long);
+	int (*error_remove_page)(struct address_space *, struct page *);
 
 locking rules:
 	All except set_page_dirty and freepage may block
 
-			BKL	PageLocked(page)	i_mutex
-writepage:		no	yes, unlocks (see below)
-readpage:		no	yes, unlocks
-sync_page:		no	maybe
-writepages:		no
-set_page_dirty		no	no
-readpages:		no
-write_begin:		no	locks the page		yes
-write_end:		no	yes, unlocks		yes
-perform_write:		no	n/a			yes
-bmap:			no
-invalidatepage:		no	yes
-releasepage:		no	yes
-freepage:		no	yes
-direct_IO:		no
-launder_page:		no	yes
+			PageLocked(page)	i_mutex
+writepage:		yes, unlocks (see below)
+readpage:		yes, unlocks
+sync_page:		maybe
+writepages:
+set_page_dirty		no
+readpages:
+write_begin:		locks the page		yes
+write_end:		yes, unlocks		yes
+bmap:
+invalidatepage:		yes
+releasepage:		yes
+freepage:		yes
+direct_IO:
+get_xip_mem:					maybe
+migratepage:		yes (both)
+launder_page:		yes
+is_partially_uptodate:	yes
+error_remove_page:	yes
 
 	->write_begin(), ->write_end(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
@@ -276,9 +303,8 @@
 not locked.
 
 	->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
-filesystems and by the swapper. The latter will eventually go away. All
-instances do not actually need the BKL. Please, keep it that way and don't
-breed new callers.
+filesystems and by the swapper. The latter will eventually go away.  Please,
+keep it that way and don't breed new callers.
 
 	->invalidatepage() is called when the filesystem must attempt to drop
 some or all of the buffers from the page when it is being truncated.  It
@@ -299,47 +325,37 @@
 getting mapped back in and redirtied, it needs to be kept locked
 across the entire operation.
 
-	Note: currently almost all instances of address_space methods are
-using BKL for internal serialization and that's one of the worst sources
-of contention. Normally they are calling library functions (in fs/buffer.c)
-and pass foo_get_block() as a callback (on local block-based filesystems,
-indeed). BKL is not needed for library stuff and is usually taken by
-foo_get_block(). It's an overkill, since block bitmaps can be protected by
-internal fs locking and real critical areas are much smaller than the areas
-filesystems protect now.
-
 ----------------------- file_lock_operations ------------------------------
 prototypes:
-	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */
-	void (*fl_remove)(struct file_lock *);	/* lock removal callback */
 	void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
 	void (*fl_release_private)(struct file_lock *);
 
 
 locking rules:
-			BKL	may block
-fl_insert:		yes	no
-fl_remove:		yes	no
-fl_copy_lock:		yes	no
-fl_release_private:	yes	yes
+			file_lock_lock	may block
+fl_copy_lock:		yes		no
+fl_release_private:	maybe		no
 
 ----------------------- lock_manager_operations ---------------------------
 prototypes:
 	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
 	void (*fl_notify)(struct file_lock *);  /* unblock callback */
+	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:
-			BKL	may block
-fl_compare_owner:	yes	no
-fl_notify:		yes	no
-fl_release_private:	yes	yes
-fl_break:		yes	no
+			file_lock_lock	may block
+fl_compare_owner:	yes		no
+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
 
-	Currently only NFSD and NLM provide instances of this class. None of the
-them block. If you have out-of-tree instances - please, show up. Locking
-in that area will change.
 --------------------------- buffer_head -----------------------------------
 prototypes:
 	void (*b_end_io)(struct buffer_head *bh, int uptodate);
@@ -364,17 +380,17 @@
 	void (*swap_slot_free_notify) (struct block_device *, unsigned long);
 
 locking rules:
-			BKL	bd_mutex
-open:			no	yes
-release:		no	yes
-ioctl:			no	no
-compat_ioctl:		no	no
-direct_access:		no	no
-media_changed:		no	no
-unlock_native_capacity:	no	no
-revalidate_disk:	no	no
-getgeo:			no	no
-swap_slot_free_notify:	no	no	(see below)
+			bd_mutex
+open:			yes
+release:		yes
+ioctl:			no
+compat_ioctl:		no
+direct_access:		no
+media_changed:		no
+unlock_native_capacity:	no
+revalidate_disk:	no
+getgeo:			no
+swap_slot_free_notify:	no	(see below)
 
 media_changed, unlock_native_capacity and revalidate_disk are called only from
 check_disk_change().
@@ -413,34 +429,21 @@
 	unsigned long (*get_unmapped_area)(struct file *, unsigned long,
 			unsigned long, unsigned long, unsigned long);
 	int (*check_flags)(int);
+	int (*flock) (struct file *, int, struct file_lock *);
+	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
+			size_t, unsigned int);
+	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
+			size_t, unsigned int);
+	int (*setlease)(struct file *, long, struct file_lock **);
 };
 
 locking rules:
-	All may block.
-			BKL
-llseek:			no	(see below)
-read:			no
-aio_read:		no
-write:			no
-aio_write:		no
-readdir: 		no
-poll:			no
-unlocked_ioctl:		no
-compat_ioctl:		no
-mmap:			no
-open:			no
-flush:			no
-release:		no
-fsync:			no	(see below)
-aio_fsync:		no
-fasync:			no
-lock:			yes
-readv:			no
-writev:			no
-sendfile:		no
-sendpage:		no
-get_unmapped_area:	no
-check_flags:		no
+	All may block except for ->setlease.
+	No VFS locks held on entry except for ->fsync and ->setlease.
+
+->fsync() has i_mutex on inode.
+
+->setlease has the file_list_lock held and must not sleep.
 
 ->llseek() locking has moved from llseek to the individual llseek
 implementations.  If your fs is not using generic_file_llseek, you
@@ -450,17 +453,10 @@
 Note: this does not protect the file->f_pos against concurrent modifications
 since this is something the userspace has to take care about.
 
-Note: ext2_release() was *the* source of contention on fs-intensive
-loads and dropping BKL on ->release() helps to get rid of that (we still
-grab BKL for cases when we close a file that had been opened r/w, but that
-can and should be done using the internal locking with smaller critical areas).
-Current worst offender is ext2_get_block()...
-
-->fasync() is called without BKL protection, and is responsible for
-maintaining the FASYNC bit in filp->f_flags.  Most instances call
-fasync_helper(), which does that maintenance, so it's not normally
-something one needs to worry about.  Return values > 0 will be mapped to
-zero in the VFS layer.
+->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags.
+Most instances call fasync_helper(), which does that maintenance, so it's
+not normally something one needs to worry about.  Return values > 0 will be
+mapped to zero in the VFS layer.
 
 ->readdir() and ->ioctl() on directories must be changed. Ideally we would
 move ->readdir() to inode_operations and use a separate method for directory
@@ -471,8 +467,6 @@
 ->read on directories probably must go away - we should just enforce -EISDIR
 in sys_read() and friends.
 
-->fsync() has i_mutex on inode.
-
 --------------------------- dquot_operations -------------------------------
 prototypes:
 	int (*write_dquot) (struct dquot *);
@@ -507,12 +501,12 @@
 	int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
 
 locking rules:
-		BKL	mmap_sem	PageLocked(page)
-open:		no	yes
-close:		no	yes
-fault:		no	yes		can return with page locked
-page_mkwrite:	no	yes		can return with page locked
-access:		no	yes
+		mmap_sem	PageLocked(page)
+open:		yes
+close:		yes
+fault:		yes		can return with page locked
+page_mkwrite:	yes		can return with page locked
+access:		yes
 
 	->fault() is called when a previously not present pte is about
 to be faulted in. The filesystem must find and return the page associated
@@ -539,6 +533,3 @@
 
 (if you break something or notice that it is broken and do not fix it yourself
 - at least put it here)
-
-ipc/shm.c::shm_delete() - may need BKL.
-->read() and ->write() in many drivers are (probably) missing BKL.
diff --git a/Documentation/filesystems/dentry-locking.txt b/Documentation/filesystems/dentry-locking.txt
deleted file mode 100644
index 79334ed..0000000
--- a/Documentation/filesystems/dentry-locking.txt
+++ /dev/null
@@ -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 --git a/Documentation/filesystems/path-lookup.txt b/Documentation/filesystems/path-lookup.txt
new file mode 100644
index 0000000..eb59c8b
--- /dev/null
+++ b/Documentation/filesystems/path-lookup.txt
@@ -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 --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index b12c895..07a32b4 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -216,7 +216,6 @@
 ->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,71 @@
 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-walk.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_RCU). See
+Documentation/filesystems/vfs.txt for more details.
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index e73df27..9471225 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1181,6 +1181,30 @@
  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
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 20899e0..fbb324e 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -325,7 +325,8 @@
         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 @@
   permission: called by the VFS to check for access rights on a POSIX-like
   	filesystem.
 
+	May be called in rcu-walk mode (flags & IPERM_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,9 +855,12 @@
 
 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);
@@ -860,13 +871,45 @@
 	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
 
@@ -910,14 +953,11 @@
 	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 --git a/Documentation/input/cma3000_d0x.txt b/Documentation/input/cma3000_d0x.txt
new file mode 100644
index 0000000..29d088d
--- /dev/null
+++ b/Documentation/input/cma3000_d0x.txt
@@ -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 --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt
index bdcba154..71536e7 100644
--- a/Documentation/input/multi-touch-protocol.txt
+++ b/Documentation/input/multi-touch-protocol.txt
@@ -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 @@
 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 @@
 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 @@
 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 @@
 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 --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 63ffd78..d6a63c7 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -155,7 +155,6 @@
 '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 @@
 					<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!
@@ -260,14 +258,11 @@
 '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 @@
 					<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 --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index 715eaaf..9a86746 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -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 --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 8b61c93..f3dc951 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1579,20 +1579,12 @@
 
 	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 +1614,8 @@
 	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.
 
@@ -1759,7 +1753,7 @@
 
 	nousb		[USB] Disable the USB subsystem
 
-	nowatchdog	[KNL] Disable the lockup detector.
+	nowatchdog	[KNL] Disable the lockup detector (NMI watchdog).
 
 	nowb		[ARM]
 
@@ -2467,12 +2461,13 @@
 			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 --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index 00301ed..b64d10d 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -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 --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX
index 07dcdb0..e09468a 100644
--- a/Documentation/serial/00-INDEX
+++ b/Documentation/serial/00-INDEX
@@ -14,6 +14,8 @@
 	- 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 --git a/Documentation/serial/serial-rs485.txt b/Documentation/serial/serial-rs485.txt
new file mode 100644
index 0000000..a493238
--- /dev/null
+++ b/Documentation/serial/serial-rs485.txt
@@ -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 --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
index 6bb916d..68a4fe3 100644
--- a/Documentation/spi/pxa2xx
+++ b/Documentation/spi/pxa2xx
@@ -19,7 +19,7 @@
 -----------------------------------
 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 @@
 
 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 --git a/Documentation/trace/events-power.txt b/Documentation/trace/events-power.txt
new file mode 100644
index 0000000..96d87b6
--- /dev/null
+++ b/Documentation/trace/events-power.txt
@@ -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 --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index b29d8e5..c9ffa9c 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -2,7 +2,7 @@
 
 		 Alan Stern <stern@rowland.harvard.edu>
 
-			    December 11, 2009
+			    October 28, 2010
 
 
 
@@ -107,9 +107,14 @@
 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 @@
 		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 @@
 
 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 @@
 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 @@
 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 @@
 
 	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 @@
 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 --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index ac2616a..31b4857 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -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 --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 8d9afc7..6b4c72d 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -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 --git a/Documentation/video4linux/Makefile b/Documentation/video4linux/Makefile
deleted file mode 100644
index 1ed0e98..0000000
--- a/Documentation/video4linux/Makefile
+++ /dev/null
@@ -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 --git a/Documentation/video4linux/README.cpia b/Documentation/video4linux/README.cpia
deleted file mode 100644
index 8a747fe..0000000
--- a/Documentation/video4linux/README.cpia
+++ /dev/null
@@ -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 --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index 00e3f92..699b60e 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -322,76 +322,11 @@
 
 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 @@
    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 --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards
index 12217fc..db833ce 100644
--- a/Documentation/video4linux/bttv/Cards
+++ b/Documentation/video4linux/bttv/Cards
@@ -464,10 +464,6 @@
 -------
    Multimedia eXtension Board (MXB) (SAA7146, SAA7111)
 
-Stradis
--------
-   SDM275,SDM250,SDM026,SDM025 (SAA7146, IBMMPEG2): MPEG2 decoder only
-
 Powercolor
 ----------
    MTV878
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 6a562ee..261776e 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -366,6 +366,7 @@
 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 --git a/Documentation/video4linux/meye.txt b/Documentation/video4linux/meye.txt
index bf3af5f..34e2842 100644
--- a/Documentation/video4linux/meye.txt
+++ b/Documentation/video4linux/meye.txt
@@ -45,8 +45,6 @@
 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 @@
 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 @@
 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 --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c
deleted file mode 100644
index c8ded17..0000000
--- a/Documentation/video4linux/v4lgrab.c
+++ /dev/null
@@ -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 --git a/Documentation/video4linux/videobuf b/Documentation/video4linux/videobuf
index 17a1f9a..1d00d7f 100644
--- a/Documentation/video4linux/videobuf
+++ b/Documentation/video4linux/videobuf
@@ -247,8 +247,6 @@
 		       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 @@
 
 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 --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index 30b43e1..bdeb81c 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -600,6 +600,7 @@
   0x00000001	lguest
   0x00000002	Xen
   0x00000003	Moorestown MID
+  0x00000004	CE4100 TV Platform
 
 Field name:	hardware_subarch_data
 Type:		write (subarch-dependent)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2424699..23d0436 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -791,11 +791,14 @@
 
 ARM/NOMADIK ARCHITECTURE
 M:	Alessandro Rubini <rubini@unipv.it>
+M:	Linus Walleij <linus.walleij@stericsson.com>
 M:	STEricsson <STEricsson_nomadik_linux@list.st.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-nomadik/
 F:	arch/arm/plat-nomadik/
+F:	drivers/i2c/busses/i2c-nomadik.c
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
 
 ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
 M:	Nelson Castillo <arhuaco@freaks-unidos.net>
@@ -997,12 +1000,24 @@
 F:	drivers/rtc/rtc-coh901331.c
 F:	drivers/watchdog/coh901327_wdt.c
 F:	drivers/dma/coh901318*
+F:	drivers/mfd/ab3100*
+F:	drivers/rtc/rtc-ab3100.c
+F:	drivers/rtc/rtc-coh901331.c
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
 
-ARM/U8500 ARM ARCHITECTURE
+ARM/Ux500 ARM ARCHITECTURE
 M:	Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+M:	Linus Walleij <linus.walleij@stericsson.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-ux500/
+F:	drivers/dma/ste_dma40*
+F:	drivers/mfd/ab3550*
+F:	drivers/mfd/abx500*
+F:	drivers/mfd/ab8500*
+F:	drivers/mfd/stmpe*
+F:	drivers/rtc/rtc-ab8500.c
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
 
 ARM/VFP SUPPORT
 M:	Russell King <linux@arm.linux.org.uk>
@@ -2811,6 +2826,10 @@
 S:	Maintained
 F:	Documentation/timers/
 F:	kernel/hrtimer.c
+F:	kernel/time/clockevents.c
+F:	kernel/time/tick*.*
+F:	kernel/time/timer_*.c
+F	include/linux/clockevents.h
 F:	include/linux/hrtimer.h
 
 HIGH-SPEED SCC DRIVER FOR AX.25
@@ -3046,8 +3065,10 @@
 INPUT MULTITOUCH (MT) PROTOCOL
 M:	Henrik Rydberg <rydberg@euromail.se>
 L:	linux-input@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rydberg/input-mt.git
 S:	Maintained
 F:	Documentation/input/multi-touch-protocol.txt
+F:	drivers/input/input-mt.c
 K:	\b(ABS|SYN)_MT_
 
 INTEL IDLE DRIVER
@@ -4344,6 +4365,20 @@
 S:	Maintained
 F:	drivers/char/hw_random/omap-rng.c
 
+OMAP HWMOD SUPPORT
+M:	Benoît Cousson <b-cousson@ti.com>
+M:	Paul Walmsley <paul@pwsan.com>
+L:	linux-omap@vger.kernel.org
+S:	Maintained
+F:	arch/arm/mach-omap2/omap_hwmod.c
+F:	arch/arm/plat-omap/include/plat/omap_hwmod.h
+
+OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
+M:	Benoît Cousson <b-cousson@ti.com>
+L:	linux-omap@vger.kernel.org
+S:	Maintained
+F:	arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+
 OMAP USB SUPPORT
 M:	Felipe Balbi <balbi@ti.com>
 M:	David Brownell <dbrownell@users.sourceforge.net>
@@ -4618,6 +4653,16 @@
 F:	crypto/pcrypt.c
 F:	include/crypto/pcrypt.h
 
+PER-CPU MEMORY ALLOCATOR
+M:	Tejun Heo <tj@kernel.org>
+M:	Christoph Lameter <cl@linux-foundation.org>
+L:	linux-kernel@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git
+S:	Maintained
+F:	include/linux/percpu*.h
+F:	mm/percpu*.c
+F:	arch/*/include/asm/percpu.h
+
 PER-TASK DELAY ACCOUNTING
 M:	Balbir Singh <balbir@linux.vnet.ibm.com>
 S:	Maintained
@@ -4628,7 +4673,7 @@
 M:	Peter Zijlstra <a.p.zijlstra@chello.nl>
 M:	Paul Mackerras <paulus@samba.org>
 M:	Ingo Molnar <mingo@elte.hu>
-M:	Arnaldo Carvalho de Melo <acme@redhat.com>
+M:	Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 S:	Supported
 F:	kernel/perf_event*.c
 F:	include/linux/perf_event.h
@@ -5153,6 +5198,18 @@
 S:	Supported
 F:	sound/soc/s3c24xx
 
+TIMEKEEPING, NTP
+M:	John Stultz <johnstul@us.ibm.com>
+M:	Thomas Gleixner <tglx@linutronix.de>
+S:	Supported
+F:	include/linux/clocksource.h
+F:	include/linux/time.h
+F:	include/linux/timex.h
+F:	include/linux/timekeeping.h
+F:	kernel/time/clocksource.c
+F:	kernel/time/time*.c
+F:	kernel/time/ntp.c
+
 TLG2300 VIDEO4LINUX-2 DRIVER
 M:	Huang Shijie <shijie8@gmail.com>
 M:	Kang Yong <kangyong@telegent.com>
@@ -5723,12 +5780,6 @@
 S:	Odd Fixes
 F:	drivers/net/starfire*
 
-STRADIS MPEG-2 DECODER DRIVER
-M:	Nathan Laredo <laredo@gnu.org>
-W:	http://www.stradis.com/
-S:	Maintained
-F:	drivers/media/video/stradis.c
-
 SUN3/3X
 M:	Sam Creasey <sammy@sammy.net>
 W:	http://sammy.net/sun3/
diff --git a/Makefile b/Makefile
index 77044b7..74b2555 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 37
-EXTRAVERSION = -rc7
+EXTRAVERSION =
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
diff --git a/arch/Kconfig b/arch/Kconfig
index 8bf0fa65..f78c2be 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -175,4 +175,7 @@
 config HAVE_ARCH_JUMP_LABEL
 	bool
 
+config HAVE_ARCH_MUTEX_CPU_RELAX
+	bool
+
 source "kernel/gcov/Kconfig"
diff --git a/arch/alpha/include/asm/ioctls.h b/arch/alpha/include/asm/ioctls.h
index 59617c3..034b6cf 100644
--- a/arch/alpha/include/asm/ioctls.h
+++ b/arch/alpha/include/asm/ioctls.h
@@ -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 --git a/arch/alpha/include/asm/perf_event.h b/arch/alpha/include/asm/perf_event.h
index fe792ca..5996e7a 100644
--- a/arch/alpha/include/asm/perf_event.h
+++ b/arch/alpha/include/asm/perf_event.h
@@ -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 --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index 5f77afb..4c8bb37 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -112,8 +112,6 @@
 	wrent(entInt, 0);
 
 	alpha_mv.init_irq();
-
-	init_hw_perf_events();
 }
 
 /*
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 1cc4968..90561c4 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -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 @@
 /*
  * 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 @@
 	/* 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 --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c..e2f8011 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2,6 +2,7 @@
 	bool
 	default y
 	select HAVE_AOUT
+	select HAVE_DMA_API_DEBUG
 	select HAVE_IDE
 	select HAVE_MEMBLOCK
 	select RTC_LIB
@@ -14,6 +15,7 @@
 	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,7 @@
 	select PERF_USE_VMALLOC
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
+	select HAVE_C_RECORDMCOUNT
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -34,9 +37,15 @@
 config HAVE_PWM
 	bool
 
+config MIGHT_HAVE_PCI
+	bool
+
 config SYS_SUPPORTS_APM_EMULATION
 	bool
 
+config HAVE_SCHED_CLOCK
+	bool
+
 config GENERIC_GPIO
 	bool
 
@@ -221,7 +230,7 @@
 	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 +240,8 @@
 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 +255,8 @@
 	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 +270,10 @@
 	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 +292,7 @@
 	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 +310,7 @@
 	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 +340,7 @@
 	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 +360,22 @@
 	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 COMMON_CLKDEV
+	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 +454,8 @@
 	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 +495,7 @@
 	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 +529,9 @@
 	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 +563,7 @@
 	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 +577,19 @@
 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 +599,7 @@
 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 +609,10 @@
 	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 +632,15 @@
 	  (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 +667,7 @@
 	select CPU_FREQ
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
+	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select ARCH_REQUIRE_GPIOLIB
 	help
@@ -761,7 +794,7 @@
 	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 +814,12 @@
 	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 +829,9 @@
 	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 +840,7 @@
 	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 +852,7 @@
 	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 +864,7 @@
 	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 +873,7 @@
 	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 +938,8 @@
 
 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 +1020,11 @@
 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 +1039,8 @@
 
 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 +1057,11 @@
 	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
@@ -1164,7 +1209,7 @@
 	bool
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+	bool "PCI support" if 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 +1220,12 @@
 	bool
 	depends on PCI
 
+config PCI_NANOENGINE
+	bool "BSE nanoEngine PCI support"
+	depends on SA1100_NANOENGINE
+	help
+	  Enable PCI on the BSE nanoEngine board.
+
 config PCI_SYSCALL
 	def_bool PCI
 
@@ -1205,10 +1256,11 @@
 	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 +1281,7 @@
 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
 	default y
 	help
 	  SMP kernels contain instructions which fail on non-SMP processors.
@@ -1248,6 +1300,7 @@
 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 +1336,7 @@
 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 +1345,7 @@
 	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 +1364,7 @@
 	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
@@ -1524,6 +1578,7 @@
 
 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 +1705,19 @@
 	  Should the atags used to boot the kernel be exported in an "atags"
 	  file in procfs. Useful with kexec.
 
+config CRASH_DUMP
+	bool "Build kdump crash kernel (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  Generate crash dump after being started by kexec. This should
+	  be normally only set in special crash dump kernels which are
+	  loaded in the main kernel with kexec-tools into a specially
+	  reserved region and then later executed after a crash by
+	  kdump/kexec. The crash dump kernel must be compiled to a
+	  memory address not used by the main kernel
+
+	  For more details see Documentation/kdump/kdump.txt
+
 config AUTO_ZRELADDR
 	bool "Auto calculation of the decompressed kernel image address"
 	depends on !ZBOOT_ROM && !ARCH_U300
@@ -1707,7 +1775,7 @@
 	  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 +1787,7 @@
 	  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 --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 2fd0b99..494224a 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -23,7 +23,7 @@
 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 @@
 	  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 --git a/arch/arm/Makefile b/arch/arm/Makefile
index b87aed0..c22c1ad 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -154,10 +154,11 @@
 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 --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 65a7c1c..0a8f748 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -45,6 +45,10 @@
 endif
 endif
 
+ifeq ($(CONFIG_ARCH_SHMOBILE),y)
+OBJS		+= head-shmobile.o
+endif
+
 #
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
new file mode 100644
index 0000000..30973b7
--- /dev/null
+++ b/arch/arm/boot/compressed/head-shmobile.S
@@ -0,0 +1,53 @@
+/*
+ * The head-file for SH-Mobile ARM platforms
+ *
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Simon Horman <horms@verge.net.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef CONFIG_ZBOOT_ROM
+
+	.section	".start", "ax"
+
+	/* load board-specific initialization code */
+#include <mach/zboot.h>
+
+	b	1f
+__atags:@ tag #1
+	.long	12			@ tag->hdr.size = tag_size(tag_core);
+	.long	0x54410001		@ tag->hdr.tag = ATAG_CORE;
+	.long   0			@ tag->u.core.flags = 0;
+	.long	0			@ tag->u.core.pagesize = 0;
+	.long	0			@ tag->u.core.rootdev = 0;
+	@ tag #2
+	.long	8			@ tag->hdr.size = tag_size(tag_mem32);
+	.long	0x54410002		@ tag->hdr.tag = ATAG_MEM;
+	.long	CONFIG_MEMORY_SIZE	@ tag->u.mem.size = CONFIG_MEMORY_SIZE;
+	.long	CONFIG_MEMORY_START	@ @ tag->u.mem.start = CONFIG_MEMORY_START;
+	@ tag #3
+	.long	0			@ tag->hdr.size = 0
+	.long	0			@ tag->hdr.tag = ATAG_NONE;
+1:
+
+	/* Set board ID necessary for boot */
+	ldr	r7, 1f				@ Set machine type register
+	adr	r8, __atags			@ Set atag register
+	b	2f
+
+1 :	.long MACH_TYPE
+2 :
+
+#endif /* CONFIG_ZBOOT_ROM */
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 0a34c81..778655f 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -37,7 +37,3 @@
 
 config SHARP_SCOOP
 	bool
-
-config COMMON_CLKDEV
-	bool
-	select HAVE_CLK
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index e6e8664..e7521bca 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -17,3 +17,4 @@
 obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_COMMON_CLKDEV)	+= clkdev.o
+obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c
deleted file mode 100644
index e2b2bb6..0000000
--- a/arch/arm/common/clkdev.c
+++ /dev/null
@@ -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 --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index cc0a932..e568163 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -328,7 +328,7 @@
  * 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 @@
 
 	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 @@
  * 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 @@
 
 	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 @@
 
 	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 @@
  * 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 @@
 
 	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 --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index e6388dc..0b89ef0 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -35,6 +35,9 @@
 
 static DEFINE_SPINLOCK(irq_controller_lock);
 
+/* Address of GIC 0 CPU interface */
+void __iomem *gic_cpu_base_addr __read_mostly;
+
 struct gic_chip_data {
 	unsigned int irq_offset;
 	void __iomem *dist_base;
@@ -45,7 +48,7 @@
 #define MAX_GIC_NR	1
 #endif
 
-static struct gic_chip_data gic_data[MAX_GIC_NR];
+static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
 
 static inline void __iomem *gic_dist_base(unsigned int irq)
 {
@@ -213,21 +216,16 @@
 	set_irq_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
-			  unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic,
+	unsigned int irq_start)
 {
 	unsigned int gic_irqs, irq_limit, i;
+	void __iomem *base = gic->dist_base;
 	u32 cpumask = 1 << smp_processor_id();
 
-	if (gic_nr >= MAX_GIC_NR)
-		BUG();
-
 	cpumask |= cpumask << 8;
 	cpumask |= cpumask << 16;
 
-	gic_data[gic_nr].dist_base = base;
-	gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
-
 	writel(0, base + GIC_DIST_CTRL);
 
 	/*
@@ -267,7 +265,7 @@
 	/*
 	 * Limit number of interrupts registered to the platform maximum
 	 */
-	irq_limit = gic_data[gic_nr].irq_offset + gic_irqs;
+	irq_limit = gic->irq_offset + gic_irqs;
 	if (WARN_ON(irq_limit > NR_IRQS))
 		irq_limit = NR_IRQS;
 
@@ -276,7 +274,7 @@
 	 */
 	for (i = irq_start; i < irq_limit; i++) {
 		set_irq_chip(i, &gic_chip);
-		set_irq_chip_data(i, &gic_data[gic_nr]);
+		set_irq_chip_data(i, gic);
 		set_irq_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
@@ -284,19 +282,12 @@
 	writel(1, base + GIC_DIST_CTRL);
 }
 
-void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
+static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 {
-	void __iomem *dist_base;
+	void __iomem *dist_base = gic->dist_base;
+	void __iomem *base = gic->cpu_base;
 	int i;
 
-	if (gic_nr >= MAX_GIC_NR)
-		BUG();
-
-	dist_base = gic_data[gic_nr].dist_base;
-	BUG_ON(!dist_base);
-
-	gic_data[gic_nr].cpu_base = base;
-
 	/*
 	 * Deal with the banked PPI and SGI interrupts - disable all
 	 * PPI interrupts, ensure all SGI interrupts are enabled.
@@ -314,6 +305,42 @@
 	writel(1, base + GIC_CPU_CTRL);
 }
 
+void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+	void __iomem *dist_base, void __iomem *cpu_base)
+{
+	struct gic_chip_data *gic;
+
+	BUG_ON(gic_nr >= MAX_GIC_NR);
+
+	gic = &gic_data[gic_nr];
+	gic->dist_base = dist_base;
+	gic->cpu_base = cpu_base;
+	gic->irq_offset = (irq_start - 1) & ~31;
+
+	if (gic_nr == 0)
+		gic_cpu_base_addr = cpu_base;
+
+	gic_dist_init(gic, irq_start);
+	gic_cpu_init(gic);
+}
+
+void __cpuinit gic_secondary_init(unsigned int gic_nr)
+{
+	BUG_ON(gic_nr >= MAX_GIC_NR);
+
+	gic_cpu_init(&gic_data[gic_nr]);
+}
+
+void __cpuinit gic_enable_ppi(unsigned int irq)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	irq_to_desc(irq)->status |= IRQ_NOPROBE;
+	gic_unmask_irq(irq);
+	local_irq_restore(flags);
+}
+
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index 1bec96e..42ff90b 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -352,3 +352,4 @@
 	return pci_scan_bus(nr, &it8152_ops, sys);
 }
 
+EXPORT_SYMBOL(dma_set_coherent_mask);
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
new file mode 100644
index 0000000..6ef3342
--- /dev/null
+++ b/arch/arm/common/timer-sp.c
@@ -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 --git a/arch/arm/configs/ag5evm_defconfig b/arch/arm/configs/ag5evm_defconfig
new file mode 100644
index 0000000..2b9cf56
--- /dev/null
+++ b/arch/arm/configs/ag5evm_defconfig
@@ -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_EMBEDDED=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 --git a/arch/arm/configs/ams_delta_defconfig b/arch/arm/configs/ams_delta_defconfig
deleted file mode 100644
index 75de45e..0000000
--- a/arch/arm/configs/ams_delta_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/htcherald_defconfig b/arch/arm/configs/htcherald_defconfig
deleted file mode 100644
index edfa1c0..0000000
--- a/arch/arm/configs/htcherald_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/mackerel_defconfig b/arch/arm/configs/mackerel_defconfig
new file mode 100644
index 0000000..306a2e2
--- /dev/null
+++ b/arch/arm/configs/mackerel_defconfig
@@ -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 --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig
index f0c339f..e648ea3 100644
--- a/arch/arm/configs/mx3_defconfig
+++ b/arch/arm/configs/mx3_defconfig
@@ -84,6 +84,7 @@
 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 --git a/arch/arm/configs/n770_defconfig b/arch/arm/configs/n770_defconfig
deleted file mode 100644
index 993e94d..0000000
--- a/arch/arm/configs/n770_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
new file mode 100644
index 0000000..a350cc6
--- /dev/null
+++ b/arch/arm/configs/omap1_defconfig
@@ -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_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_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 --git a/arch/arm/configs/omap_generic_1510_defconfig b/arch/arm/configs/omap_generic_1510_defconfig
deleted file mode 100644
index 0e42ba4..0000000
--- a/arch/arm/configs/omap_generic_1510_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap_generic_1610_defconfig b/arch/arm/configs/omap_generic_1610_defconfig
deleted file mode 100644
index 5e536cf..0000000
--- a/arch/arm/configs/omap_generic_1610_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap_generic_1710_defconfig b/arch/arm/configs/omap_generic_1710_defconfig
deleted file mode 100644
index c0867b1..0000000
--- a/arch/arm/configs/omap_generic_1710_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig
deleted file mode 100644
index e2de2aa..0000000
--- a/arch/arm/configs/omap_h2_1610_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap_innovator_1510_defconfig b/arch/arm/configs/omap_innovator_1510_defconfig
deleted file mode 100644
index 265af26..0000000
--- a/arch/arm/configs/omap_innovator_1510_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap_innovator_1610_defconfig b/arch/arm/configs/omap_innovator_1610_defconfig
deleted file mode 100644
index cc7fbf8..0000000
--- a/arch/arm/configs/omap_innovator_1610_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap_osk_5912_defconfig b/arch/arm/configs/omap_osk_5912_defconfig
deleted file mode 100644
index 9105de7..0000000
--- a/arch/arm/configs/omap_osk_5912_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/omap_perseus2_730_defconfig b/arch/arm/configs/omap_perseus2_730_defconfig
deleted file mode 100644
index aa777e6..0000000
--- a/arch/arm/configs/omap_perseus2_730_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/palmte_defconfig b/arch/arm/configs/palmte_defconfig
deleted file mode 100644
index 828d7cb..0000000
--- a/arch/arm/configs/palmte_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/palmtt_defconfig b/arch/arm/configs/palmtt_defconfig
deleted file mode 100644
index 31d02c4..0000000
--- a/arch/arm/configs/palmtt_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/palmz71_defconfig b/arch/arm/configs/palmz71_defconfig
deleted file mode 100644
index c478db6..0000000
--- a/arch/arm/configs/palmz71_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/configs/sx1_defconfig b/arch/arm/configs/sx1_defconfig
deleted file mode 100644
index 20a8618..0000000
--- a/arch/arm/configs/sx1_defconfig
+++ /dev/null
@@ -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 --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 749bb66..bc2d2d7 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -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 --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
index 9d61220..75fe66b 100644
--- a/arch/arm/include/asm/cache.h
+++ b/arch/arm/include/asm/cache.h
@@ -23,4 +23,6 @@
 #define ARCH_SLAB_MINALIGN 8
 #endif
 
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
 #endif
diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h
index b56c138..765d332 100644
--- a/arch/arm/include/asm/clkdev.h
+++ b/arch/arm/include/asm/clkdev.h
@@ -12,23 +12,13 @@
 #ifndef __ASM_CLKDEV_H
 #define __ASM_CLKDEV_H
 
-struct clk;
-struct device;
+#include <linux/slab.h>
 
-struct clk_lookup {
-	struct list_head	node;
-	const char		*dev_id;
-	const char		*con_id;
-	struct clk		*clk;
-};
+#include <mach/clkdev.h>
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-	const char *dev_fmt, ...);
-
-void clkdev_add(struct clk_lookup *cl);
-void clkdev_drop(struct clk_lookup *cl);
-
-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 --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index c568da7..4fff837 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -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 @@
 	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 @@
 /*
  * 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 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 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_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 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_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 @@
 {
 	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 @@
 {
 	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 --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index cc7ef40..af18cea 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -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 --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 8bb66bc..c3cd875 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -99,6 +99,8 @@
 extern int elf_check_arch(const struct elf32_hdr *);
 #define elf_check_arch elf_check_arch
 
+#define vmcore_elf64_check_arch(x) (0)
+
 extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
 #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
 
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
new file mode 100644
index 0000000..ec0bbf7
--- /dev/null
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -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 --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 540a044..b33fe70 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -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 @@
 	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 --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index 6d7485a..89ad180 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -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 --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index cc42d5f..5aeec1e 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -59,7 +59,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 --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
new file mode 100644
index 0000000..c115b82
--- /dev/null
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/include/asm/hardware/entry-macro-gic.S
+ *
+ * Low-level IRQ helper macros for GIC
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/hardware/gic.h>
+
+#ifndef HAVE_GET_IRQNR_PREAMBLE
+	.macro	get_irqnr_preamble, base, tmp
+	ldr	\base, =gic_cpu_base_addr
+	ldr	\base, [\base]
+	.endm
+#endif
+
+/*
+ * The interrupt numbering scheme is defined in the
+ * interrupt controller spec.  To wit:
+ *
+ * Interrupts 0-15 are IPI
+ * 16-28 are reserved
+ * 29-31 are local.  We allow 30 to be used for the watchdog.
+ * 32-1020 are global
+ * 1021-1022 are reserved
+ * 1023 is "spurious" (no interrupt)
+ *
+ * For now, we ignore all local interrupts so only return an interrupt if it's
+ * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
+ *
+ * A simple read from the controller will tell us the number of the highest
+ * priority enabled interrupt.  We then just need to check whether it is in the
+ * valid range for an IRQ (30-1020 inclusive).
+ */
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+	/* bits 12-10 = src CPU, 9-0 = int # */
+
+	ldr	\tmp, =1021
+	bic     \irqnr, \irqstat, #0x1c00
+	cmp     \irqnr, #29
+	cmpcc	\irqnr, \irqnr
+	cmpne	\irqnr, \tmp
+	cmpcs	\irqnr, \irqnr
+	.endm
+
+/* We assume that irqstat (the raw value of the IRQ acknowledge
+ * register) is preserved from the macro above.
+ * If there is an IPI, we immediately signal end of interrupt on the
+ * controller, since this requires the original irqstat value which
+ * we won't easily be able to recreate later.
+ */
+
+	.macro test_for_ipi, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	cmp	\irqnr, #16
+	strcc	\irqstat, [\base, #GIC_CPU_EOI]
+	cmpcs	\irqnr, \irqnr
+	.endm
+
+/* As above, this assumes that irqstat and base are preserved.. */
+
+	.macro test_for_ltirq, irqnr, irqstat, base, tmp
+	bic	\irqnr, \irqstat, #0x1c00
+	mov 	\tmp, #0
+	cmp	\irqnr, #29
+	moveq	\tmp, #1
+	streq	\irqstat, [\base, #GIC_CPU_EOI]
+	cmp	\tmp, #0
+	.endm
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 7f34333b..84557d3 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,10 +33,13 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
-void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
-void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+extern void __iomem *gic_cpu_base_addr;
+
+void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
+void gic_enable_ppi(unsigned int);
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h
index 21fa272..b2f95c7 100644
--- a/arch/arm/include/asm/hardware/it8152.h
+++ b/arch/arm/include/asm/hardware/it8152.h
@@ -76,6 +76,7 @@
   IT8152_PD_IRQ(0)  Audio controller (ACR)
  */
 #define IT8152_IRQ(x)   (IRQ_BOARD_START + (x))
+#define IT8152_LAST_IRQ	(IRQ_BOARD_START + 40)
 
 /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
 #define IT8152_LD_IRQ_COUNT     9
diff --git a/arch/arm/plat-versatile/include/plat/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h
similarity index 100%
rename from arch/arm/plat-versatile/include/plat/timer-sp.h
rename to arch/arm/include/asm/hardware/timer-sp.h
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
index 1fc684e..7080e2c 100644
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -25,9 +25,6 @@
 extern void *kmap_high_get(struct page *page);
 extern void kunmap_high(struct page *page);
 
-extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte);
-extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte);
-
 /*
  * The following functions are already defined by <linux/highmem.h>
  * when CONFIG_HIGHMEM is not set.
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
index 4d8ae9d..f389b27 100644
--- a/arch/arm/include/asm/hw_breakpoint.h
+++ b/arch/arm/include/asm/hw_breakpoint.h
@@ -20,8 +20,8 @@
 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 --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 815efa2..20e0f7c 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -241,18 +241,15 @@
  *
  */
 #ifndef __arch_ioremap
-#define ioremap(cookie,size)		__arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_nocache(cookie,size)	__arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_cached(cookie,size)	__arm_ioremap(cookie, size, MT_DEVICE_CACHED)
-#define ioremap_wc(cookie,size)		__arm_ioremap(cookie, size, MT_DEVICE_WC)
-#define iounmap(cookie)			__iounmap(cookie)
-#else
+#define __arch_ioremap			__arm_ioremap
+#define __arch_iounmap			__iounmap
+#endif
+
 #define ioremap(cookie,size)		__arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)	__arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_cached(cookie,size)	__arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)		__arch_ioremap((cookie), (size), MT_DEVICE_WC)
-#define iounmap(cookie)			__arch_iounmap(cookie)
-#endif
+#define iounmap				__arch_iounmap
 
 /*
  * io{read,write}{8,16,32} macros
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index 8ec9ef5..c0094d8 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -33,10 +33,20 @@
 	if (oldregs) {
 		memcpy(newregs, oldregs, sizeof(*newregs));
 	} else {
-		__asm__ __volatile__ ("stmia %0, {r0 - r15}"
-				      : : "r" (&newregs->ARM_r0));
-		__asm__ __volatile__ ("mrs %0, cpsr"
-				      : "=r" (newregs->ARM_cpsr));
+		__asm__ __volatile__ (
+			"stmia	%[regs_base], {r0-r12}\n\t"
+			"mov	%[_ARM_sp], sp\n\t"
+			"str	lr, %[_ARM_lr]\n\t"
+			"adr	%[_ARM_pc], 1f\n\t"
+			"mrs	%[_ARM_cpsr], cpsr\n\t"
+		"1:"
+			: [_ARM_pc] "=r" (newregs->ARM_pc),
+			  [_ARM_cpsr] "=r" (newregs->ARM_cpsr),
+			  [_ARM_sp] "=r" (newregs->ARM_sp),
+			  [_ARM_lr] "=o" (newregs->ARM_lr)
+			: [regs_base] "r" (&newregs->ARM_r0)
+			: "memory"
+		);
 	}
 }
 
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
index 50c7e7c..6bc63ab 100644
--- a/arch/arm/include/asm/localtimer.h
+++ b/arch/arm/include/asm/localtimer.h
@@ -30,7 +30,6 @@
 #include "smp_twd.h"
 
 #define local_timer_ack()	twd_timer_ack()
-#define local_timer_stop()	twd_timer_stop()
 
 #else
 
@@ -40,11 +39,6 @@
  */
 int local_timer_ack(void);
 
-/*
- * Stop a local timer interrupt.
- */
-void local_timer_stop(void);
-
 #endif
 
 /*
@@ -52,12 +46,6 @@
  */
 void local_timer_setup(struct clock_event_device *);
 
-#else
-
-static inline void local_timer_stop(void)
-{
-}
-
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index d97a964..3a0893a 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -37,12 +37,21 @@
 					 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 --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index ce3eee9f..22ac140 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -17,10 +17,12 @@
 /*
  * 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 --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index 35d408f..883f6be 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -43,7 +43,6 @@
 #endif
 };
 
-extern struct sys_timer *system_timer;
 extern void timer_tick(void);
 
 #endif
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index cbb0bc2..12c8e68 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -8,11 +8,6 @@
 struct unwind_table;
 
 #ifdef CONFIG_ARM_UNWIND
-struct arm_unwind_mapping {
-	Elf_Shdr *unw_sec;
-	Elf_Shdr *sec_text;
-	struct unwind_table *unwind;
-};
 enum {
 	ARM_SEC_INIT,
 	ARM_SEC_DEVINIT,
@@ -21,14 +16,14 @@
 	ARM_SEC_DEVEXIT,
 	ARM_SEC_MAX,
 };
-struct mod_arch_specific {
-	struct arm_unwind_mapping map[ARM_SEC_MAX];
-};
-#else
-struct mod_arch_specific {
-};
 #endif
 
+struct mod_arch_specific {
+#ifdef CONFIG_ARM_UNWIND
+	struct unwind_table *unwind[ARM_SEC_MAX];
+#endif
+};
+
 /*
  * Include the ARM architecture version.
  */
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index a485ac3..f51a695 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -151,13 +151,15 @@
 #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 @@
 /*
  * .. 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 --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h
index b12cc98..9763be0 100644
--- a/arch/arm/include/asm/pgalloc.h
+++ b/arch/arm/include/asm/pgalloc.h
@@ -30,14 +30,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 +47,14 @@
  * 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 +62,8 @@
 	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 +79,8 @@
 	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 +92,8 @@
  */
 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 +102,10 @@
 	__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 +120,16 @@
 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 --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 53d1d5d..ebcb643 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -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
- * +- - - - + +4    |  h/w pt 0  |
- * |        |-----> +------------+ +1024
- * +--------+ +8    |  h/w pt 1  |
- * |        |       +------------+ +2048
+ * +--------+
+ * |        |       +------------+ +0
  * +- - - - +       | Linux pt 0 |
- * |        |       +------------+ +3072
- * +--------+       | Linux pt 1 |
+ * |        |       +------------+ +1024
+ * +--------+ +0    | Linux pt 1 |
+ * |        |-----> +------------+ +2048
+ * +- - - - + +4    |  h/w pt 0  |
+ * |        |-----> +------------+ +3072
+ * +--------+ +8    |  h/w pt 1  |
  * |        |       +------------+ +4096
  *
  * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
@@ -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 @@
  */
 #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 @@
  * 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 @@
 
 #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,94 +280,31 @@
 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];
 
-#define pte_offset_map(dir,addr)	(__pte_map(dir) + __pte_index(addr))
-#define pte_unmap(pte)			__pte_unmap(pte)
+/* to find an entry in a page-table-directory */
+#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
 
-#ifndef CONFIG_HIGHPTE
-#define __pte_map(dir)		pmd_page_vaddr(*(dir))
-#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))
-#endif
+#define pgd_offset(mm, addr)	((mm)->pgd + pgd_index(addr))
 
-#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
-
-#if __LINUX_ARM_ARCH__ < 6
-static inline void __sync_icache_dcache(pte_t pteval)
-{
-}
-#else
-extern void __sync_icache_dcache(pte_t pteval);
-#endif
-
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
-			      pte_t *ptep, pte_t pteval)
-{
-	if (addr >= TASK_SIZE)
-		set_pte_ext(ptep, pteval, 0);
-	else {
-		__sync_icache_dcache(pteval);
-		set_pte_ext(ptep, pteval, PTE_EXT_NG);
-	}
-}
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
 
 /*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
+ * 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 pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT)
-#define pte_write(pte)		(pte_val(pte) & L_PTE_WRITE)
-#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_special(pte)	(0)
+#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)
 
-#define pte_present_user(pte) \
-	((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
-	 (L_PTE_PRESENT | L_PTE_USER))
 
-#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(mkclean,   &= ~L_PTE_DIRTY);
-PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
-PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
-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
+/* 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))
@@ -364,12 +326,7 @@
 
 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);
+	return __va(pmd_val(pmd) & PAGE_MASK);
 }
 
 #define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
@@ -377,46 +334,81 @@
 /* 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)
+#ifndef CONFIG_HIGHPTE
+#define __pte_map(pmd)		pmd_page_vaddr(*(pmd))
+#define __pte_unmap(pte)	do { } while (0)
+#else
+#define __pte_map(pmd)		(pte_t *)kmap_atomic(pmd_page(*(pmd)))
+#define __pte_unmap(pte)	kunmap_atomic(pte)
+#endif
 
-/* to find an entry in a page-table-directory */
-#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
+#define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 
-#define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
+#define pte_offset_kernel(pmd,addr)	(pmd_page_vaddr(*(pmd)) + pte_index(addr))
 
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
+#define pte_offset_map(pmd,addr)	(__pte_map(pmd) + pte_index(addr))
+#define pte_unmap(pte)			__pte_unmap(pte)
 
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, addr)	((pmd_t *)(dir))
+#define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
+#define pfn_pte(pfn,prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
-/* Find an entry in the third-level page table.. */
-#define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#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)
+{
+}
+#else
+extern void __sync_icache_dcache(pte_t pteval);
+#endif
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pteval)
+{
+	if (addr >= TASK_SIZE)
+		set_pte_ext(ptep, pteval, 0);
+	else {
+		__sync_icache_dcache(pteval);
+		set_pte_ext(ptep, pteval, PTE_EXT_NG);
+	}
+}
+
+#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_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_XN))
+#define pte_special(pte)	(0)
+
+#define pte_present_user(pte) \
+	((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
+	 (L_PTE_PRESENT | L_PTE_USER))
+
+#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_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);
+PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
+
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
 
 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 @@
 
 #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 --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h
new file mode 100644
index 0000000..a84628b
--- /dev/null
+++ b/arch/arm/include/asm/sched_clock.h
@@ -0,0 +1,118 @@
+/*
+ * 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);
+	}
+}
+
+#endif
diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h
index 4fc1565..316bb2b 100644
--- a/arch/arm/include/asm/sizes.h
+++ b/arch/arm/include/asm/sizes.h
@@ -13,9 +13,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-/* DO NOT EDIT!! - this file automatically generated
- *                 from .s file by awk -f s2h.awk
- */
 /*  Size definitions
  *  Copyright (C) ARM Limited 1998. All rights reserved.
  */
@@ -25,6 +22,9 @@
 
 /* handy sizes */
 #define SZ_16				0x00000010
+#define SZ_32				0x00000020
+#define SZ_64				0x00000040
+#define SZ_128				0x00000080
 #define SZ_256				0x00000100
 #define SZ_512				0x00000200
 
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 3d05190..96ed521 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -33,27 +33,23 @@
 /*
  * 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 @@
 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 @@
 /*
  * 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 --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h
deleted file mode 100644
index 6a9307d..0000000
--- a/arch/arm/include/asm/smp_mpidr.h
+++ /dev/null
@@ -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 --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index 634f357..fed9981 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -22,7 +22,6 @@
 
 extern void __iomem *twd_base;
 
-void twd_timer_stop(void);
 int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
 
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 1120f18..97f6d60 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -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 @@
 #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")
@@ -150,6 +162,7 @@
 #define rmb()		dmb()
 #define wmb()		mb()
 #else
+#include <asm/memory.h>
 #define mb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
 #define rmb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
 #define wmb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index 491960b..1b960d5 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -15,16 +15,37 @@
 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 --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 33e4a48..b293616 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -227,7 +227,7 @@
 
 #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 @@
 
 #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 @@
 
 #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 @@
 
 #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 @@
 
 #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 --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5b9b268..185ee82 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -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_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_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 @@
 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 --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index bb96a7d..2b46fea 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -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 @@
 	@
 	@ 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 @@
 #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 @@
 	@
 	@ 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 @@
 #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 @@
  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 @@
 	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_memory_barrier:				@ 0xffff0fa0
-	smp_dmb
+	smp_dmb	arm
 	usr_ret	lr
 
 	.align	5
@@ -959,7 +943,7 @@
 
 #else
 
-	smp_dmb
+	smp_dmb	arm
 1:	ldrex	r3, [r2]
 	subs	r3, r3, r0
 	strexeq	r3, r1, [r2]
@@ -1245,3 +1229,9 @@
 	.space	4
 cr_no_alignment:
 	.space	4
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+	.globl	handle_arch_irq
+handle_arch_irq:
+	.space	4
+#endif
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 8bfa987..1e7b04a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -29,6 +29,9 @@
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
 	bne	fast_work_pending
+#if defined(CONFIG_IRQSOFF_TRACER)
+	asm_trace_hardirqs_on
+#endif
 
 	/* perform architecture specific actions before user return */
 	arch_ret_to_user r1, lr
@@ -65,6 +68,9 @@
 	tst	r1, #_TIF_WORK_MASK
 	bne	work_pending
 no_work_pending:
+#if defined(CONFIG_IRQSOFF_TRACER)
+	asm_trace_hardirqs_on
+#endif
 	/* perform architecture specific actions before user return */
 	arch_ret_to_user r1, lr
 
@@ -141,98 +147,170 @@
 #endif
 #endif
 
-#ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(__gnu_mcount_nc)
-	mov	ip, lr
-	ldmia	sp!, {lr}
-	mov	pc, ip
-ENDPROC(__gnu_mcount_nc)
-
-ENTRY(ftrace_caller)
-	stmdb	sp!, {r0-r3, lr}
-	mov	r0, lr
-	sub	r0, r0, #MCOUNT_INSN_SIZE
-	ldr	r1, [sp, #20]
-
-	.global	ftrace_call
-ftrace_call:
-	bl	ftrace_stub
-	ldmia	sp!, {r0-r3, ip, lr}
-	mov	pc, ip
-ENDPROC(ftrace_caller)
-
-#ifdef CONFIG_OLD_MCOUNT
-ENTRY(mcount)
-	stmdb	sp!, {lr}
-	ldr	lr, [fp, #-4]
-	ldmia	sp!, {pc}
-ENDPROC(mcount)
-
-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}
-ENDPROC(ftrace_caller_old)
-#endif
-
-#else
-
-ENTRY(__gnu_mcount_nc)
-	stmdb	sp!, {r0-r3, lr}
+.macro __mcount suffix
+	mcount_enter
 	ldr	r0, =ftrace_trace_function
 	ldr	r2, [r0]
 	adr	r0, .Lftrace_stub
 	cmp	r0, r2
-	bne	gnu_trace
-	ldmia	sp!, {r0-r3, ip, lr}
-	mov	pc, ip
+	bne	1f
 
-gnu_trace:
-	ldr	r1, [sp, #20]			@ lr of instrumented routine
-	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
-	adr	lr, BSYM(1f)
+	adr	lr, BSYM(2f)
 	mov	pc, r2
-1:
-	ldmia	sp!, {r0-r3, ip, lr}
-	mov	pc, ip
-ENDPROC(__gnu_mcount_nc)
+2:	mcount_exit
+.endm
+
+.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
+
+#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
 /*
- * 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.
+ * 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}
 
-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
+.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)
+	__ftrace_caller _old
+ENDPROC(ftrace_caller_old)
 #endif
 
-#endif /* CONFIG_DYNAMIC_FTRACE */
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller_old)
+	__ftrace_graph_caller
+ENDPROC(ftrace_graph_caller_old)
+#endif
+
+.purgem mcount_enter
+.purgem mcount_get_lr
+.purgem mcount_exit
+#endif
+
+/*
+ * __gnu_mcount_nc
+ */
+
+.macro mcount_enter
+	stmdb	sp!, {r0-r3, lr}
+.endm
+
+.macro mcount_get_lr reg
+	ldr	\reg, [sp, #20]
+.endm
+
+.macro mcount_exit
+	ldmia	sp!, {r0-r3, ip, lr}
+	mov	pc, ip
+.endm
+
+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_DYNAMIC_FTRACE
+ENTRY(ftrace_caller)
+	__ftrace_caller
+ENDPROC(ftrace_caller)
+#endif
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller)
+	__ftrace_graph_caller
+ENDPROC(ftrace_graph_caller)
+#endif
+
+.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 --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index d93f976..ae94649 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -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 --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index 6ff7919..e72dc34 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -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 *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 --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index 971ac8c..c0062ad 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -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 @@
 }
 #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 @@
 	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 @@
 
 	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 @@
 
 	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 --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 6bd82d25..f17d9a0 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -91,6 +91,11 @@
 	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
@@ -387,19 +392,19 @@
 
 #ifdef CONFIG_SMP_ON_UP
 __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?
+	mov	r4, #0x00070000
+	orr	r3, r4, #0xff000000	@ mask 0xff070000
+	orr	r4, r4, #0x41000000	@ val 0x41070000
+	and	r0, r9, r3
+	teq	r0, r4			@ ARM CPU and ARMv6/v7?
 	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?
+	orr	r3, r3, #0x0000ff00
+	orr	r3, r3, #0x000000f0	@ mask 0xff07fff0
+	orr	r4, r4, #0x0000b000
+	orr	r4, r4, #0x00000020	@ val 0x4107b020
+	and	r0, r9, r3
+	teq	r0, r4			@ ARM 11MPCore?
 	moveq	pc, lr			@ yes, assume SMP
 
 	mrc	p15, 0, r0, c0, c0, 5	@ read MPIDR
@@ -408,15 +413,22 @@
 
 __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
+2:	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	2b
 ENDPROC(__fixup_smp)
 
 	.align
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 21e3a4a..c9f3f04 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -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 @@
 
 /* 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 @@
 /* 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,94 @@
 	isb();
 }
 
+/* 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;
+}
+
+u8 arch_get_debug_arch(void)
+{
+	return debug_arch;
+}
+
+/* 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 +239,12 @@
 		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 +259,30 @@
 
 	/* 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)
+{
+	/*
+	 * 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 +296,6 @@
 	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 +315,6 @@
 }
 
 /*
- * 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 +322,41 @@
 	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 +374,11 @@
 		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 +393,15 @@
 	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 +418,6 @@
 	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 +551,23 @@
 		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 +586,7 @@
 {
 	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 +596,85 @@
 	/* 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;
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
 
-	if (bp == NULL)
-		return;
+	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);
+}
 
-	info = counter_arch_bp(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,87 +684,121 @@
 		 * 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();
+	}
+}
+
 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 +813,47 @@
 		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 *unused)
 {
 	int i;
 
+	/*
+	 * 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 write to 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) {
+		/*
+		 * 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 +864,57 @@
 	}
 }
 
+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;
 
 	debug_arch = get_debug_arch();
 
 	if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
 		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);
 
 	ARM_DBG_READ(c1, 0, dscr);
 	if (dscr & ARM_DSCR_HDBGEN) {
 		pr_warning("halting debug mode enabled. Assuming maximum "
 				"watchpoint size of 4 bytes.");
 	} 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);
+
+		/* 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);
 	}
 
 	/* Register debug fault handler. */
@@ -829,8 +923,9 @@
 	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 --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 36ad3be..8135438 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -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 @@
 	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,7 +85,7 @@
 		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 ? : "-");
@@ -89,13 +98,15 @@
 		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 @@
  * 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 __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
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index b63b528..7fa3bb0 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -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 @@
 	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_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 @@
 	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 --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 3a8fd514..30ead13 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -23,6 +23,8 @@
 extern unsigned long kexec_mach_type;
 extern unsigned long kexec_boot_atags;
 
+static atomic_t waiting_for_crash_ipi;
+
 /*
  * Provide a dummy crash_notes definition while crash dump arrives to arm.
  * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -37,9 +39,37 @@
 {
 }
 
+void machine_crash_nonpanic_core(void *unused)
+{
+	struct pt_regs regs;
+
+	crash_setup_regs(&regs, NULL);
+	printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
+	       smp_processor_id());
+	crash_save_cpu(&regs, smp_processor_id());
+	flush_cache_all();
+
+	atomic_dec(&waiting_for_crash_ipi);
+	while (1)
+		cpu_relax();
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
+	unsigned long msecs;
+
 	local_irq_disable();
+
+	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+	smp_call_function(machine_crash_nonpanic_core, NULL, false);
+	msecs = 1000; /* Wait at most a second for the other cpus to stop */
+	while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+		mdelay(1);
+		msecs--;
+	}
+	if (atomic_read(&waiting_for_crash_ipi) > 0)
+		printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
+
 	crash_save_cpu(regs, smp_processor_id());
 
 	printk(KERN_INFO "Loading crashdump kernel...\n");
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index d9bd786..0c1bb68 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -67,35 +67,6 @@
 			      char *secstrings,
 			      struct module *mod)
 {
-#ifdef CONFIG_ARM_UNWIND
-	Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
-	struct arm_unwind_mapping *maps = mod->arch.map;
-
-	for (s = sechdrs; s < sechdrs_end; s++) {
-		char const *secname = secstrings + s->sh_name;
-
-		if (strcmp(".ARM.exidx.init.text", secname) == 0)
-			maps[ARM_SEC_INIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
-			maps[ARM_SEC_DEVINIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx", secname) == 0)
-			maps[ARM_SEC_CORE].unw_sec = s;
-		else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
-			maps[ARM_SEC_EXIT].unw_sec = s;
-		else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
-			maps[ARM_SEC_DEVEXIT].unw_sec = s;
-		else if (strcmp(".init.text", secname) == 0)
-			maps[ARM_SEC_INIT].sec_text = s;
-		else if (strcmp(".devinit.text", secname) == 0)
-			maps[ARM_SEC_DEVINIT].sec_text = s;
-		else if (strcmp(".text", secname) == 0)
-			maps[ARM_SEC_CORE].sec_text = s;
-		else if (strcmp(".exit.text", secname) == 0)
-			maps[ARM_SEC_EXIT].sec_text = s;
-		else if (strcmp(".devexit.text", secname) == 0)
-			maps[ARM_SEC_DEVEXIT].sec_text = s;
-	}
-#endif
 	return 0;
 }
 
@@ -300,41 +271,69 @@
 	return -ENOEXEC;
 }
 
+struct mod_unwind_map {
+	const Elf_Shdr *unw_sec;
+	const Elf_Shdr *txt_sec;
+};
+
+int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+		    struct module *mod)
+{
 #ifdef CONFIG_ARM_UNWIND
-static void register_unwind_tables(struct module *mod)
-{
+	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+	const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+	struct mod_unwind_map maps[ARM_SEC_MAX];
 	int i;
-	for (i = 0; i < ARM_SEC_MAX; ++i) {
-		struct arm_unwind_mapping *map = &mod->arch.map[i];
-		if (map->unw_sec && map->sec_text)
-			map->unwind = unwind_table_add(map->unw_sec->sh_addr,
-						       map->unw_sec->sh_size,
-						       map->sec_text->sh_addr,
-						       map->sec_text->sh_size);
+
+	memset(maps, 0, sizeof(maps));
+
+	for (s = sechdrs; s < sechdrs_end; s++) {
+		const char *secname = secstrs + s->sh_name;
+
+		if (!(s->sh_flags & SHF_ALLOC))
+			continue;
+
+		if (strcmp(".ARM.exidx.init.text", secname) == 0)
+			maps[ARM_SEC_INIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx", secname) == 0)
+			maps[ARM_SEC_CORE].unw_sec = s;
+		else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].unw_sec = s;
+		else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].unw_sec = s;
+		else if (strcmp(".init.text", secname) == 0)
+			maps[ARM_SEC_INIT].txt_sec = s;
+		else if (strcmp(".devinit.text", secname) == 0)
+			maps[ARM_SEC_DEVINIT].txt_sec = s;
+		else if (strcmp(".text", secname) == 0)
+			maps[ARM_SEC_CORE].txt_sec = s;
+		else if (strcmp(".exit.text", secname) == 0)
+			maps[ARM_SEC_EXIT].txt_sec = s;
+		else if (strcmp(".devexit.text", secname) == 0)
+			maps[ARM_SEC_DEVEXIT].txt_sec = s;
 	}
-}
 
-static void unregister_unwind_tables(struct module *mod)
-{
-	int i = ARM_SEC_MAX;
-	while (--i >= 0)
-		unwind_table_del(mod->arch.map[i].unwind);
-}
-#else
-static inline void register_unwind_tables(struct module *mod) { }
-static inline void unregister_unwind_tables(struct module *mod) { }
+	for (i = 0; i < ARM_SEC_MAX; i++)
+		if (maps[i].unw_sec && maps[i].txt_sec)
+			mod->arch.unwind[i] =
+				unwind_table_add(maps[i].unw_sec->sh_addr,
+					         maps[i].unw_sec->sh_size,
+					         maps[i].txt_sec->sh_addr,
+					         maps[i].txt_sec->sh_size);
 #endif
-
-int
-module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
-		struct module *module)
-{
-	register_unwind_tables(module);
 	return 0;
 }
 
 void
 module_arch_cleanup(struct module *mod)
 {
-	unregister_unwind_tables(mod);
+#ifdef CONFIG_ARM_UNWIND
+	int i;
+
+	for (i = 0; i < ARM_SEC_MAX; i++)
+		if (mod->arch.unwind[i])
+			unwind_table_del(mod->arch.unwind[i]);
+#endif
 }
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 07a5035..5efa264 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -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 @@
  * 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 @@
 	 */
 	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 @@
 
 #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 @@
 	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 @@
 }
 
 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 @@
 
 	/* 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 @@
 	.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 @@
 		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 @@
 		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 @@
  * 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;
@@ -3089,10 +709,10 @@
 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 --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
new file mode 100644
index 0000000..c058bfc
--- /dev/null
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -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 --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
new file mode 100644
index 0000000..2e14025
--- /dev/null
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -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 --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
new file mode 100644
index 0000000..28cd3b0
--- /dev/null
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -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 --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c
new file mode 100644
index 0000000..a4b1b07
--- /dev/null
+++ b/arch/arm/kernel/pj4-cp0.c
@@ -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 --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 3e97483..19c6816 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -1060,8 +1060,8 @@
 			goto out;
 
 		if ((gen_type & implied_type) != gen_type) {
-				ret = -EINVAL;
-				goto out;
+			ret = -EINVAL;
+			goto out;
 		}
 
 		attr.bp_len	= gen_len;
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
new file mode 100644
index 0000000..2cdcc92
--- /dev/null
+++ b/arch/arm/kernel/sched_clock.c
@@ -0,0 +1,69 @@
+/*
+ * 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, 60);
+
+	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));
+	sched_clock_poll(sched_clock_timer.data);
+
+	/*
+	 * Ensure that sched_clock() starts off at 0ns
+	 */
+	cd->epoch_ns = 0;
+}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 336f14e..3455ad3 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -75,9 +75,9 @@
 
 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 @@
 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 @@
 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' } };
@@ -708,13 +709,11 @@
 	{ 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 +808,7 @@
 
 	setup_processor();
 	mdesc = setup_machine(machine_arch_type);
+	machine_desc = mdesc;
 	machine_name = mdesc->name;
 
 	if (mdesc->soft_reboot)
@@ -868,13 +868,9 @@
 	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 +880,9 @@
 #endif
 #endif
 	early_trap_init();
+
+	if (mdesc->init_early)
+		mdesc->init_early();
 }
 
 
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8c19595..4539ebc 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -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 @@
 			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 @@
 
 	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 @@
 	/*
 	 * 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 @@
 	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 @@
 {
 	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 @@
 	 * 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 @@
 #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.
  */
@@ -310,7 +284,6 @@
 	 * All kernel threads share the same mm context; grab a
 	 * reference and switch to it.
 	 */
-	atomic_inc(&mm->mm_users);
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
@@ -320,6 +293,7 @@
 
 	cpu_init();
 	preempt_disable();
+	trace_hardirqs_off();
 
 	/*
 	 * Give the platform a chance to do its own initialisation.
@@ -353,17 +327,6 @@
 	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;
@@ -386,61 +349,80 @@
 	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;
+	unsigned int ncores = num_possible_cpus();
 
-	local_irq_save(flags);
-
-	for_each_cpu(cpu, mask) {
-		struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-
-		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;
 }
 
 /*
@@ -457,24 +439,36 @@
 }
 
 #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
@@ -511,6 +505,21 @@
 	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);
 
 /*
@@ -537,85 +546,70 @@
 
 /*
  * 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++;
+	if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
+		__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
 
-	for (;;) {
-		unsigned long msgs;
+	switch (ipinr) {
+	case IPI_TIMER:
+		ipi_timer();
+		break;
 
-		spin_lock(&ipi->lock);
-		msgs = ipi->bits;
-		ipi->bits = 0;
-		spin_unlock(&ipi->lock);
+	case IPI_RESCHEDULE:
+		/*
+		 * nothing more to do - eveything is
+		 * done on the interrupt return path
+		 */
+		break;
 
-		if (!msgs)
-			break;
+	case IPI_CALL_FUNC:
+		generic_smp_call_function_interrupt();
+		break;
 
-		do {
-			unsigned nextmsg;
+	case IPI_CALL_FUNC_SINGLE:
+		generic_smp_call_function_single_interrupt();
+		break;
 
-			nextmsg = msgs & -msgs;
-			msgs &= ~nextmsg;
-			nextmsg = ffz(~nextmsg);
+	case IPI_CPU_STOP:
+		ipi_cpu_stop(cpu);
+		break;
 
-			switch (nextmsg) {
-			case IPI_TIMER:
-				ipi_timer();
-				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_SINGLE:
-				generic_smp_call_function_single_interrupt();
-				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;
+
+	if (num_online_cpus() > 1) {
+		cpumask_t mask = cpu_online_map;
+		cpu_clear(smp_processor_id(), mask);
+
+		smp_cross_call(&mask, IPI_CPU_STOP);
+	}
+
+	/* Wait up to one second for other CPUs to stop */
+	timeout = USEC_PER_SEC;
+	while (num_online_cpus() > 1 && timeout--)
+		udelay(1);
+
+	if (num_online_cpus() > 1)
+		pr_warning("SMP: failed to stop secondary CPUs\n");
 }
 
 /*
@@ -625,128 +619,3 @@
 {
 	return -EINVAL;
 }
-
-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 --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
new file mode 100644
index 0000000..7dcb352
--- /dev/null
+++ b/arch/arm/kernel/smp_tlb.c
@@ -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 --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 35882fb..dd79074 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -127,8 +127,6 @@
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
-	unsigned long flags;
-
 	twd_calibrate_rate();
 
 	clk->name = "local_timer";
@@ -143,20 +141,7 @@
 	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
 	/* Make sure our local interrupt controller has this enabled */
-	local_irq_save(flags);
-	irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
-	get_irq_chip(clk->irq)->unmask(clk->irq);
-	local_irq_restore(flags);
+	gic_enable_ppi(clk->irq);
 
 	clockevents_register_device(clk);
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * take a local timer down
- */
-void twd_timer_stop(void)
-{
-	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-}
-#endif
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
new file mode 100644
index 0000000..7a576092
--- /dev/null
+++ b/arch/arm/kernel/swp_emulate.c
@@ -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 --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 38c261f..f1e2eb1 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -30,12 +30,13 @@
 #include <asm/leds.h>
 #include <asm/thread_info.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 +161,7 @@
 
 void __init time_init(void)
 {
+	system_timer = machine_desc->timer;
 	system_timer->init();
 }
 
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 446aee9..ee57640 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -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 @@
 }
 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 @@
 
 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 @@
 	 * 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 --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index cead889..86b66f3 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -101,6 +101,7 @@
 			__exception_text_start = .;
 			*(.exception.text)
 			__exception_text_end = .;
+			IRQENTRY_TEXT
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
@@ -167,6 +168,7 @@
 
 		NOSAVE_DATA
 		CACHELINE_ALIGNED_DATA(32)
+		READ_MOSTLY_DATA(32)
 
 		/*
 		 * The exception fixup table (might need resorting at runtime)
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index b1631a7..1b049cd 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -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 @@
 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 --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 5a01a23..c023fc1 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -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 @@
 	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 @@
 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 --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
index fee9f6f..d0ece2a 100644
--- a/arch/arm/lib/uaccess.S
+++ b/arch/arm/lib/uaccess.S
@@ -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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 .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 @@
 .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 @@
 		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 @@
 
 .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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 2500f41..1dd69c8 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -101,7 +101,6 @@
 	.rating		= 150,
 	.read		= read_clk32k,
 	.mask		= CLOCKSOURCE_MASK(20),
-	.shift		= 10,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -201,8 +200,7 @@
 	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 --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 608a632..4ba8549 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -51,7 +51,6 @@
 	.name		= "pit",
 	.rating		= 175,
 	.read		= read_pit_clk,
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -163,10 +162,9 @@
 	 * 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 --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h
index 57f8ee1..27ac6f5 100644
--- a/arch/arm/mach-at91/include/mach/at91_mci.h
+++ b/arch/arm/mach-at91/include/mach/at91_mci.h
@@ -74,6 +74,8 @@
 #define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
 #define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
 #define			AT91_MCI_TRTYP_STREAM	(2 << 19)
+#define			AT91_MCI_TRTYP_SDIO_BYTE	(4 << 19)
+#define			AT91_MCI_TRTYP_SDIO_BLOCK	(5 << 19)
 
 #define AT91_MCI_BLKR		0x18		/* Block Register */
 #define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */
diff --git a/arch/arm/mach-bcmring/clock.c b/arch/arm/mach-bcmring/clock.c
index 14bafc3..ad237a4 100644
--- a/arch/arm/mach-bcmring/clock.c
+++ b/arch/arm/mach-bcmring/clock.c
@@ -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 --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c
index d3f959e..8fc2035 100644
--- a/arch/arm/mach-bcmring/core.c
+++ b/arch/arm/mach-bcmring/core.c
@@ -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 @@
 	.rating = 200,
 	.read = bcmring_get_cycles_timer1,
 	.mask = CLOCKSOURCE_MASK(32),
-	.shift = 20,
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -303,7 +302,6 @@
 	.rating = 100,
 	.read = bcmring_get_cycles_timer3,
 	.mask = CLOCKSOURCE_MASK(32),
-	.shift = 20,
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -316,10 +314,8 @@
 	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 @@
 	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 --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig
index 9ebfcc4..29b13f2 100644
--- a/arch/arm/mach-cns3xxx/Kconfig
+++ b/arch/arm/mach-cns3xxx/Kconfig
@@ -3,6 +3,7 @@
 
 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 --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 90fe9ab..08e5c87 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -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 @@
 }
 
 /*
+ * 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 --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 9ca4d58..da30078 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -69,13 +69,10 @@
 }
 
 /* used by entry-macro.S */
-void __iomem *gic_cpu_base_addr;
-
 void __init cns3xxx_init_irq(void)
 {
-	gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT);
-	gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
+		 __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
 }
 
 void cns3xxx_power_off(void)
diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h
index 6b33ec1..ffeb3a8 100644
--- a/arch/arm/mach-cns3xxx/core.h
+++ b/arch/arm/mach-cns3xxx/core.h
@@ -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 --git a/arch/arm/mach-cns3xxx/devices.c b/arch/arm/mach-cns3xxx/devices.c
index 50b4d31..79d1fb0 100644
--- a/arch/arm/mach-cns3xxx/devices.c
+++ b/arch/arm/mach-cns3xxx/devices.c
@@ -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 --git a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
index 6dbce13..191c8e5 100644
--- a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
+++ b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
@@ -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 --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
index 5e1c554..6bd83ed 100644
--- a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
+++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
@@ -9,74 +9,10 @@
  */
 
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
 
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff --git a/arch/arm/mach-cns3xxx/include/mach/pm.h b/arch/arm/mach-cns3xxx/include/mach/pm.h
new file mode 100644
index 0000000..6eae7f7
--- /dev/null
+++ b/arch/arm/mach-cns3xxx/include/mach/pm.h
@@ -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 --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c
index 38e4470..5e57955 100644
--- a/arch/arm/mach-cns3xxx/pm.c
+++ b/arch/arm/mach-cns3xxx/pm.c
@@ -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 @@
 	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 @@
 	/* 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 @@
 	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 @@
 		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 @@
 	}
 	cns3xxx_pwr_soft_rst_force(block);
 }
+EXPORT_SYMBOL(cns3xxx_pwr_soft_rst);
 
 void arch_reset(char mode, const char *cmd)
 {
@@ -99,3 +118,7 @@
 
 	return cpu;
 }
+EXPORT_SYMBOL(cns3xxx_cpu_clock);
+
+atomic_t usb_pwr_ref = ATOMIC_INIT(0);
+EXPORT_SYMBOL(usb_pwr_ref);
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index b77b860..32f1479 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -61,6 +61,8 @@
 	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_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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 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_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 --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
index 9c3f500..1ce70a9 100644
--- a/arch/arm/mach-davinci/aemif.c
+++ b/arch/arm/mach-davinci/aemif.c
@@ -90,7 +90,7 @@
 					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 --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index c6e11c6..b01fb2a 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -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 @@
 	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 @@
 	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 @@
 
 	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 @@
 static int da850_evm_ui_expander_teardown(struct i2c_client *client,
 					unsigned gpio, unsigned ngpio, void *c)
 {
-	/* deselect all functionalities */
-	gpio_set_value(gpio + 5, 1);
-	gpio_set_value(gpio + 6, 1);
-	gpio_set_value(gpio + 7, 1);
+	platform_device_unregister(&da850_evm_ui_keys_device);
 
-	gpio_free(gpio + 5);
-	gpio_free(gpio + 6);
-	gpio_free(gpio + 7);
+	/* deselect all functionalities */
+	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 + 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 @@
 	.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 @@
 		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 @@
 	{
 		.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 @@
 	.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 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 @@
 	&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 @@
 	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 --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 01ba080..e4e3af1 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -336,7 +336,7 @@
 		ratio--;
 	}
 
-	if (ratio > PLLDIV_RATIO_MASK)
+	if (ratio > pll->div_ratio_mask)
 		return -EINVAL;
 
 	do {
@@ -344,7 +344,7 @@
 	} 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 --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index 1109998..0dd2203 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -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 --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 63916b9..78b5ae2 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -830,8 +830,7 @@
  * 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 @@
 	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 struct cpufreq_frequency_table da850_freq_table[] = {
+	OPP(456),
+	OPP(408),
+	OPP(372),
 	OPP(300),
 	OPP(200),
 	OPP(96),
@@ -886,6 +915,19 @@
 };
 
 #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 @@
 	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 @@
 }
 #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 @@
 	.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 @@
 {
 	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 @@
 	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 --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index c9a86d8..85503deb 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -344,7 +344,20 @@
 
 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 --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 2652af1..a5f8a80 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -412,12 +412,7 @@
 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 --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index c466d71..02d2cc3 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -625,12 +625,6 @@
 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 --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index 4247b3f..e7f9520 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -28,6 +28,13 @@
 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 --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h
index 62b0a90..d1b9549 100644
--- a/arch/arm/mach-davinci/include/mach/io.h
+++ b/arch/arm/mach-davinci/include/mach/io.h
@@ -22,8 +22,8 @@
 #define __mem_isa(a)		(a)
 
 #ifndef __ASSEMBLER__
-#define __arch_ioremap(p, s, t)	davinci_ioremap(p, s, t)
-#define __arch_iounmap(v)	davinci_iounmap(v)
+#define __arch_ioremap		davinci_ioremap
+#define __arch_iounmap		davinci_iounmap
 
 void __iomem *davinci_ioremap(unsigned long phys, size_t size,
 			      unsigned int type);
diff --git a/arch/arm/mach-davinci/include/mach/spi.h b/arch/arm/mach-davinci/include/mach/spi.h
index 910efbf..38f4da5 100644
--- a/arch/arm/mach-davinci/include/mach/spi.h
+++ b/arch/arm/mach-davinci/include/mach/spi.h
@@ -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 --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index 1b15dbd..a415804 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -83,21 +83,16 @@
 		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 --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 0f21c36..e1969ce 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -272,15 +272,35 @@
 	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 @@
 	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 --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c
index daeae06..6fcdece 100644
--- a/arch/arm/mach-davinci/tnetv107x.c
+++ b/arch/arm/mach-davinci/tnetv107x.c
@@ -131,12 +131,13 @@
 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(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(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 @@
 	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 @@
 	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 --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index 31f0cbe..23d2b6d 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -64,17 +64,19 @@
 	{
 		.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 @@
 	{
 		.start		= IRQ_DA8XX_USB_INT,
 		.flags		= IORESOURCE_IRQ,
+		.name		= "mc",
 	},
 };
 
@@ -121,6 +124,7 @@
 
 	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 --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig
index 3b9a32a..a4ed390 100644
--- a/arch/arm/mach-dove/Kconfig
+++ b/arch/arm/mach-dove/Kconfig
@@ -9,6 +9,12 @@
 	  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 --git a/arch/arm/mach-dove/Makefile b/arch/arm/mach-dove/Makefile
index 7ab3be5..fa0f018 100644
--- a/arch/arm/mach-dove/Makefile
+++ b/arch/arm/mach-dove/Makefile
@@ -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 --git a/arch/arm/mach-dove/cm-a510.c b/arch/arm/mach-dove/cm-a510.c
new file mode 100644
index 0000000..96e0e94
--- /dev/null
+++ b/arch/arm/mach-dove/cm-a510.c
@@ -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 --git a/arch/arm/mach-dove/include/mach/dove.h b/arch/arm/mach-dove/include/mach/dove.h
index f6a0839..27b4145 100644
--- a/arch/arm/mach-dove/include/mach/dove.h
+++ b/arch/arm/mach-dove/include/mach/dove.h
@@ -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 --git a/arch/arm/mach-dove/include/mach/gpio.h b/arch/arm/mach-dove/include/mach/gpio.h
index 0ee70ff..340bb7a 100644
--- a/arch/arm/mach-dove/include/mach/gpio.h
+++ b/arch/arm/mach-dove/include/mach/gpio.h
@@ -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 --git a/arch/arm/mach-dove/mpp.c b/arch/arm/mach-dove/mpp.c
new file mode 100644
index 0000000..71db2bd
--- /dev/null
+++ b/arch/arm/mach-dove/mpp.c
@@ -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 --git a/arch/arm/mach-dove/mpp.h b/arch/arm/mach-dove/mpp.h
new file mode 100644
index 0000000..2a43ce4
--- /dev/null
+++ b/arch/arm/mach-dove/mpp.h
@@ -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 --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index ef06c66..ca4de71 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -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 --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 197f9e2..17d2e60 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -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 @@
 
 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 @@
 
 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 @@
 
 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 @@
 	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 @@
 
 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_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 @@
 
 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,26 @@
 
 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_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 +262,7 @@
 
 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 +270,17 @@
 
 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 +289,11 @@
 
 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 --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 5582692..77100bf 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -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_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 --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
index 7988a85..3953d60 100644
--- a/arch/arm/mach-imx/Makefile.boot
+++ b/arch/arm/mach-imx/Makefile.boot
@@ -6,6 +6,10 @@
 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 --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index daca30b..3938a56 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -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 --git a/arch/arm/mach-imx/clock-imx21.c b/arch/arm/mach-imx/clock-imx21.c
index cf15ea5..bf30a8c 100644
--- a/arch/arm/mach-imx/clock-imx21.c
+++ b/arch/arm/mach-imx/clock-imx21.c
@@ -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 @@
 	_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 --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c
new file mode 100644
index 0000000..daa0165
--- /dev/null
+++ b/arch/arm/mach-imx/clock-imx25.c
@@ -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 --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 98a25ba..583f251 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -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 @@
 	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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 	 * 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 @@
 	/* 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 @@
 	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 @@
 {
 	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 @@
 {
 	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 @@
 	_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 @@
 {
 	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 --git a/arch/arm/mach-imx/cpu-imx27.c b/arch/arm/mach-imx/cpu-imx27.c
index d8d3b2d..3b117be 100644
--- a/arch/arm/mach-imx/cpu-imx27.c
+++ b/arch/arm/mach-imx/cpu-imx27.c
@@ -42,7 +42,19 @@
 	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 --git a/arch/arm/mach-imx/devices-imx21.h b/arch/arm/mach-imx/devices-imx21.h
index d189039..16744d2 100644
--- a/arch/arm/mach-imx/devices-imx21.h
+++ b/arch/arm/mach-imx/devices-imx21.h
@@ -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 @@
 #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 --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h
new file mode 100644
index 0000000..bde33ca
--- /dev/null
+++ b/arch/arm/mach-imx/devices-imx25.h
@@ -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 --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h
index 7011690..f1272d4 100644
--- a/arch/arm/mach-imx/devices-imx27.h
+++ b/arch/arm/mach-imx/devices-imx27.h
@@ -13,10 +13,26 @@
 #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 @@
 #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 --git a/arch/arm/mach-imx/devices.c b/arch/arm/mach-imx/devices.c
deleted file mode 100644
index fba5047..0000000
--- a/arch/arm/mach-imx/devices.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-imx/devices.h b/arch/arm/mach-imx/devices.h
deleted file mode 100644
index 807f02a..0000000
--- a/arch/arm/mach-imx/devices.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
index 3e8c47c..e9f1769 100644
--- a/arch/arm/mach-imx/dma-v1.c
+++ b/arch/arm/mach-imx/dma-v1.c
@@ -818,9 +818,11 @@
 		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 --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 7e1e9dc..275c858 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -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 @@
 	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_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 @@
 	&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 @@
 	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 @@
 	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 --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
new file mode 100644
index 0000000..cb705c2
--- /dev/null
+++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
@@ -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 --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 745ee60..6cf04da 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -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 @@
 
 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 @@
 #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 @@
 
 	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 @@
 		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 --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
new file mode 100644
index 0000000..eb395ab
--- /dev/null
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -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 --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 59716fa..40a3666 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -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 @@
 	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 @@
 	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 @@
 				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 --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index bbdbc75..3a1202e 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -25,7 +25,6 @@
 #include <mach/iomux-mx27.h>
 
 #include "devices-imx27.h"
-#include "devices.h"
 
 static const int mx27lite_pins[] __initconst = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 6187ce9..1f446e5 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -30,7 +30,6 @@
 #include <mach/irqs.h>
 
 #include "devices-imx1.h"
-#include "devices.h"
 
 static const int mx1ads_pins[] __initconst = {
 	/* UART1 */
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index e1282e9..0a37257 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -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_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_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 @@
 	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 @@
 	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 --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
new file mode 100644
index 0000000..aa76cfd
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -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 __initdata = {
+	.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 --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 84a5ba03..6fd0f8f 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -22,20 +22,27 @@
 
 #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 "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)
 
 static const int mx27pdk_pins[] __initconst = {
 	/* UART1 */
@@ -70,6 +77,24 @@
 	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 +117,7 @@
 	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 +134,7 @@
 	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 +146,111 @@
 	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_REGU_VMMC1,
+		.init_data = &vmmc1_init,
+	}, {
+		.id = MC13783_REGU_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 +258,24 @@
 	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));
 }
 
 static void __init mx27pdk_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index a1e4bc5..b832f96 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -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_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 @@
 	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 @@
 	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 --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index 38d3a4a..4ce71b0 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -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_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 @@
 	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 @@
 
 	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 --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index 8c720d4..cccc0a0 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -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 @@
 	.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 @@
 	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 @@
 	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 @@
 	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_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 @@
 
 	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 @@
 		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 --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 49a97ce..f667a26 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -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 @@
 
 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 struct regulator_consumer_supply sdhc1_consumers[] = {
 	{
-		.dev	= &mxc_sdhc_device1.dev,
+		.dev_name = "mxc-mmc.1",
 		.supply	= "sdhc_vcc",
 	},
 };
@@ -285,7 +281,7 @@
 	}
 };
 
-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 @@
 	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 --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index 1fbdd3f..eae878f 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -25,7 +25,6 @@
 #include <mach/iomux-mx1.h>
 
 #include "devices-imx1.h"
-#include "devices.h"
 
 /*
  * This scb9328 has a 32MiB flash
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 9be92b9..729ae09 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -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 --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index 12faeeaa..e728af8 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -35,33 +35,18 @@
 	 * - 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 --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
new file mode 100644
index 0000000..2edec6c
--- /dev/null
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -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 --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index a246229..374e48b 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -35,33 +35,18 @@
 	 * - 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 --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
index 9110d9c..99afbc3 100644
--- a/arch/arm/mach-imx/pcm970-baseboard.c
+++ b/arch/arm/mach-imx/pcm970-baseboard.c
@@ -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 @@
 	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_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 @@
 	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 --git a/arch/arm/mach-imx/pm-imx27.c b/arch/arm/mach-imx/pm-imx27.c
index afc17ce..6bf81ce 100644
--- a/arch/arm/mach-imx/pm-imx27.c
+++ b/arch/arm/mach-imx/pm-imx27.c
@@ -39,6 +39,9 @@
 
 static int __init mx27_pm_init(void)
 {
+	if (!cpu_is_mx27())
+		return 0;
+
 	suspend_set_ops(&mx27_suspend_ops);
 	return 0;
 }
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index 27db275..769b0f1 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -4,6 +4,7 @@
 
 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 --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 8f4fb6d..b8e884b 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -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 --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index fd684bf2..5db574f 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -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 --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 548208f..2774df8 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -372,7 +372,6 @@
 	.rating		= 200,
 	.read		= timersp_read,
 	.mask		= CLOCKSOURCE_MASK(16),
-	.shift		= 16,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -390,8 +389,7 @@
 	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 --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 6258c90..85e48a5 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -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"
 
diff --git a/arch/arm/mach-iop13xx/include/mach/io.h b/arch/arm/mach-iop13xx/include/mach/io.h
index a6e0f9e..dffb234 100644
--- a/arch/arm/mach-iop13xx/include/mach/io.h
+++ b/arch/arm/mach-iop13xx/include/mach/io.h
@@ -35,7 +35,7 @@
 extern size_t iop13xx_atue_mem_size;
 extern size_t iop13xx_atux_mem_size;
 
-#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop13xx_iounmap(a)
+#define __arch_ioremap	__iop13xx_ioremap
+#define __arch_iounmap	__iop13xx_iounmap
 
 #endif
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h
index 7415e43..3ad4553 100644
--- a/arch/arm/mach-iop13xx/include/mach/memory.h
+++ b/arch/arm/mach-iop13xx/include/mach/memory.h
@@ -58,13 +58,13 @@
 		__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 --git a/arch/arm/mach-iop32x/include/mach/io.h b/arch/arm/mach-iop32x/include/mach/io.h
index 339e585..059c783 100644
--- a/arch/arm/mach-iop32x/include/mach/io.h
+++ b/arch/arm/mach-iop32x/include/mach/io.h
@@ -21,7 +21,7 @@
 #define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
+#define __arch_ioremap	__iop3xx_ioremap
+#define __arch_iounmap	__iop3xx_iounmap
 
 #endif
diff --git a/arch/arm/mach-iop33x/include/mach/io.h b/arch/arm/mach-iop33x/include/mach/io.h
index e99a7ed..39e893e 100644
--- a/arch/arm/mach-iop33x/include/mach/io.h
+++ b/arch/arm/mach-iop33x/include/mach/io.h
@@ -21,7 +21,7 @@
 #define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)		(a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)	 __iop3xx_iounmap(a)
+#define __arch_ioremap	__iop3xx_ioremap
+#define __arch_iounmap	__iop3xx_iounmap
 
 #endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/io.h b/arch/arm/mach-ixp23xx/include/mach/io.h
index fd9ef8e..a1749d0 100644
--- a/arch/arm/mach-ixp23xx/include/mach/io.h
+++ b/arch/arm/mach-ixp23xx/include/mach/io.h
@@ -45,8 +45,8 @@
 	__iounmap(addr);
 }
 
-#define __arch_ioremap(a,s,f)	ixp23xx_ioremap(a,s,f)
-#define __arch_iounmap(a)	ixp23xx_iounmap(a)
+#define __arch_ioremap	ixp23xx_ioremap
+#define __arch_iounmap	ixp23xx_iounmap
 
 
 #endif
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 24498a9..a54b3db 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -513,4 +513,4 @@
 
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
-
+EXPORT_SYMBOL(dma_set_coherent_mask);
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 0bce0979..4dbfcbb 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -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>
@@ -399,6 +400,23 @@
 }
 
 /*
+ * 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,7 +429,6 @@
 	.rating		= 200,
 	.read		= ixp4xx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift 		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -419,21 +436,9 @@
 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);
-}
+	init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq);
 
-/*
- * sched_clock()
- */
-unsigned long long sched_clock(void)
-{
-	cycle_t cyc = ixp4xx_get_cycles(NULL);
-	struct clocksource *cs = &clocksource_ixp4xx;
-
-	return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
+	clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq);
 }
 
 /*
diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h
index de274a1..57b5410 100644
--- a/arch/arm/mach-ixp4xx/include/mach/io.h
+++ b/arch/arm/mach-ixp4xx/include/mach/io.h
@@ -74,8 +74,8 @@
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(a, s, f)		__indirect_ioremap(a, s, f)
-#define __arch_iounmap(a)		__indirect_iounmap(a)
+#define __arch_ioremap			__indirect_ioremap
+#define __arch_iounmap			__indirect_iounmap
 
 #define writeb(v, p)			__indirect_writeb(v, p)
 #define writew(v, p)			__indirect_writew(v, p)
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 3410633..7fc603b 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -45,18 +45,18 @@
 	  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 --git a/arch/arm/mach-kirkwood/include/mach/io.h b/arch/arm/mach-kirkwood/include/mach/io.h
index 44e8be0..1aaddc3 100644
--- a/arch/arm/mach-kirkwood/include/mach/io.h
+++ b/arch/arm/mach-kirkwood/include/mach/io.h
@@ -42,8 +42,8 @@
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
-#define __arch_iounmap(a)	__arch_iounmap(a)
+#define __arch_ioremap		__arch_ioremap
+#define __arch_iounmap		__arch_iounmap
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
 
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
index 6710bd7..dc999c4 100644
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -80,15 +80,19 @@
 	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 @@
 	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 --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index 3587a28..9a44029 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -119,6 +119,8 @@
 
 static void __init qnap_ts41x_init(void)
 {
+	u32 dev, rev;
+
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
@@ -130,8 +132,15 @@
 	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 --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig
index fe0c82e..f5c39a8 100644
--- a/arch/arm/mach-ks8695/Kconfig
+++ b/arch/arm/mach-ks8695/Kconfig
@@ -4,6 +4,7 @@
 
 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 --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h
index ffa19aa..bace9a6 100644
--- a/arch/arm/mach-ks8695/include/mach/memory.h
+++ b/arch/arm/mach-ks8695/include/mach/memory.h
@@ -35,17 +35,17 @@
 					__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 --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
index 32d6379..da0e649 100644
--- a/arch/arm/mach-lpc32xx/clock.c
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -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 --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c
index 630dd4a..6162ac3 100644
--- a/arch/arm/mach-lpc32xx/timer.c
+++ b/arch/arm/mach-lpc32xx/timer.c
@@ -38,7 +38,6 @@
 
 static struct clocksource lpc32xx_clksrc = {
 	.name	= "lpc32xx_clksrc",
-	.shift	= 24,
 	.rating	= 300,
 	.read	= lpc32xx_clksrc_read,
 	.mask	= CLOCKSOURCE_MASK(32),
@@ -171,9 +170,7 @@
 	__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 --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 0711d3b..67793a6 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -37,25 +37,38 @@
 	  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_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 --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 751cdbf..5c68382 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -15,6 +15,7 @@
 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 --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
new file mode 100644
index 0000000..7bb78fd
--- /dev/null
+++ b/arch/arm/mach-mmp/brownstone.c
@@ -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 --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h
index 016ae94..9b027d7 100644
--- a/arch/arm/mach-mmp/clock.h
+++ b/arch/arm/mach-mmp/clock.h
@@ -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 --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c
index bdeb6db..c4fd806 100644
--- a/arch/arm/mach-mmp/flint.c
+++ b/arch/arm/mach-mmp/flint.c
@@ -47,7 +47,7 @@
 	GPIO113_SMC_RDY,
 
 	/*Ethernet*/
-	GPIO155_GPIO155,
+	GPIO155_GPIO,
 
 	/* DFI */
 	GPIO168_DFI_D0,
diff --git a/arch/arm/mach-mmp/include/mach/mfp-mmp2.h b/arch/arm/mach-mmp/include/mach/mfp-mmp2.h
index 761c2da..117e303 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-mmp2.h
@@ -9,175 +9,175 @@
 #define MFP_DRIVE_FAST		(0x8 << 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 --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h
index dbba6e8..4aec493 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -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_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)
 {
@@ -63,5 +69,21 @@
 	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 --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
index ac47023..f7011ef 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -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 --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index 2a684fa..24172a0 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -67,6 +67,36 @@
 
 	/* 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 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 @@
 	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 --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 2e3dd08..8e6c3ac 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -115,6 +115,29 @@
 	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(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 @@
 	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(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 --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 46f2d69..8f92ccd 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -111,6 +111,7 @@
 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 @@
 	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 --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
index 6652819..aeb9ae2 100644
--- a/arch/arm/mach-mmp/time.c
+++ b/arch/arm/mach-mmp/time.c
@@ -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 @@
 	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 struct clocksource cksrc = {
 	.name		= "clocksource",
-	.shift		= 20,
 	.rating		= 200,
 	.read		= clksrc_read,
 	.mask		= CLOCKSOURCE_MASK(32),
@@ -186,17 +175,15 @@
 {
 	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 --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index dbbcfeb..fae931a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -44,11 +44,14 @@
 	select CPU_V7
 	select MSM_V2_TLMM
 	select MSM_GPIOMUX
+	select IOMMU_API
 
 endchoice
 
 config MSM_SOC_REV_A
 	bool
+config  ARCH_MSM_SCORPIONMP
+	bool
 
 config  ARCH_MSM_ARM11
 	bool
@@ -122,6 +125,10 @@
 
 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 +169,7 @@
 
 config MSM_V2_TLMM
 	bool
+
+config IOMMU_API
+	bool
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index b5a7b07..59646bb 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -20,6 +20,7 @@
 obj-$(CONFIG_MSM_SMD) += last_radio_log.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 +29,8 @@
 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 --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 05241df..6f3b973 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -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(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 --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 7486a68..9b5eb2b 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -28,8 +28,6 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-void __iomem *gic_cpu_base_addr;
-
 unsigned long clk_get_max_axi_khz(void)
 {
 	return 0;
@@ -44,9 +42,8 @@
 {
 	unsigned int i;
 
-	gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
-	gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
-	gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+		 (void *)MSM_QGIC_CPU_BASE);
 
 	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
 	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index ed2af4a..2e83913 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -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>
@@ -74,9 +75,24 @@
 }
 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(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 --git a/arch/arm/mach-msm/board-trout-gpio.c b/arch/arm/mach-msm/board-trout-gpio.c
index c50f3af..f8c09ef 100644
--- a/arch/arm/mach-msm/board-trout-gpio.c
+++ b/arch/arm/mach-msm/board-trout-gpio.c
@@ -72,6 +72,13 @@
 	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 @@
 			.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,				\
 		},							\
diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c
new file mode 100644
index 0000000..729bb49
--- /dev/null
+++ b/arch/arm/mach-msm/board-trout-panel.c
@@ -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 --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index c57210f..2069bfa 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -120,6 +120,21 @@
 
 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 --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
index 4e8c0bc..fb548a8 100644
--- a/arch/arm/mach-msm/devices-msm7x00.c
+++ b/arch/arm/mach-msm/devices-msm7x00.c
@@ -347,6 +347,73 @@
 	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 @@
 	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 --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 7fcf2e3..4e9a0ab 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -56,6 +56,77 @@
 	.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 @@
 	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 --git a/arch/arm/mach-msm/devices-msm8x60-iommu.c b/arch/arm/mach-msm/devices-msm8x60-iommu.c
index 89b9d44..f9e7bd3 100644
--- a/arch/arm/mach-msm/devices-msm8x60-iommu.c
+++ b/arch/arm/mach-msm/devices-msm8x60-iommu.c
@@ -254,60 +254,86 @@
 	},
 };
 
+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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+		 31, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
+	.name = "gfx2d0_2d0",
+	.num = 0,
 	.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}
-};
-
-static struct msm_iommu_ctx_dev gfx2d0_pixv1_ctx = {
-	.name = "gfx2d0_pixv1_smmu",
+static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = {
+	.name = "gfx2d1_2d1",
 	.num = 0,
-	.mids = {0, 3, 4, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx2d0_texv3_ctx = {
-	.name = "gfx2d0_texv3_smmu",
-	.num = 1,
-	.mids = {1, 6, 7, -1}
+	.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 @@
 	.name = "msm_iommu_ctx",
 	.id = 1,
 	.dev = {
-		.parent = &msm_device_smmu_jpegd.dev,
+		.parent = &msm_device_iommu_jpegd.dev,
 	},
 };
 
@@ -569,7 +600,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 2,
 	.dev = {
-		.parent = &msm_device_smmu_vpe.dev,
+		.parent = &msm_device_iommu_vpe.dev,
 	},
 };
 
@@ -577,7 +608,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 3,
 	.dev = {
-		.parent = &msm_device_smmu_vpe.dev,
+		.parent = &msm_device_iommu_vpe.dev,
 	},
 };
 
@@ -585,7 +616,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 4,
 	.dev = {
-		.parent = &msm_device_smmu_mdp0.dev,
+		.parent = &msm_device_iommu_mdp0.dev,
 	},
 };
 
@@ -593,7 +624,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 5,
 	.dev = {
-		.parent = &msm_device_smmu_mdp0.dev,
+		.parent = &msm_device_iommu_mdp0.dev,
 	},
 };
 
@@ -601,7 +632,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 6,
 	.dev = {
-		.parent = &msm_device_smmu_mdp1.dev,
+		.parent = &msm_device_iommu_mdp1.dev,
 	},
 };
 
@@ -609,7 +640,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 7,
 	.dev = {
-		.parent = &msm_device_smmu_mdp1.dev,
+		.parent = &msm_device_iommu_mdp1.dev,
 	},
 };
 
@@ -617,7 +648,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 8,
 	.dev = {
-		.parent = &msm_device_smmu_rot.dev,
+		.parent = &msm_device_iommu_rot.dev,
 	},
 };
 
@@ -625,7 +656,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 9,
 	.dev = {
-		.parent = &msm_device_smmu_rot.dev,
+		.parent = &msm_device_iommu_rot.dev,
 	},
 };
 
@@ -633,7 +664,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 10,
 	.dev = {
-		.parent = &msm_device_smmu_ijpeg.dev,
+		.parent = &msm_device_iommu_ijpeg.dev,
 	},
 };
 
@@ -641,7 +672,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 11,
 	.dev = {
-		.parent = &msm_device_smmu_ijpeg.dev,
+		.parent = &msm_device_iommu_ijpeg.dev,
 	},
 };
 
@@ -649,7 +680,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 12,
 	.dev = {
-		.parent = &msm_device_smmu_vfe.dev,
+		.parent = &msm_device_iommu_vfe.dev,
 	},
 };
 
@@ -657,7 +688,7 @@
 	.name = "msm_iommu_ctx",
 	.id = 13,
 	.dev = {
-		.parent = &msm_device_smmu_vfe.dev,
+		.parent = &msm_device_iommu_vfe.dev,
 	},
 };
 
@@ -665,7 +696,7 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	&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 @@
 	&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 @@
 		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 @@
 					       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 @@
 	return ret;
 }
 
-static void msm8x60_iommu_exit(void)
+static void __exit msm8x60_iommu_exit(void)
 {
 	int i;
 
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 6fe67c5..a4b798f 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -53,6 +53,77 @@
 	.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 --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 568443e..87c70bf 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -28,6 +28,8 @@
 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_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 --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
new file mode 100644
index 0000000..0de19ec
--- /dev/null
+++ b/arch/arm/mach-msm/gpio-v2.c
@@ -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 --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 218ef57..296c0f1 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -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 --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
index f9386d3..c2c3da9 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
@@ -54,6 +54,7 @@
 
 #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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h
index 36074cf..f65841c 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8x60.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8x60.h
@@ -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 --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index 8a00c2d..0fd7b68 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -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 --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index 45bab50..7c43a9b 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -98,4 +98,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 --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h
index 3ff7bf5..a95f7b9 100644
--- a/arch/arm/mach-msm/include/mach/smp.h
+++ b/arch/arm/mach-msm/include/mach/smp.h
@@ -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 --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index d36b610..f912d7b 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -163,3 +163,4 @@
 	return __arm_ioremap_caller(phys_addr, size, mtype,
 		__builtin_return_address(0));
 }
+EXPORT_SYMBOL(__msm_ioremap);
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index f71747d..e2d58e4 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -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 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 @@
 		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 __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 @@
 	/* 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 @@
 		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 @@
 			  __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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 
 	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 @@
 		}
 	}
 
-	__flush_iotlb(domain);
+	ret = __flush_iotlb(domain);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -490,9 +536,6 @@
 	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 @@
 	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 @@
 {
 	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 @@
 
 	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 @@
 	.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 --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index 9019cee..b83c73b 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -346,7 +346,7 @@
 	.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 @@
 	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 --git a/arch/arm/mach-msm/sirc.c b/arch/arm/mach-msm/sirc.c
index b079452..152eefd 100644
--- a/arch/arm/mach-msm/sirc.c
+++ b/arch/arm/mach-msm/sirc.c
@@ -40,9 +40,6 @@
 	}
 };
 
-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)
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index f07dc7c..657be73 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 
 	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 @@
 {
 	unsigned long flags;
 
-	pr_info("smd_close(%p)\n", ch);
-
 	if (ch == 0)
 		return -1;
 
@@ -939,7 +939,6 @@
 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 @@
 	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 --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index f91c3b7..8736aff 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -270,8 +270,10 @@
 {
 	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 --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 950100f..595be7f 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -137,7 +137,6 @@
 			.rating         = 200,
 			.read           = msm_gpt_read,
 			.mask           = CLOCKSOURCE_MASK(32),
-			.shift          = 17,
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
 		.irq = {
@@ -164,7 +163,6 @@
 			.rating         = 300,
 			.read           = msm_dgt_read,
 			.mask           = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
-			.shift          = 24 - MSM_DGT_SHIFT,
 			.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 		},
 		.irq = {
@@ -205,8 +203,7 @@
 		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);
diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
index 788bdac..3eff399 100644
--- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
+++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
@@ -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 --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig
deleted file mode 100644
index 38ca09a..0000000
--- a/arch/arm/mach-mx25/Kconfig
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/Makefile b/arch/arm/mach-mx25/Makefile
deleted file mode 100644
index d9e46ce..0000000
--- a/arch/arm/mach-mx25/Makefile
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/Makefile.boot b/arch/arm/mach-mx25/Makefile.boot
deleted file mode 100644
index e1dd366..0000000
--- a/arch/arm/mach-mx25/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
-   zreladdr-y	:= 0x80008000
-params_phys-y	:= 0x80000100
-initrd_phys-y	:= 0x80800000
diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c
deleted file mode 100644
index 9e4a557..0000000
--- a/arch/arm/mach-mx25/clock.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/devices-imx25.h b/arch/arm/mach-mx25/devices-imx25.h
deleted file mode 100644
index d94d282..0000000
--- a/arch/arm/mach-mx25/devices-imx25.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/devices.c b/arch/arm/mach-mx25/devices.c
deleted file mode 100644
index 1d0eb3e..0000000
--- a/arch/arm/mach-mx25/devices.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/devices.h b/arch/arm/mach-mx25/devices.h
deleted file mode 100644
index 7b70a43..0000000
--- a/arch/arm/mach-mx25/devices.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
deleted file mode 100644
index e765ac5..0000000
--- a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/mach-cpuimx25.c b/arch/arm/mach-mx25/mach-cpuimx25.c
deleted file mode 100644
index f6f9ad6..0000000
--- a/arch/arm/mach-mx25/mach-cpuimx25.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/mach-mx25_3ds.c b/arch/arm/mach-mx25/mach-mx25_3ds.c
deleted file mode 100644
index f8be1eb..0000000
--- a/arch/arm/mach-mx25/mach-mx25_3ds.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx25/mm.c b/arch/arm/mach-mx25/mm.c
deleted file mode 100644
index bb67711..0000000
--- a/arch/arm/mach-mx25/mm.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 5000ac1..0717f88 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -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_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_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_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_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_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_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_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_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_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_EUKREA_CPUIMX35
 	bool "Support Eukrea CPUIMX35 Platform"
-	select ARCH_MX35
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_MXC_NAND
+	select SOC_IMX35
 	select IMX_HAVE_PLATFORM_FLEXCAN
-	select IMX_HAVE_PLATFORM_ESDHC
+	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_SDHCI_ESDHC_IMX
 	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Eukrea CPUIMX35 platform. This includes
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index 8a182d0a..8db1329 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -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 --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c
index 109e98f..d423cac 100644
--- a/arch/arm/mach-mx3/clock-imx31.c
+++ b/arch/arm/mach-mx3/clock-imx31.c
@@ -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 @@
 	_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 @@
 
 	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 --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c
index 61e4a31..448a038 100644
--- a/arch/arm/mach-mx3/clock-imx35.c
+++ b/arch/arm/mach-mx3/clock-imx35.c
@@ -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 @@
 	_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 --git a/arch/arm/mach-mx3/cpu.c b/arch/arm/mach-mx3/cpu.c
index d00a754..d1d3395 100644
--- a/arch/arm/mach-mx3/cpu.c
+++ b/arch/arm/mach-mx3/cpu.c
@@ -25,15 +25,15 @@
 };
 
 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 @@
 			return;
 		}
 
+	mx31_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
+
 	printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
 }
 
@@ -62,22 +64,25 @@
 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 --git a/arch/arm/mach-mx3/devices-imx31.h b/arch/arm/mach-mx3/devices-imx31.h
index de95985..40f4e84 100644
--- a/arch/arm/mach-mx3/devices-imx31.h
+++ b/arch/arm/mach-mx3/devices-imx31.h
@@ -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 @@
 #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 @@
 #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 --git a/arch/arm/mach-mx3/devices-imx35.h b/arch/arm/mach-mx3/devices-imx35.h
index 5eb917b..677b18a 100644
--- a/arch/arm/mach-mx3/devices-imx35.h
+++ b/arch/arm/mach-mx3/devices-imx35.h
@@ -13,10 +13,19 @@
 #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 @@
 #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 @@
 #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 --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
index d4da949..b6672db 100644
--- a/arch/arm/mach-mx3/devices.c
+++ b/arch/arm/mach-mx3/devices.c
@@ -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 @@
 
 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 @@
 
 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 @@
 	},
 };
 
-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 @@
 	.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 --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h
index 585f814..121962c 100644
--- a/arch/arm/mach-mx3/devices.h
+++ b/arch/arm/mach-mx3/devices.h
@@ -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 --git a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
index 1abc10d..14a5ffc 100644
--- a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
@@ -111,7 +111,7 @@
 	.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 @@
 	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 --git a/arch/arm/mach-mx3/mach-armadillo5x0.c b/arch/arm/mach-mx3/mach-armadillo5x0.c
index aaa30fe..28b6f41 100644
--- a/arch/arm/mach-mx3/mach-armadillo5x0.c
+++ b/arch/arm/mach-mx3/mach-armadillo5x0.c
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c
index 9fde873..26ae90f 100644
--- a/arch/arm/mach-mx3/mach-cpuimx35.c
+++ b/arch/arm/mach-mx3/mach-cpuimx35.c
@@ -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 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 @@
 	.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 @@
 			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 @@
 	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 --git a/arch/arm/mach-mx3/mach-kzm_arm11_01.c b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
index 042cd56..a5f3eb2 100644
--- a/arch/arm/mach-mx3/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
@@ -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 --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 0ad9e78..4e516b4 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -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 @@
 	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 @@
 	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,6 +131,13 @@
 	},
 };
 
+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. */
@@ -122,6 +145,13 @@
 	}, {
 		.id = MC13783_REGU_PWGT2SPI, /* Power Gate for L2 Cache. */
 		.init_data = &pwgtx_init,
+	}, {
+
+		.id = MC13783_REGU_GPO1, /* Turn on 1.8V */
+		.init_data = &gpo_init,
+	}, {
+		.id = MC13783_REGU_GPO3, /* Turn on 3.3V */
+		.init_data = &gpo_init,
 	},
 };
 
@@ -129,7 +159,7 @@
 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 @@
 		     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 @@
 	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 @@
 	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 --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c
index 42f47fa..2c59548 100644
--- a/arch/arm/mach-mx3/mach-mx31lilly.c
+++ b/arch/arm/mach-mx3/mach-mx31lilly.c
@@ -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 @@
 	.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 @@
 	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 --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
index b938958..9e64c66 100644
--- a/arch/arm/mach-mx3/mach-mx31lite.c
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -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 @@
 	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 @@
 	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 --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index eb5f426..203d21a 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -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 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",
 	},
 };
@@ -345,7 +343,7 @@
 	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 @@
 
 #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 @@
 	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 --git a/arch/arm/mach-mx3/mach-mx35_3ds.c b/arch/arm/mach-mx3/mach-mx35_3ds.c
index b66a75a..b1963f2 100644
--- a/arch/arm/mach-mx3/mach-mx35_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx35_3ds.c
@@ -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 @@
 	&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 @@
 };
 
 /* 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 @@
 	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 --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c
index 2ff3f66..b752f6b 100644
--- a/arch/arm/mach-mx3/mach-pcm037.c
+++ b/arch/arm/mach-mx3/mach-pcm037.c
@@ -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 @@
 	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 struct platform_device *devices[] __initdata = {
 	&pcm037_flash,
 	&pcm037_sram_device,
-	&imx_wdt_device0,
 	&pcm037_mt9t031,
 	&pcm037_mt9v022,
 };
@@ -538,18 +534,18 @@
 };
 
 #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 @@
 
 	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 @@
 	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 @@
 		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 --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
index 4e1de87..bcf83fc 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -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 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 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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 };
 
 #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 @@
 
 	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 @@
 		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 --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c
index b4ffc53..47118f7 100644
--- a/arch/arm/mach-mx3/mm.c
+++ b/arch/arm/mach-mx3/mm.c
@@ -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 @@
 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
+int imx31_register_gpios(void);
+void __init mx31_init_irq(void)
+{
+	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
+	imx31_register_gpios();
+}
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+static struct map_desc mx35_io_desc[] __initdata = {
+	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
 void __init mx35_map_io(void)
 {
 	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));
+	mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
 
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
-}
-#endif
-
-int imx3x_register_gpios(void);
-
-void __init mx31_init_irq(void)
-{
-	mxc_init_irq(IO_ADDRESS(AVIC_BASE_ADDR));
-	imx3x_register_gpios();
+	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 @@
 		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 --git a/arch/arm/mach-mx3/mx31lilly-db.c b/arch/arm/mach-mx3/mx31lilly-db.c
index 827fd3c..8f1a38e 100644
--- a/arch/arm/mach-mx3/mx31lilly-db.c
+++ b/arch/arm/mach-mx3/mx31lilly-db.c
@@ -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 @@
 	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 @@
 	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 --git a/arch/arm/mach-mx3/mx31lite-db.c b/arch/arm/mach-mx3/mx31lite-db.c
index 7b0e74e..3124ea8 100644
--- a/arch/arm/mach-mx3/mx31lite-db.c
+++ b/arch/arm/mach-mx3/mx31lite-db.c
@@ -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 @@
 	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 @@
 					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 --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c
index fc395a7..94a0b9e 100644
--- a/arch/arm/mach-mx3/mx31moboard-devboard.c
+++ b/arch/arm/mach-mx3/mx31moboard-devboard.c
@@ -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 @@
 	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 @@
 	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 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 @@
 
 	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 @@
 
 	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 --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c
index 18069cb..f449a97 100644
--- a/arch/arm/mach-mx3/mx31moboard-marxbot.c
+++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c
@@ -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 @@
 	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 @@
 	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 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 @@
 
 	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 @@
 
 	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 @@
 	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 --git a/arch/arm/mach-mx3/mx31moboard-smartbot.c b/arch/arm/mach-mx3/mx31moboard-smartbot.c
index 04760a5..bbec3c8 100644
--- a/arch/arm/mach-mx3/mx31moboard-smartbot.c
+++ b/arch/arm/mach-mx3/mx31moboard-smartbot.c
@@ -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 @@
 	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 @@
 
 	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 --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 3ec910a..55254b6 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -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,9 @@
 
 config MACH_MX51_3DS
 	bool "Support MX51PDK (3DS)"
+	select SOC_IMX51
 	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 +60,7 @@
 
 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 +77,7 @@
 config MACH_EUKREA_MBIMX51_BASEBOARD
 	prompt "Eukrea MBIMX51 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
 	  MBIMX51 evaluation board.
@@ -56,6 +86,7 @@
 
 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 +103,7 @@
 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 +112,33 @@
 
 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
+	help
+	  Include support for MX53 EVK 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 --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 462f177..0c398ba 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -3,13 +3,16 @@
 #
 
 # 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_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 --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot
index 9939a19..e928be1 100644
--- a/arch/arm/mach-mx5/Makefile.boot
+++ b/arch/arm/mach-mx5/Makefile.boot
@@ -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 --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index 6a9792f..f8652ef 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -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 @@
 #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 @@
 	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 @@
 	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 @@
 	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 @@
 
 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 --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
index 4b3a611..ad93189 100644
--- a/arch/arm/mach-mx5/board-cpuimx51sd.c
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 		.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 @@
 
 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 --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
new file mode 100644
index 0000000..fd32e4c
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -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 --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index 79ce8dc..e42bd2e 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -30,7 +30,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 +50,7 @@
 	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 +68,7 @@
 	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 */
@@ -172,6 +172,7 @@
 		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 +187,7 @@
 
 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 --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index acbe30d..1d231e8 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -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 @@
 	.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 @@
 	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 @@
 	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 @@
 	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 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 @@
 	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 @@
 	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 @@
 	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 @@
 }
 __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 @@
 	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 @@
 	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 --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
index 6e623bd..b7946f8 100644
--- a/arch/arm/mach-mx5/board-mx51_efikamx.c
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -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 @@
 	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 @@
 	.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 --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
new file mode 100644
index 0000000..fa97d0d
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx53_evk.c
@@ -0,0 +1,84 @@
+/*
+ * 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 <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>
+
+#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,
+};
+
+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 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();
+}
+
+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 --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
new file mode 100644
index 0000000..785e1a3
--- /dev/null
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -0,0 +1,1420 @@
+/*
+ * 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);
+
+/* 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("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.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-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)
+};
+
+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_set_parent(&uart_root_clk, &pll3_sw_clk);
+	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_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 --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
deleted file mode 100644
index 8ac36d8..0000000
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
index eaacb6e..d40671d 100644
--- a/arch/arm/mach-mx5/cpu.c
+++ b/arch/arm/mach-mx5/cpu.c
@@ -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;
+	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
+	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
 
-	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;
-	}
-
-	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 @@
 		return -EINVAL;
 
 	if (cpu_silicon_rev == -1)
-		query_silicon_parameter();
+		cpu_silicon_rev = get_mx51_srev();
 
 	return cpu_silicon_rev;
 }
@@ -79,7 +60,10 @@
  */
 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 @@
 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 --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
index c776b9a..b462c22 100644
--- a/arch/arm/mach-mx5/crm_regs.h
+++ b/arch/arm/mach-mx5/crm_regs.h
@@ -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 --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
index 8c50cb5..6302e46 100644
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -31,6 +31,11 @@
 #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,6 @@
 #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])
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
new file mode 100644
index 0000000..9d0ec25
--- /dev/null
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -0,0 +1,13 @@
+/*
+ * 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_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)
diff --git a/arch/arm/mach-mx5/devices-mx50.h b/arch/arm/mach-mx5/devices-mx50.h
new file mode 100644
index 0000000..98ab074
--- /dev/null
+++ b/arch/arm/mach-mx5/devices-mx50.h
@@ -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 --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 4c7be87..1bda5cb 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -97,19 +97,27 @@
 	},
 };
 
-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,
 	},
+	{
+		.start = MX51_MXC_INT_USB_H2,
+		.flags = IORESOURCE_IRQ,
+	},
 };
 
-struct platform_device mxc_wdt = {
-	.name = "imx2-wdt",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_wdt_resources),
-	.resource = mxc_wdt_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 resource mxc_kpp_resources[] = {
@@ -160,9 +168,36 @@
 		.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 --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
index af1d07c..16891aa 100644
--- a/arch/arm/mach-mx5/devices.h
+++ b/arch/arm/mach-mx5/devices.h
@@ -1,6 +1,6 @@
 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 --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
index a2e6e8c..c96d018 100644
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
@@ -33,12 +33,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 +84,7 @@
 	&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 +96,13 @@
 	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,
@@ -217,6 +217,6 @@
 	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 --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
index 2b48f51..c372a43 100644
--- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
@@ -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 @@
 	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 @@
 	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 --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c
new file mode 100644
index 0000000..8c6540e
--- /dev/null
+++ b/arch/arm/mach-mx5/mm-mx50.c
@@ -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 --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index bc3f30d..457f9f9 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -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 @@
 {
 	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 @@
 	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 @@
 	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 --git a/arch/arm/mach-mxc91231/clock.c b/arch/arm/mach-mxc91231/clock.c
index 5c85075..9fab505 100644
--- a/arch/arm/mach-mxc91231/clock.c
+++ b/arch/arm/mach-mxc91231/clock.c
@@ -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 --git a/arch/arm/mach-mxc91231/mm.c b/arch/arm/mach-mxc91231/mm.c
index aeccfd75..7652c30 100644
--- a/arch/arm/mach-mxc91231/mm.c
+++ b/arch/arm/mach-mxc91231/mm.c
@@ -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 @@
 {
 	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 --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
new file mode 100644
index 0000000..c4ac7b4
--- /dev/null
+++ b/arch/arm/mach-mxs/Kconfig
@@ -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_PLATFORM_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_PLATFORM_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 --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
new file mode 100644
index 0000000..39d3f9c
--- /dev/null
+++ b/arch/arm/mach-mxs/Makefile
@@ -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 --git a/arch/arm/mach-mxs/Makefile.boot b/arch/arm/mach-mxs/Makefile.boot
new file mode 100644
index 0000000..eb541e0
--- /dev/null
+++ b/arch/arm/mach-mxs/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-y := 0x40008000
diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
new file mode 100644
index 0000000..8f5a19a
--- /dev/null
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -0,0 +1,526 @@
+/*
+ * 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 <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,		\
+			 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[] = {
+	_REGISTER_CLOCK("mxs-duart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
+	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
+	_REGISTER_CLOCK(NULL, "xclk", xbus_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();
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	mxs_timer_init(&clk32k_clk, MX23_INT_TIMER0);
+
+	return 0;
+}
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
new file mode 100644
index 0000000..74e2103
--- /dev/null
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -0,0 +1,734 @@
+/*
+ * 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 <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_CPU);		\
+									\
+	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,		\
+			 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[] = {
+	_REGISTER_CLOCK("mxs-duart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("fec.0", 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();
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	mxs_timer_init(&clk32k_clk, MX28_INT_TIMER0);
+
+	return 0;
+}
diff --git a/arch/arm/mach-mxs/clock.c b/arch/arm/mach-mxs/clock.c
new file mode 100644
index 0000000..e7d2269
--- /dev/null
+++ b/arch/arm/mach-mxs/clock.c
@@ -0,0 +1,200 @@
+/*
+ * 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);
+		__clk_disable(clk->secondary);
+	}
+}
+
+static int __clk_enable(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	if (clk->usecount++ == 0) {
+		__clk_enable(clk->parent);
+		__clk_enable(clk->secondary);
+
+		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 --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
new file mode 100644
index 0000000..d0f49fc
--- /dev/null
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -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 mxs_duart_data mx23_duart_data __initconst;
+#define mx23_add_duart() \
+	mxs_add_duart(&mx23_duart_data)
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
new file mode 100644
index 0000000..00b736c
--- /dev/null
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -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 mxs_duart_data mx28_duart_data __initconst;
+#define mx28_add_duart() \
+	mxs_add_duart(&mx28_duart_data)
+
+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 --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c
new file mode 100644
index 0000000..6b60f02
--- /dev/null
+++ b/arch/arm/mach-mxs/devices.c
@@ -0,0 +1,75 @@
+/*
+ * 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/err.h>
+#include <linux/platform_device.h>
+#include <mach/common.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;
+}
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
new file mode 100644
index 0000000..a35a2dc
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -0,0 +1,5 @@
+config MXS_HAVE_PLATFORM_DUART
+	bool
+
+config MXS_HAVE_PLATFORM_FEC
+	bool
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
new file mode 100644
index 0000000..4b5266a
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MXS_HAVE_PLATFORM_DUART) += platform-duart.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
diff --git a/arch/arm/mach-mxs/devices/platform-duart.c b/arch/arm/mach-mxs/devices/platform-duart.c
new file mode 100644
index 0000000..2fe0df5
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-duart.c
@@ -0,0 +1,48 @@
+/*
+ * 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 <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_duart_data_entry(soc)					\
+	{								\
+		.iobase = soc ## _DUART_BASE_ADDR,			\
+		.irq = soc ## _INT_DUART,				\
+	}
+
+#ifdef CONFIG_SOC_IMX23
+const struct mxs_duart_data mx23_duart_data __initconst =
+	mxs_duart_data_entry(MX23);
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_duart_data mx28_duart_data __initconst =
+	mxs_duart_data_entry(MX28);
+#endif
+
+struct platform_device *__init mxs_add_duart(
+		const struct mxs_duart_data *data)
+{
+	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 mxs_add_platform_device("mxs-duart", 0, res, ARRAY_SIZE(res),
+					NULL, 0);
+}
diff --git a/arch/arm/mach-mxs/devices/platform-fec.c b/arch/arm/mach-mxs/devices/platform-fec.c
new file mode 100644
index 0000000..c08168c
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-fec.c
@@ -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("fec", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-mxs/gpio.c b/arch/arm/mach-mxs/gpio.c
new file mode 100644
index 0000000..d7ad7a6
--- /dev/null
+++ b/arch/arm/mach-mxs/gpio.c
@@ -0,0 +1,325 @@
+/*
+ * 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;
+
+	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 --git a/arch/arm/mach-mxs/gpio.h b/arch/arm/mach-mxs/gpio.h
new file mode 100644
index 0000000..005bb06
--- /dev/null
+++ b/arch/arm/mach-mxs/gpio.h
@@ -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 --git a/arch/arm/mach-mxs/icoll.c b/arch/arm/mach-mxs/icoll.c
new file mode 100644
index 0000000..5dd43ba
--- /dev/null
+++ b/arch/arm/mach-mxs/icoll.c
@@ -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 --git a/arch/arm/mach-mxs/include/mach/clkdev.h b/arch/arm/mach-mxs/include/mach/clkdev.h
new file mode 100644
index 0000000..3a8f2e3
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/clkdev.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/clock.h b/arch/arm/mach-mxs/include/mach/clock.h
new file mode 100644
index 0000000..041e276
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/clock.h
@@ -0,0 +1,64 @@
+/*
+ * 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;
+	/* Secondary clock to enable/disable with this clock */
+	struct clk *secondary;
+	/* 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 --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
new file mode 100644
index 0000000..59133eb
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/common.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/debug-macro.S b/arch/arm/mach-mxs/include/mach/debug-macro.S
new file mode 100644
index 0000000..79650a1
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/debug-macro.S
@@ -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 --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
new file mode 100644
index 0000000..3da48d4
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -0,0 +1,46 @@
+/*
+ * 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>
+
+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);
+}
+
+/* duart */
+struct mxs_duart_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init mxs_add_duart(
+		const struct mxs_duart_data *data);
+
+/* 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 --git a/arch/arm/mach-mxs/include/mach/entry-macro.S b/arch/arm/mach-mxs/include/mach/entry-macro.S
new file mode 100644
index 0000000..9f0da12
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/entry-macro.S
@@ -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 --git a/arch/arm/mach-mxs/include/mach/gpio.h b/arch/arm/mach-mxs/include/mach/gpio.h
new file mode 100644
index 0000000..828cccc
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/gpio.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/hardware.h b/arch/arm/mach-mxs/include/mach/hardware.h
new file mode 100644
index 0000000..53e89a0
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/hardware.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/io.h b/arch/arm/mach-mxs/include/mach/io.h
new file mode 100644
index 0000000..289b722
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/io.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/iomux-mx23.h b/arch/arm/mach-mxs/include/mach/iomux-mx23.h
new file mode 100644
index 0000000..94e5dd8
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/iomux-mx23.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/iomux-mx28.h b/arch/arm/mach-mxs/include/mach/iomux-mx28.h
new file mode 100644
index 0000000..f50fefd
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/iomux-mx28.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/iomux.h b/arch/arm/mach-mxs/include/mach/iomux.h
new file mode 100644
index 0000000..fe558e3
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/iomux.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/irqs.h b/arch/arm/mach-mxs/include/mach/irqs.h
new file mode 100644
index 0000000..f771039
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/irqs.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/memory.h b/arch/arm/mach-mxs/include/mach/memory.h
new file mode 100644
index 0000000..b5420a5
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/memory.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/mx23.h b/arch/arm/mach-mxs/include/mach/mx23.h
new file mode 100644
index 0000000..9edd02e
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/mx23.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/mx28.h b/arch/arm/mach-mxs/include/mach/mx28.h
new file mode 100644
index 0000000..0716745
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/mx28.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/mxs.h b/arch/arm/mach-mxs/include/mach/mxs.h
new file mode 100644
index 0000000..f186c08
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/mxs.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/system.h b/arch/arm/mach-mxs/include/mach/system.h
new file mode 100644
index 0000000..0e42823
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/system.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/timex.h b/arch/arm/mach-mxs/include/mach/timex.h
new file mode 100644
index 0000000..734ce89
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/timex.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/uncompress.h b/arch/arm/mach-mxs/include/mach/uncompress.h
new file mode 100644
index 0000000..a005e76f
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/uncompress.h
@@ -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 --git a/arch/arm/mach-mxs/include/mach/vmalloc.h b/arch/arm/mach-mxs/include/mach/vmalloc.h
new file mode 100644
index 0000000..103b016
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/vmalloc.h
@@ -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 --git a/arch/arm/mach-mxs/iomux.c b/arch/arm/mach-mxs/iomux.c
new file mode 100644
index 0000000..0e804e2
--- /dev/null
+++ b/arch/arm/mach-mxs/iomux.c
@@ -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 --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
new file mode 100644
index 0000000..aa06400
--- /dev/null
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -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 --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
new file mode 100644
index 0000000..d162e95
--- /dev/null
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -0,0 +1,138 @@
+/*
+ * 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),
+	/* 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 const struct fec_platform_data mx28_fec_pdata __initconst = {
+	.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);
+}
+
+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 --git a/arch/arm/mach-mxs/mm-mx23.c b/arch/arm/mach-mxs/mm-mx23.c
new file mode 100644
index 0000000..5148cd6
--- /dev/null
+++ b/arch/arm/mach-mxs/mm-mx23.c
@@ -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 --git a/arch/arm/mach-mxs/mm-mx28.c b/arch/arm/mach-mxs/mm-mx28.c
new file mode 100644
index 0000000..7e4cea3
--- /dev/null
+++ b/arch/arm/mach-mxs/mm-mx28.c
@@ -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 --git a/arch/arm/mach-mxs/regs-clkctrl-mx23.h b/arch/arm/mach-mxs/regs-clkctrl-mx23.h
new file mode 100644
index 0000000..dbc0474
--- /dev/null
+++ b/arch/arm/mach-mxs/regs-clkctrl-mx23.h
@@ -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 --git a/arch/arm/mach-mxs/regs-clkctrl-mx28.h b/arch/arm/mach-mxs/regs-clkctrl-mx28.h
new file mode 100644
index 0000000..661df18
--- /dev/null
+++ b/arch/arm/mach-mxs/regs-clkctrl-mx28.h
@@ -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 --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
new file mode 100644
index 0000000..9343d7e
--- /dev/null
+++ b/arch/arm/mach-mxs/system.c
@@ -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 --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
new file mode 100644
index 0000000..13647f3
--- /dev/null
+++ b/arch/arm/mach-mxs/timer.c
@@ -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 --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index 82801db..f12f22d 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -114,7 +114,6 @@
 	.rating		= 200,
 	.read		= netx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -151,9 +150,7 @@
 	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 --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c
index 89f793a..48a59f2 100644
--- a/arch/arm/mach-nomadik/clock.c
+++ b/arch/arm/mach-nomadik/clock.c
@@ -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 --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c
index 7728126..9ca32f5 100644
--- a/arch/arm/mach-ns9xxx/time-ns9360.c
+++ b/arch/arm/mach-ns9xxx/time-ns9360.c
@@ -35,7 +35,6 @@
 	.rating	= 300,
 	.read	= ns9360_clocksource_read,
 	.mask	= CLOCKSOURCE_MASK(32),
-	.shift	= 20,
 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -148,10 +147,7 @@
 
 	__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 --git a/arch/arm/mach-nuc93x/clock.h b/arch/arm/mach-nuc93x/clock.h
index 18e51be..4de1f1d 100644
--- a/arch/arm/mach-nuc93x/clock.h
+++ b/arch/arm/mach-nuc93x/clock.h
@@ -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 --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 5f64963..8d2f2da 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -152,20 +152,11 @@
 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 --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 9a304d8..6ee1950 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,7 @@
 #
 
 # 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 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
@@ -39,8 +39,8 @@
 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 +49,12 @@
 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 --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 1d4163b..bd0495a 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -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(6, 5, KEY_B),
+	KEY(6, 4, KEY_N),
+	KEY(6, 3, KEY_M),
+	KEY(6, 2, KEY_SPACE),
 
-	KEY(0, 7, KEY_LEFTSHIFT),	/* Vol up    */
-	KEY(3, 7, KEY_LEFTCTRL),	/* Vol down  */
-
-	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 @@
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static struct map_desc ams_delta_io_desc[] __initdata = {
@@ -189,11 +187,15 @@
 	},
 };
 
+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,
 };
 
@@ -307,16 +309,14 @@
 #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 +340,9 @@
 {
 	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 --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 149fdd3..0efb9db 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -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 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 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 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 @@
 	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 --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 197adb4..28b84aa 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -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 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 @@
 {
 	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 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 --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 9126e3e..dbc8b8d 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -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 @@
 	.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 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 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 @@
 	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 --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 071af3e..f2c5c58 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -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_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 @@
 	.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 @@
 	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 --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index dc2b86f..a36e674 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -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 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 @@
 {
 	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 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 --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index aa8375b..d21f09d 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -54,19 +54,18 @@
 	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 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 @@
 	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 --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e9dd791..7c5e211 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -283,9 +283,6 @@
 {
 	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 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 @@
 {
 	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 --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index f32738b..fb51ce6 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -63,28 +63,31 @@
 {
 	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 --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index ed1400a..f04f2d3 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -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 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 --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index d7a245c..d7bbbe7 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -62,29 +62,32 @@
 {
 	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 --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index a8d16a2..3c8ee84 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -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 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 @@
 	{ 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 @@
 	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 --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index d25f59e..d41fe2d 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -164,36 +164,35 @@
 
 /*----------- 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 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 @@
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 /*----------------------------------------*/
 
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index f5992c2..815a69c 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -83,6 +83,9 @@
 
 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 @@
 {
 	omap1_init_common_hw();
 	omap_init_irq();
-	omap_gpio_init();
 }
 
 static void __init voiceblue_init(void)
@@ -236,6 +238,9 @@
 
 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 --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index b8c7fb9..84ef704 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -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 --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index af54114..92400b9 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -143,7 +143,7 @@
  * 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 @@
 	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 @@
 	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 @@
 			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 @@
 	       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 --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index e7f9ee6..b0f4c23 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -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 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 --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
new file mode 100644
index 0000000..d855934
--- /dev/null
+++ b/arch/arm/mach-omap1/dma.c
@@ -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 --git a/arch/arm/mach-omap1/flash.c b/arch/arm/mach-omap1/flash.c
index 0b07a78..acd1616 100644
--- a/arch/arm/mach-omap1/flash.c
+++ b/arch/arm/mach-omap1/flash.c
@@ -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 --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index 5cfce16..8780e75 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -143,7 +143,7 @@
  */
 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 @@
 	 * 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 --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
new file mode 100644
index 0000000..04c4b04
--- /dev/null
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -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 --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
new file mode 100644
index 0000000..5dd0d4c
--- /dev/null
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -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 --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
new file mode 100644
index 0000000..1204c8b
--- /dev/null
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -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 --git a/arch/arm/mach-omap1/include/mach/entry-macro.S b/arch/arm/mach-omap1/include/mach/entry-macro.S
index df9060e..c9be6d4 100644
--- a/arch/arm/mach-omap1/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap1/include/mach/entry-macro.S
@@ -14,18 +14,17 @@
 #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
+/*
+ * We use __glue to avoid errors with multiple definitions of
+ * .globl omap_irq_flags as it's included from entry-armv.S but not
+ * from entry-common.S.
+ */
+#ifdef __glue
+		.pushsection .data
+		.globl	omap_irq_flags
+omap_irq_flags:
+		.word	0
+		.popsection
 #endif
 
  		.macro	disable_fiq
@@ -47,9 +46,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 --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 0ce3fec..870886a 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -142,3 +142,42 @@
 	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 --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index db913c3..6bddbc8 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -176,26 +176,31 @@
 
 void __init omap_init_irq(void)
 {
+	extern unsigned int omap_irq_flags;
 	int i, j;
 
 #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);
 	}
diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c
index 3be11af..c9088d8 100644
--- a/arch/arm/mach-omap1/lcd_dma.c
+++ b/arch/arm/mach-omap1/lcd_dma.c
@@ -424,6 +424,9 @@
 {
 	int r;
 
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	if (cpu_is_omap16xx()) {
 		u16 w;
 
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c
index 277f356..22eb11d 100644
--- a/arch/arm/mach-omap1/leds.c
+++ b/arch/arm/mach-omap1/leds.c
@@ -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 --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
index 1a85a42..c0e1f48 100644
--- a/arch/arm/mach-omap1/mailbox.c
+++ b/arch/arm/mach-omap1/mailbox.c
@@ -133,19 +133,18 @@
 	},
 };
 
-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 --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index b3a796a..8209736 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -174,8 +174,11 @@
 #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 --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index 7835add..5fdef7a 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -343,7 +343,7 @@
 #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 --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index b1d3f9f..0cca23a 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -661,6 +661,9 @@
 	int error;
 #endif
 
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	printk("Power Management for TI OMAP.\n");
 
 	/*
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
index 8b66392..6588c22 100644
--- a/arch/arm/mach-omap1/pm_bus.c
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -48,7 +48,6 @@
 
 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 @@
 	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 --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index b78d074..550ca9d 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -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 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 @@
 
 static int __init omap_init(void)
 {
+	if (!cpu_class_is_omap1())
+		return -ENODEV;
+
 	return platform_device_register(&serial_device);
 }
 arch_initcall(omap_init);
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 1be6a21..ed7a61f 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -52,6 +52,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#include <plat/common.h>
 
 #define OMAP_MPU_TIMER_BASE		OMAP_MPU_TIMER1_BASE
 #define OMAP_MPU_TIMER_OFFSET		0x100
@@ -208,7 +209,6 @@
 	.rating		= 300,
 	.read		= mpu_read,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 24,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -217,13 +217,10 @@
 	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);
 
-	if (clocksource_register(&clocksource_mpu))
+	if (clocksource_register_hz(&clocksource_mpu, rate))
 		printk(err, clocksource_mpu.name);
 }
 
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index ab784bf..1a2cf62 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -15,7 +15,7 @@
 	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 @@
 	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 @@
 	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_CBP
        bool
 
+config OMAP_PACKAGE_CBL
+       bool
+
+config OMAP_PACKAGE_CBS
+       bool
+
 comment "OMAP Board Type"
 	depends on ARCH_OMAP2PLUS
 
@@ -128,7 +139,6 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 60e51bc..cd7332f 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -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 @@
 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
 
 # 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,17 +177,20 @@
 					   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-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-flash.o \
 					   hsmmc.o \
@@ -168,12 +209,16 @@
 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 --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index b527f8d..e066177 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -135,7 +135,7 @@
 
 #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 @@
 {
 	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_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static void __init omap_2430sdp_init(void)
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 4e3742c..3b39ef1 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -326,9 +326,9 @@
 	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 +663,6 @@
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 /*
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index bbcf580..5d41dbe 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -73,18 +73,16 @@
 {
 	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
 
 /*
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index df5a425..a70bdf2 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -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 @@
 	.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 @@
 	&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 @@
 {
 	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 @@
 	.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 @@
 	{
 		I2C_BOARD_INFO("tmp105", 0x48),
 	},
+	{
+		I2C_BOARD_INFO("bh1780", 0x29),
+	},
 };
 static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = {
 	{
@@ -505,20 +552,37 @@
 	}
 }
 
+#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 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 */
+	if (gpio_is_valid(OMAP4SDP_MDM_PWR_EN_GPIO)) {
+		/* FIXME: Assumes pad is already muxed for GPIO mode */
+		gpio_request(OMAP4SDP_MDM_PWR_EN_GPIO, "USBB1 PHY VMDM_3V3");
+		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 --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
new file mode 100644
index 0000000..71acb5a
--- /dev/null
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -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 --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 0739950..bc15626 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -389,10 +389,9 @@
 {
 	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 +441,6 @@
 	OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 2c6db1a..9f55b68 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -270,7 +270,7 @@
 	.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 @@
 {
 	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 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 @@
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
+	apollon_init_smc91x();
 	apollon_led_init();
 	apollon_flash_init();
 	apollon_usb_init();
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 63f764e..486a3de 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -600,8 +600,8 @@
 	.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 +630,6 @@
 	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 +677,10 @@
 	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 +799,7 @@
 	cm_t35_init_display();
 
 	usb_musb_init(&musb_board_data);
+	usb_ehci_init(&ehci_pdata);
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 1dd303e..5b0c777 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -248,9 +248,9 @@
 	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 = {
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 53ac762..451e7ff 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -118,27 +118,27 @@
 	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 =
@@ -444,13 +444,13 @@
 
 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 --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index b1c2c9a..0e3d81e 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -37,7 +37,8 @@
 {
 	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 --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 929993b..25cc9da 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -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 @@
 	.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 @@
 	.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 @@
 {
 	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 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 --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 5e035a5..0afa301 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -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>
 
@@ -136,16 +137,9 @@
 	},
 };
 
-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 +153,34 @@
 
 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 +247,8 @@
 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 +265,52 @@
 	.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 +352,7 @@
 		.name			= "gpio-led:green:d1",
 		.default_trigger	= "heartbeat",
 		.gpio			= -EINVAL, /* gets replaced */
+		.active_low		= 1,
 	},
 };
 
@@ -342,24 +378,21 @@
 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 +406,6 @@
 	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 +424,9 @@
 	/* 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;
@@ -489,15 +515,15 @@
 
 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 = {
@@ -519,7 +545,7 @@
 	.gpio		= &igep2_twl4030_gpio_pdata,
 	.vmmc1          = &igep2_vmmc1,
 	.vpll2		= &igep2_vpll2,
-
+	.vio		= &igep2_vio,
 };
 
 static struct i2c_board_info __initdata igep2_i2c1_boardinfo[] = {
@@ -577,8 +603,6 @@
 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 --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
index 22b0b25..bcccd68 100644
--- a/arch/arm/mach-omap2/board-igep0030.c
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -289,9 +289,10 @@
 
 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 = {
@@ -366,8 +367,6 @@
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
-#else
-#define board_mux	NULL
 #endif
 
 static void __init igep3_init(void)
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 001fd97..e5dc748 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -292,10 +292,9 @@
 {
 	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 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 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 --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index e823c70..f396756 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -46,8 +46,7 @@
 #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 @@
 
 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 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_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 @@
 	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 @@
 	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 --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 14f4224..6c12760 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -484,13 +484,13 @@
 
 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 +548,6 @@
 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 --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index b04365c..3de8d9b 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -623,9 +623,9 @@
 {
 	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 +654,6 @@
 				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 --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 5f7d2c1..15e4b08 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -197,17 +197,15 @@
 
 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 --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 8be2615..0b34bed 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -293,7 +293,7 @@
 	},
 	{
 		.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,10 +636,10 @@
 
 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 __init pandora_wl1251_init(void)
@@ -697,8 +697,6 @@
 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 --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index f252721..9df9d93 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -584,12 +584,12 @@
 {
 	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 +616,6 @@
 		  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 --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 41104bb..db1f74f 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -413,8 +413,6 @@
 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 @@
 	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 --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 1ecd0a6c..3094e20 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -40,6 +40,7 @@
 
 #include "hsmmc.h"
 #include "control.h"
+#include "mux.h"
 
 #define GPIO_HUB_POWER		1
 #define GPIO_HUB_NRESET		62
@@ -76,9 +77,9 @@
 
 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 = {
@@ -133,15 +134,23 @@
 
 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 +354,7 @@
 	.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,8 +378,23 @@
 	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();
@@ -377,9 +402,7 @@
 	/* 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 +414,7 @@
 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 --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 7053bc0..cb26e5d 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -413,10 +413,10 @@
 {
 	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 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 --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
new file mode 100644
index 0000000..cb77be7
--- /dev/null
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -0,0 +1,187 @@
+/*
+ * 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",
+		.min_uV			= 2900000,
+		.max_uV			= 2900000,
+		.apply_uV		= 1,
+		.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 --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 3fec4d6..e75e240 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -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 @@
 	{ .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 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 @@
 	/* 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 @@
 	/* 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_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 @@
 	.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 @@
 	.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 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 @@
 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 --git a/arch/arm/mach-omap2/board-rx51-sdram.c b/arch/arm/mach-omap2/board-rx51-sdram.c
deleted file mode 100644
index a43b2c5..0000000
--- a/arch/arm/mach-omap2/board-rx51-sdram.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index 85503fe..acd6700 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -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 @@
 	.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 --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 36f2cf4..f53fc55 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -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 @@
 	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 @@
 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 --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 9db9203..3fbd0ed 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -196,7 +196,7 @@
 	.board_ref_clock = 1,
 };
 
-static struct omap2_hsmmc_info mmc[] __initdata = {
+static struct omap2_hsmmc_info mmc[] = {
 	{
 		.name		= "external",
 		.mmc		= 1,
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
new file mode 100644
index 0000000..e041c53
--- /dev/null
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -0,0 +1,151 @@
+/*
+ * 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();
+}
+
+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 --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
deleted file mode 100644
index 2992a9f..0000000
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
deleted file mode 100644
index 5adde12..0000000
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c
index 66e01ac..f51cffd 100644
--- a/arch/arm/mach-omap2/clkt2xxx_apll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_apll.c
@@ -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 @@
 
 	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 @@
 {
 	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 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 --git a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
index 01904843..4ae4392 100644
--- a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
+++ b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
@@ -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 @@
 
 	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 @@
 {
 	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 @@
 	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 @@
 		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 --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c
index 2167be8..df7b805 100644
--- a/arch/arm/mach-omap2/clkt2xxx_osc.c
+++ b/arch/arm/mach-omap2/clkt2xxx_osc.c
@@ -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 --git a/arch/arm/mach-omap2/clkt2xxx_sys.c b/arch/arm/mach-omap2/clkt2xxx_sys.c
index 822b5a7..8693cfd 100644
--- a/arch/arm/mach-omap2/clkt2xxx_sys.c
+++ b/arch/arm/mach-omap2/clkt2xxx_sys.c
@@ -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 --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index aef6291..39f9d5a 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -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 @@
 			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 --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index 6ce512e..337392c 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -24,7 +24,6 @@
 #include <plat/clock.h>
 
 #include "clock.h"
-#include "cm.h"
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index b5babf5..2a2f152 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -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 --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index a535c7a..896584e 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -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 --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 21f8562..0a992bc 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -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 @@
 	.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 @@
 	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 @@
 	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 --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c
index 44d0ccc..d87bc9c 100644
--- a/arch/arm/mach-omap2/clock2430.c
+++ b/arch/arm/mach-omap2/clock2430.c
@@ -25,7 +25,7 @@
 
 #include "clock.h"
 #include "clock2xxx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
 
 /**
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index e32afcb..c047dcd 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -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 @@
 	.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 @@
 	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 @@
 	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 --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 6febd5f..287abc4 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -25,7 +25,7 @@
 
 #include "clock.h"
 #include "clock34xx.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /**
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
index b496a93..74116a3 100644
--- a/arch/arm/mach-omap2/clock3517.c
+++ b/arch/arm/mach-omap2/clock3517.c
@@ -25,7 +25,7 @@
 
 #include "clock.h"
 #include "clock3517.h"
-#include "cm.h"
+#include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
 /*
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index a447c4d..e9f66b6 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -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 @@
 
 	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 --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index d85ecd5..d3ab1c9e 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -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_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 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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	.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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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_3430ES2 | CK_AM35XX),
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 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 @@
 
 	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 --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 1599836..e8cb32f 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -30,11 +30,18 @@
 
 #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 "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 +54,9 @@
 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 +74,9 @@
 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 +276,71 @@
 	.set_rate	= &omap3_noncore_dpll_set_rate,
 };
 
-static struct clk dpll_abe_m2x2_ck = {
-	.name		= "dpll_abe_m2x2_ck",
+static struct clk dpll_abe_x2_ck = {
+	.name		= "dpll_abe_x2_ck",
 	.parent		= &dpll_abe_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.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_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		= &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 +390,10 @@
 	.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 +404,7 @@
 
 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 +448,22 @@
 	.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 +474,7 @@
 
 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 +485,15 @@
 	.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 +506,14 @@
 	.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 +523,13 @@
 };
 
 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 +548,13 @@
 };
 
 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 +566,7 @@
 
 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 +576,10 @@
 	.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 +590,21 @@
 
 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 +613,24 @@
 	.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 +648,12 @@
 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 +687,22 @@
 	.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 +711,10 @@
 	.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 +773,10 @@
 
 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 +844,48 @@
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static struct clk dpll_per_m2x2_ck = {
-	.name		= "dpll_per_m2x2_ck",
+static struct clk dpll_per_x2_ck = {
+	.name		= "dpll_per_x2_ck",
 	.parent		= &dpll_per_ck,
 	.ops		= &clkops_null,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap3_clkoutx2_recalc,
 };
 
-static struct clk dpll_per_m3_ck = {
-	.name		= "dpll_per_m3_ck",
-	.parent		= &dpll_per_ck,
-	.clksel		= dpll_per_m2_div,
-	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_PER,
-	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
+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_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		= &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_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_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_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 +894,10 @@
 	.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 +906,10 @@
 	.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 +918,10 @@
 	.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 +944,7 @@
 	.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 +962,21 @@
 	.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 +988,17 @@
 
 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 +1052,7 @@
 
 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 +1071,24 @@
 	.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 +1118,8 @@
 	.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 +1129,13 @@
 };
 
 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 +1236,8 @@
 	.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 +1305,13 @@
 	.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 +1445,7 @@
 	.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 +1475,7 @@
 	.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 +1532,14 @@
 };
 
 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 +1693,15 @@
 };
 
 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 +1820,7 @@
 	.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 +1840,7 @@
 	.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 +1851,7 @@
 	.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 +2156,7 @@
 	.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 +2187,7 @@
 	.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 +2532,6 @@
 	.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 +2586,16 @@
 	.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 +2606,26 @@
 	.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 +2750,13 @@
 };
 
 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 +2841,168 @@
 	.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 +3030,48 @@
 	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 +3117,26 @@
 	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 +3198,35 @@
 	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 +3242,10 @@
 	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 +3264,18 @@
 	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 --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 6fb61b1..e20b986 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -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 @@
  * 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 @@
  * 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 @@
  * 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 @@
 	}
 }
 
-/*
- * _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 */
@@ -409,7 +437,7 @@
 		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);
 	}
 
@@ -444,7 +472,7 @@
 		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);
 	}
 
@@ -480,7 +508,7 @@
 	}
 
 	/* 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));
 }
 
@@ -514,7 +542,7 @@
 		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 +581,7 @@
 		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 +624,7 @@
 			 "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 +667,7 @@
 	}
 
 	/* 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 +705,13 @@
 		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 +735,19 @@
 
 	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 +780,19 @@
 
 	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();
@@ -829,7 +837,7 @@
 			_clkdm_add_autodeps(clkdm);
 	}
 
-	_omap2_clkdm_set_hwsup(clkdm, 1);
+	_enable_hwsup(clkdm);
 
 	pwrdm_clkdm_state_switch(clkdm);
 }
@@ -857,7 +865,7 @@
 	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
@@ -891,7 +899,7 @@
  */
 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 +917,27 @@
 	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 +964,7 @@
  */
 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 +989,27 @@
 	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 --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
new file mode 100644
index 0000000..de3faa2
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -0,0 +1,149 @@
+/*
+ * 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;
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+	const u16 clktrctrl_mask;
+#endif
+	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 --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
deleted file mode 100644
index 8fc19ff..0000000
--- a/arch/arm/mach-omap2/clockdomains.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
new file mode 100644
index 0000000..e4a7133
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
@@ -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 --git a/arch/arm/mach-omap2/clockdomains44xx.h b/arch/arm/mach-omap2/clockdomains44xx.h
deleted file mode 100644
index 7e5ba0f..0000000
--- a/arch/arm/mach-omap2/clockdomains44xx.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
new file mode 100644
index 0000000..51920fc
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -0,0 +1,311 @@
+/*
+ * 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 "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 --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
index da51cc3..d70660e 100644
--- a/arch/arm/mach-omap2/cm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
@@ -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 --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 4f959a7..b912759 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -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 --git a/arch/arm/mach-omap2/cm-regbits-44xx.h b/arch/arm/mach-omap2/cm-regbits-44xx.h
index 0b72be4..9d47a05 100644
--- a/arch/arm/mach-omap2/cm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-44xx.h
@@ -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 --git a/arch/arm/mach-omap2/cm.c b/arch/arm/mach-omap2/cm.c
deleted file mode 100644
index 721c3b6..0000000
--- a/arch/arm/mach-omap2/cm.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
index a02ca30..a7bc096 100644
--- a/arch/arm/mach-omap2/cm.h
+++ b/arch/arm/mach-omap2/cm.h
@@ -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 --git a/arch/arm/mach-omap2/cm1_44xx.h b/arch/arm/mach-omap2/cm1_44xx.h
new file mode 100644
index 0000000..e2d7a56
--- /dev/null
+++ b/arch/arm/mach-omap2/cm1_44xx.h
@@ -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 --git a/arch/arm/mach-omap2/cm2_44xx.h b/arch/arm/mach-omap2/cm2_44xx.h
new file mode 100644
index 0000000..aa47450
--- /dev/null
+++ b/arch/arm/mach-omap2/cm2_44xx.h
@@ -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 --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
new file mode 100644
index 0000000..96954aa
--- /dev/null
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c
@@ -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 --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h
new file mode 100644
index 0000000..5e9ea5b
--- /dev/null
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h
@@ -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 --git a/arch/arm/mach-omap2/cm44xx.c b/arch/arm/mach-omap2/cm44xx.c
new file mode 100644
index 0000000..e96f53e
--- /dev/null
+++ b/arch/arm/mach-omap2/cm44xx.c
@@ -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 --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 3c35a87..48fc3f4 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -1,667 +1,31 @@
 /*
- * OMAP44xx CM1 & CM2 instance offset macros
+ * OMAP4 Clock Management (CM) definitions
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 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.
+ * 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_ARM_MACH_OMAP2_CM44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CM44XX_H
+#ifndef __ARCH_ASM_MACH_OMAP2_CM44XX_H
+#define __ARCH_ASM_MACH_OMAP2_CM44XX_H
 
 
-/* CM1 */
+#include "prcm-common.h"
+#include "cm.h"
 
-/* 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)
+#define OMAP4_CM_CLKSTCTRL				0x0000
 
-/* 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)
+/* Function prototypes */
+# ifndef __ASSEMBLER__
 
-/* 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)
+extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
 
-/* 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)
-
-/* 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)
-
-/* 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)
-
-/* 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)
-
-/* 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 --git a/arch/arm/mach-omap2/cm4xxx.c b/arch/arm/mach-omap2/cm4xxx.c
deleted file mode 100644
index f8a660a..0000000
--- a/arch/arm/mach-omap2/cm4xxx.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
new file mode 100644
index 0000000..c04bbbe
--- /dev/null
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -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 --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
new file mode 100644
index 0000000..a6abd0a
--- /dev/null
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -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 --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 1fa3294..6952794 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -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 @@
 	u32 sramldo4;
 	u32 sramldo5;
 	u32 csi;
+	u32 padconf_sys_nirq;
 };
 
 static struct omap3_control_regs control_context;
@@ -209,6 +214,37 @@
 	__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 __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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index b6c6b7c..f0629ae 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -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_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 --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 0d50b45..f3e043f 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -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"
@@ -293,25 +293,26 @@
 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 +453,18 @@
 	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 +517,10 @@
 		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 --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 5a0c148..381f4eb 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -638,6 +638,7 @@
 static void __init omap_hsmmc_reset(void)
 {
 	u32 i, nr_controllers;
+	struct clk *iclk, *fclk;
 
 	if (cpu_is_omap242x())
 		return;
@@ -647,7 +648,6 @@
 
 	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 @@
 		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 @@
 			 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 @@
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * 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();
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
new file mode 100644
index 0000000..d2f15f5
--- /dev/null
+++ b/arch/arm/mach-omap2/dma.c
@@ -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 IS_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 --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index ed8d330..f77022b 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -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,9 +223,33 @@
 }
 
 /**
- * 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
+ * @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_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
+{
+	unsigned long fint, clkinp; /* watch out for overflow */
+
+	clkinp = clk->parent->rate;
+	fint = (clkinp / n) * m;
+
+	if (fint < 1000000000)
+		*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
@@ -237,19 +259,13 @@
  * 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_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
 {
-	unsigned long fint, clkinp, sd; /* watch out for overflow */
+	unsigned long clkinp, sd; /* watch out for overflow */
 	int mod1, mod2;
 
 	clkinp = clk->parent->rate;
-	fint = (clkinp / n) * m;
 
-	if (fint < 1000000000)
-		*dco = 2;
-	else
-		*dco = 4;
 	/*
 	 * target sigma-delta to near 250MHz
 	 * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
@@ -278,6 +294,7 @@
 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 @@
 	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 --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c
index 6feeeae..911cd2e 100644
--- a/arch/arm/mach-omap2/dsp.c
+++ b/arch/arm/mach-omap2/dsp.c
@@ -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 @@
 	.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 --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
new file mode 100644
index 0000000..413de18
--- /dev/null
+++ b/arch/arm/mach-omap2/gpio.c
@@ -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 --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 7222096..2bb29c1 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -41,7 +41,7 @@
 		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 --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 7bb6922..3a7d25f 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -173,8 +173,17 @@
 	}
 
 	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 @@
 		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 @@
 		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 @@
 		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 --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index f46933b..1b7b3e7 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -168,6 +168,16 @@
 	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 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 --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index 06e64e1..befa321 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -38,41 +38,27 @@
  */
 
 #ifdef MULTI_OMAP2
-		.pushsection .data
-omap_irq_base:	.word	0
-		.popsection
 
-		/* Configure the interrupt base on the first interrupt */
+/*
+ * We use __glue to avoid errors with multiple definitions of
+ * .globl omap_irq_base as it's included from entry-armv.S but not
+ * from entry-common.S.
+ */
+#ifdef __glue
+		.pushsection .data
+		.globl	omap_irq_base
+omap_irq_base:
+		.word	0
+		.popsection
+#endif
+
+		/*
+		 * 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 +91,35 @@
 9999:
 		.endm
 
+#ifdef CONFIG_SMP
+		/* We assume that irqstat (the raw value of the IRQ acknowledge
+		 * register) is preserved from the macro above.
+		 * If there is an IPI, we immediately signal end of interrupt
+		 * on the controller, since this requires the original irqstat
+		 * value which we won't easily be able to recreate later.
+		 */
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		it	cc
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		it	cs
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* As above, this assumes that irqstat and base are preserved */
+
+		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov 	\tmp, #0
+		cmp	\irqnr, #29
+		itt	eq
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
+#endif	/* CONFIG_SMP */
 
 #else	/* MULTI_OMAP2 */
 
@@ -141,74 +156,16 @@
 
 
 #ifdef CONFIG_ARCH_OMAP4
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro  get_irqnr_preamble, base, tmp
 		ldr     \base, =OMAP4_IRQ_BASE
 		.endm
 
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an
-		 * interrupt if it's between 30 and 1020.  The test_for_ipi
-		 * routine below will pick up on IPIs.
-		 * A simple read from the controller will tell us the number
-		 * of the highest priority enabled interrupt.
-		 * We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-		ldr     \tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc   \irqnr, \irqnr
-		cmpne   \irqnr, \tmp
-		cmpcs   \irqnr, \irqnr
-		.endm
 #endif
+
 #endif	/* MULTI_OMAP2 */
 
-#ifdef CONFIG_SMP
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt
-		 * on the controller, since this requires the original irqstat
-		 * value which we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		it	cc
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		it	cs
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		itt	eq
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
-#endif	/* CONFIG_SMP */
-
 		.macro	irq_prio_table
 		.endm
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 2744dfe..5b0270b 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -24,7 +24,6 @@
 extern void __iomem *l2cache_base;
 #endif
 
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *gic_dist_base_addr;
 
 extern void __init gic_init_irq(void);
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index a1939b1..e66687b 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -39,13 +39,11 @@
 #include "io.h"
 
 #include <plat/omap-pm.h>
-#include <plat/powerdomain.h>
-#include "powerdomains.h"
+#include "powerdomain.h"
 
-#include <plat/clockdomain.h>
-#include "clockdomains.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,81 @@
 	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())
-		omap2420_hwmod_init();
-	else if (cpu_is_omap243x())
-		omap2430_hwmod_init();
+/*
+ * Initialize asm_irq_base for entry-macro.S
+ */
+static inline void omap_irq_base_init(void)
+{
+	extern void __iomem *omap_irq_base;
+
+#ifdef MULTI_OMAP2
+	if (cpu_is_omap24xx())
+		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE);
 	else if (cpu_is_omap34xx())
-		omap3xxx_hwmod_init();
+		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE);
 	else if (cpu_is_omap44xx())
-		omap44xx_hwmod_init();
+		omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE);
+	else
+		pr_err("Could not initialize omap_irq_base\n");
+#endif
+}
 
-	/* The OPP tables have to be registered before a clk init */
-	omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
+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()) {
+		omap2xxx_powerdomains_init();
+		omap2_clockdomains_init();
+		omap2430_hwmod_init();
+	} else if (cpu_is_omap34xx()) {
+		omap3xxx_powerdomains_init();
+		omap2_clockdomains_init();
+		omap3xxx_hwmod_init();
+	} else if (cpu_is_omap44xx()) {
+		omap44xx_powerdomains_init();
+		omap44xx_clockdomains_init();
+		omap44xx_hwmod_init();
+	} else {
+		pr_err("Could not init hwmod data - unknown SoC\n");
+        }
+
+	/* 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 +394,61 @@
 	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 --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 32eeabe..85bf8ca 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -284,7 +284,10 @@
 
 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 --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 40ddeca..394413d 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -281,7 +281,7 @@
 
 /* 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 +306,7 @@
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP3430)
+#if defined(CONFIG_ARCH_OMAP3)
 struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
 #endif
 
@@ -394,15 +394,19 @@
 
 	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 +436,8 @@
 		iounmap(mbox_base);
 		return ret;
 	}
-	return 0;
 
-	return ret;
+	return 0;
 }
 
 static int __devexit omap2_mbox_remove(struct platform_device *pdev)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 074536a..17bd639 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -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);
-	else
-		return __raw_readw(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;
 }
 
-void omap_mux_write(u16 val, u16 reg)
+u16 omap_mux_read(struct omap_mux_partition *partition, u16 reg)
 {
-	if (cpu_is_omap24xx())
-		__raw_writeb(val, mux_base + reg);
+	if (partition->flags & OMAP_MUX_REG_8BIT)
+		return __raw_readb(partition->base + reg);
 	else
-		__raw_writew(val, mux_base + reg);
+		return __raw_readw(partition->base + reg);
 }
 
-void omap_mux_write_array(struct omap_board_mux *board_mux)
+void omap_mux_write(struct omap_mux_partition *partition, u16 val,
+			   u16 reg)
 {
-	while (board_mux->reg_offset !=  OMAP_MUX_TERMINATOR) {
-		omap_mux_write(board_mux->value, board_mux->reg_offset);
+	if (partition->flags & OMAP_MUX_REG_8BIT)
+		__raw_writeb(val, partition->base + reg);
+	else
+		__raw_writew(val, partition->base + reg);
+}
+
+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(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 @@
 	}
 
 	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, mode0_len = 0;
+	struct list_head *muxmodes = &partition->muxmodes;
 
 	mode_name = strchr(muxname, '.');
 	if (mode_name) {
@@ -139,51 +171,200 @@
 		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 @@
 	} 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 @@
 			}
 			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_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 @@
 	.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 @@
 #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 @@
 	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 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_IWUGO, 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);
+	mux_dbg_board_dir = debugfs_create_dir("board", mux_dbg_dir);
+	if (!mux_dbg_board_dir)
+		return;
 
-	list_for_each_entry(e, &muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-
-		(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 @@
 /* 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 @@
 			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 @@
 			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 int __init omap_mux_copy_names(struct omap_mux *src,
-					struct omap_mux *dst)
+				      struct omap_mux *dst)
 {
 	int i;
 
@@ -592,51 +827,63 @@
 
 #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;
@@ -656,7 +903,7 @@
 #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 @@
  * 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 @@
 		}
 #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 @@
 		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,49 @@
 {
 }
 
-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)
-{
-	if (mux_base)
-		return -EBUSY;
+static u32 mux_partitions_cnt;
 
-	mux_phys = mux_pbase;
-	mux_base = ioremap(mux_pbase, mux_size);
-	if (!mux_base) {
-		printk(KERN_ERR "mux: Could not ioremap\n");
+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)
+{
+	struct omap_mux_partition *partition;
+
+	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);
 		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 --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 350c04f..a4ab17a 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -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 @@
 	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_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 @@
 	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 @@
 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 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 --git a/arch/arm/mach-omap2/mux2420.c b/arch/arm/mach-omap2/mux2420.c
index 414af54..cf6de097 100644
--- a/arch/arm/mach-omap2/mux2420.c
+++ b/arch/arm/mach-omap2/mux2420.c
@@ -678,11 +678,13 @@
 	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 --git a/arch/arm/mach-omap2/mux2430.c b/arch/arm/mach-omap2/mux2430.c
index 84d2c5a..4185f92 100644
--- a/arch/arm/mach-omap2/mux2430.c
+++ b/arch/arm/mach-omap2/mux2430.c
@@ -781,11 +781,13 @@
 		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 --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c
index 574e54e..440c98e 100644
--- a/arch/arm/mach-omap2/mux34xx.c
+++ b/arch/arm/mach-omap2/mux34xx.c
@@ -2049,12 +2049,13 @@
 		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 --git a/arch/arm/mach-omap2/mux44xx.c b/arch/arm/mach-omap2/mux44xx.c
new file mode 100644
index 0000000..980f11d
--- /dev/null
+++ b/arch/arm/mach-omap2/mux44xx.c
@@ -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)
+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)
+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)
+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 --git a/arch/arm/mach-omap2/mux44xx.h b/arch/arm/mach-omap2/mux44xx.h
new file mode 100644
index 0000000..c635026
--- /dev/null
+++ b/arch/arm/mach-omap2/mux44xx.h
@@ -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 --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
index 6cee456..4976b93 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -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 @@
  */
 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 --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index f5a1aad..3fc5dc7 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -33,9 +33,11 @@
 			.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 @@
 			.name = "iva2",
 			.nr_tlb_entries = 32,
 			.clk_name = "iva2_ck",
+			.da_start = 0x11000000,
+			.da_end = 0xFFFFF000,
 		},
 	},
 #endif
@@ -64,6 +68,8 @@
 			.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 @@
 			.name = "tesla",
 			.nr_tlb_entries = 32,
 			.clk_name = "tesla_ick",
+			.da_start = 0x0,
+			.da_end = 0xFFFFF000,
 		},
 	},
 #endif
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 9e9f70e..b66cfe8 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -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 @@
 	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 @@
 	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 @@
 		       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 @@
 	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 --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 2f89555..1926864 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -26,21 +26,22 @@
 void __iomem *l2cache_base;
 #endif
 
-void __iomem *gic_cpu_base_addr;
 void __iomem *gic_dist_base_addr;
 
 
 void __init gic_init_irq(void)
 {
+	void __iomem *gic_cpu_base;
+
 	/* Static mapping, never released */
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 	BUG_ON(!gic_dist_base_addr);
-	gic_dist_init(0, gic_dist_base_addr, 29);
 
 	/* Static mapping, never released */
-	gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
-	BUG_ON(!gic_cpu_base_addr);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
+	BUG_ON(!gic_cpu_base);
+
+	gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
 }
 
 #ifdef CONFIG_CACHE_L2X0
@@ -53,6 +54,8 @@
 
 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 @@
 	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 --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 5a30658..e282e35 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -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 @@
 
 	/* 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 @@
  * 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 @@
 
 	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 @@
  * 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 @@
 
 	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 @@
  * 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 @@
  * 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 @@
 	    (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 @@
 		_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 @@
  * @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 @@
 }
 
 /**
- * _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 @@
  * 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 @@
 	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 @@
 }
 
 /**
- * _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 @@
 	     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 @@
 			_enable_sysc(oh);
 		}
 	} else {
+		_disable_clocks(oh);
 		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
 			 oh->name, r);
 	}
@@ -1221,16 +1256,14 @@
 }
 
 /**
- * _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 @@
 	_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 @@
  */
 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 @@
 
 	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 @@
 	}
 	/* 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 @@
 /**
  * _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 @@
 		}
 	}
 
-	mutex_init(&oh->_mutex);
 	oh->_state = _HWMOD_STATE_INITIALIZED;
 
 	/*
@@ -1347,7 +1392,7 @@
 	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 @@
 
 		/*
 		 * 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 @@
 		}
 	}
 
-	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 @@
 }
 
 /**
- * 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 @@
 	if (!name)
 		return NULL;
 
-	mutex_lock(&omap_hwmod_mutex);
 	oh = _lookup(name);
-	mutex_unlock(&omap_hwmod_mutex);
 
 	return oh;
 }
@@ -1521,13 +1576,11 @@
 	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 @@
  * 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 @@
 	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 @@
 
 /**
  * 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 @@
 	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_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_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_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_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_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 @@
 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_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_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_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_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_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 @@
  * @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 @@
 	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 @@
 		}
 	}
 
-	mutex_unlock(&omap_hwmod_mutex);
-
 	if (ret)
 		pr_debug("omap_hwmod: %s: iterator terminated early: %d\n",
 			 __func__, ret);
@@ -2117,3 +2157,64 @@
 	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 --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index adf6e36..b85c630 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -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_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_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 @@
 	.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 @@
 	&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 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 @@
 	.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 @@
 	&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 @@
 {
 	return omap_hwmod_init(omap2420_hwmods);
 }
-
-
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 12d939e..8ecfbcd 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -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_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_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 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 @@
 	.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 @@
 	&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 @@
 {
 	return omap_hwmod_init(omap2430_hwmods);
 }
-
-
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index cb97ecf..8d81813 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -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_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 @@
 	.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 @@
 	&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 @@
 	.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 @@
 	.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 @@
 	&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 --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 7274db4d..c2806bd 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -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 @@
  * instance(s): dmm
  */
 static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
-	.name = "dmm",
+	.name	= "dmm",
 };
 
 /* dmm interface data */
@@ -67,7 +75,15 @@
 	.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 @@
 	.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 @@
  * 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 @@
 	.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 @@
  * 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 @@
 
 /* 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 @@
 	.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 @@
 
 /* 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 @@
 };
 
 /* 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 @@
 
 /* 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 @@
  * 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 @@
 
 /* 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 @@
  * 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 @@
 };
 
 /*
+ * 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,19 +1475,167 @@
 };
 
 /*
- * '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,
+};
+
+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 omap44xx_smartreflex_hwmod_class = {
+	.name	= "smartreflex",
+	.sysc	= &omap44xx_smartreflex_sysc,
+	.rev	= 2,
+};
+
+/* 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 },
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
+	{
+		.pa_start	= 0x4a0dd000,
+		.pa_end		= 0x4a0dd03f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* 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	= 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),
 };
 
 /*
@@ -477,34 +1647,17 @@
 	.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_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_wd_timer_hwmod_class = {
-	.name = "wd_timer",
-	.sysc = &omap44xx_wd_timer_sysc,
-};
-
-/* 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
-	},
-};
-
 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 @@
 	},
 };
 
-/* 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 @@
 	},
 };
 
-/* 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_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 @@
 	.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 --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h
new file mode 100644
index 0000000..46ac27d
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_opp_data.h
@@ -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 --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
new file mode 100644
index 0000000..745252c
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -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 --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
new file mode 100644
index 0000000..15f8c6c
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -0,0 +1,277 @@
+/**
+ * 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>
+
+#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
+
+unsigned long twl4030_vsel_to_uv(const u8 vsel)
+{
+	return (((vsel * 125) + 6000)) * 100;
+}
+
+u8 twl4030_uv_to_vsel(unsigned long uv)
+{
+	return DIV_ROUND_UP(uv - 600000, 12500);
+}
+
+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;
+}
+
+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 --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
new file mode 100644
index 0000000..ab8b35b
--- /dev/null
+++ b/arch/arm/mach-omap2/opp.c
@@ -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 --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
new file mode 100644
index 0000000..0486fce
--- /dev/null
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -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 --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
new file mode 100644
index 0000000..a11fa56
--- /dev/null
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -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 --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index a8afb61..125f565 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -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 @@
 
 #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 @@
 		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 @@
 	*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);
 	}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 59ca03b..d5a102c 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -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 @@
 	}
 }
 
+/* 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 @@
 		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 @@
 		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 @@
 
 	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 --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 0d75bfd..1c1b0ab 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -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 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 @@
 #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 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 --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index aaeea49..dac2d1d 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -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 @@
 {
 	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 @@
 
 	/* 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 @@
 	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);
@@ -167,30 +167,30 @@
 	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 @@
 	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 @@
 	 * 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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 	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 = {
 	.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 @@
 	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 @@
 	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 @@
 		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 --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 648b8c5..5b323f2 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -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 @@
 #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 @@
 	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 @@
 				       "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_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);
@@ -218,27 +212,27 @@
 		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 +275,9 @@
 	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 +298,10 @@
 			     "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 +351,7 @@
 	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 +390,7 @@
 	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();
 	}
 
@@ -408,9 +403,10 @@
 
 	/* 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 +417,7 @@
 		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 +426,7 @@
 	/*
 	* 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 +457,14 @@
 		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);
 	}
@@ -492,7 +488,8 @@
 	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 +526,6 @@
 }
 
 #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 +588,10 @@
 	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 +601,14 @@
 {
 	suspend_state = PM_SUSPEND_ON;
 	omap_uart_enable_irqs(1);
+	enable_hlt();
 	return;
 }
 
 static 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 +627,21 @@
 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 +649,13 @@
 			 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 +679,10 @@
 	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 +697,23 @@
 
 	/* 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 +746,7 @@
 		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 +755,13 @@
 		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 +770,17 @@
 		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 +804,7 @@
 		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 +816,16 @@
 	 * 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 +834,31 @@
 	 * 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 +866,7 @@
 			  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 +879,22 @@
 			  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 +911,29 @@
 		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 +1005,17 @@
 				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 +1025,8 @@
 	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 +1074,14 @@
 	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 =
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 54544b4..e9f4862c 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -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 @@
 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 @@
 	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 = {
 	.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 --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
new file mode 100644
index 0000000..171fccd
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -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 --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 6527ec3..eaed0df 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -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 @@
 	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 @@
 {
 	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 @@
 /**
  * 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 @@
  * 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_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
@@ -440,11 +406,10 @@
 	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_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_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_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_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
 {
-	u32 v;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
 		return -EINVAL;
@@ -522,17 +499,10 @@
 	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_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 {
-	u32 m;
+	int ret = -EINVAL;
 
 	if (!pwrdm)
 		return -EINVAL;
@@ -566,37 +536,10 @@
 	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;
-	}
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst)
+		ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst);
 
-	prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
-			     pwrdm->prcm_offs, pwrstctrl_reg_offs);
-
-	return 0;
+	return ret;
 }
 
 /**
@@ -617,7 +560,7 @@
  */
 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 @@
 	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;
-	}
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst)
+		ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst);
 
-	prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
-			     pwrstctrl_reg_offs);
-
-	return 0;
+	return ret;
 }
 
 /**
@@ -675,11 +591,15 @@
  */
 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_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_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_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_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_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_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 @@
 	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_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_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 @@
  */
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
 {
+	int ret = -EINVAL;
+
 	if (!pwrdm)
 		return -EINVAL;
 
@@ -1001,11 +854,10 @@
 	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_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?
-	 */
+	if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
+		ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
 
-	/* 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);
-
-	return 0;
+	return ret;
 }
 
 int pwrdm_state_switch(struct powerdomain *pwrdm)
@@ -1075,3 +910,31 @@
 	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 --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
new file mode 100644
index 0000000..c66431e
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -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 --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
new file mode 100644
index 0000000..d523389
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -0,0 +1,242 @@
+/*
+ * 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-regbits-34xx.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 --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
new file mode 100644
index 0000000..a7880af
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -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 --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h
deleted file mode 100644
index 105cbca..0000000
--- a/arch/arm/mach-omap2/powerdomains.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/powerdomains24xx.h b/arch/arm/mach-omap2/powerdomains24xx.h
deleted file mode 100644
index 775093a..0000000
--- a/arch/arm/mach-omap2/powerdomains24xx.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
new file mode 100644
index 0000000..5b4dd97
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
@@ -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 --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.h b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.h
new file mode 100644
index 0000000..fa31166
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.h
@@ -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 --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
new file mode 100644
index 0000000..9b1a335
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -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 --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h
deleted file mode 100644
index fa90486..0000000
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
new file mode 100644
index 0000000..e1bec56
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -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 --git a/arch/arm/mach-omap2/powerdomains44xx.h b/arch/arm/mach-omap2/powerdomains44xx.h
deleted file mode 100644
index 9c01b55..0000000
--- a/arch/arm/mach-omap2/powerdomains44xx.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
new file mode 100644
index 0000000..26d7641
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -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 --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index f81acee..87486f5 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -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 --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index a51846e..679bcd2 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -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 @@
 
 		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);
-}
+	/*
+	 * 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.
+	 */
 
-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);
-
-	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 @@
  *
  * 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 @@
 		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 --git a/arch/arm/mach-omap2/prcm44xx.h b/arch/arm/mach-omap2/prcm44xx.h
new file mode 100644
index 0000000..7334ffb
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm44xx.h
@@ -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 --git a/arch/arm/mach-omap2/prcm_mpu44xx.c b/arch/arm/mach-omap2/prcm_mpu44xx.c
new file mode 100644
index 0000000..171fe17
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.c
@@ -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 --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h
new file mode 100644
index 0000000..729a644
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.h
@@ -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	0x0000
+#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS	0x0000
+
+
+/*
+ * 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 --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h
index 0b188ff..6ac96610 100644
--- a/arch/arm/mach-omap2/prm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-24xx.h
@@ -14,7 +14,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "prm.h"
+#include "prm2xxx_3xxx.h"
 
 /* Bits shared between registers */
 
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 9e63cb7..64c087a 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -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 --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h
index 25b19b6..6d2776f 100644
--- a/arch/arm/mach-omap2/prm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-44xx.h
@@ -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 --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 7be040b..39d5621 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -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 @@
 #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 @@
 #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 --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index 421771e..ec03625 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -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 @@
 	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 @@
 		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 @@
 	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 --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
new file mode 100644
index 0000000..53d44f6
--- /dev/null
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -0,0 +1,367 @@
+/*
+ * 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__
+
+/* 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
+
+/*
+ * 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 --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index a1ff918..a2a04bfa 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -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 @@
 	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 --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 59839db..67a0d3f 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -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);
 
-/* 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
+
 #endif
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
new file mode 100644
index 0000000..a303242
--- /dev/null
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -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 --git a/arch/arm/mach-omap2/prminst44xx.h b/arch/arm/mach-omap2/prminst44xx.h
new file mode 100644
index 0000000..02dd66d
--- /dev/null
+++ b/arch/arm/mach-omap2/prminst44xx.h
@@ -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 --git a/arch/arm/mach-omap2/scrm44xx.h b/arch/arm/mach-omap2/scrm44xx.h
new file mode 100644
index 0000000..701bf2d
--- /dev/null
+++ b/arch/arm/mach-omap2/scrm44xx.h
@@ -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 --git a/arch/arm/mach-omap2/sdram-nokia.c b/arch/arm/mach-omap2/sdram-nokia.c
new file mode 100644
index 0000000..14caa22
--- /dev/null
+++ b/arch/arm/mach-omap2/sdram-nokia.c
@@ -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 --git a/arch/arm/mach-omap2/sdram-nokia.h b/arch/arm/mach-omap2/sdram-nokia.h
new file mode 100644
index 0000000..ee63da5
--- /dev/null
+++ b/arch/arm/mach-omap2/sdram-nokia.h
@@ -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 --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index 4c65f56..da6f3a6 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -27,8 +27,6 @@
 #include <plat/clock.h>
 #include <plat/sram.h>
 
-#include "prm.h"
-
 #include <plat/sdrc.h>
 #include "sdrc.h"
 
diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h
index 68f57bb..b3f8379 100644
--- a/arch/arm/mach-omap2/sdrc.h
+++ b/arch/arm/mach-omap2/sdrc.h
@@ -74,5 +74,4 @@
  */
 #define SDRC_MPURATE_LOOPS		96
 
-
 #endif
diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c
index 0f4d27a..ccdb010 100644
--- a/arch/arm/mach-omap2/sdrc2xxx.c
+++ b/arch/arm/mach-omap2/sdrc2xxx.c
@@ -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 @@
 	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 --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index d17960a..c645788 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -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 @@
 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 __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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 @@
 
 /**
  * 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 @@
 	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 @@
 	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;
@@ -857,7 +861,14 @@
 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 --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 2fb205a..98d8232 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -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_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,278 +149,55 @@
 	.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
-	/* Data memory barrier and Data sync barrier */
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c10, 4
-	mcr	p15, 0, r1, c7, c10, 5
+	beq	omap3_do_wfi
 
-	wfi				@ wait for interrupt
-
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	bl wait_sdrc_ok
-
-	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
-restore_es3:
-	/*b restore_es3*/		@ Enable to debug restore code
-	ldr	r5, pm_prepwstst_core_p
-	ldr	r4, [r5]
-	and	r4, r4, #0x3
-	cmp	r4, #0x0	@ Check if previous power state of CORE is OFF
-	bne	restore
-	adr	r0, es3_sdrc_fix
-	ldr	r1, sram_base
-	ldr	r2, es3_sdrc_fix_sz
-	mov	r2, r2, ror #2
-copy_to_sram:
-	ldmia	r0!, {r3}	@ val = *src
-	stmia	r1!, {r3}	@ *dst = val
-	subs	r2, r2, #0x1	@ num_words--
-	bne	copy_to_sram
-	ldr	r1, sram_base
-	blx	r1
-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
-	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
-	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation
-	bne	logic_l1_restore
-	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	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	r6, #0xff
-	ldr	r4, scratchpad_base
-	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
-	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	r6, #0xff
-	ldr	r4, scratchpad_base
-	ldr	r3, [r4, #0xBC]
-	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
-l2_inv_gp:
-	/* Execute smi to invalidate L2 cache */
-	mov r12, #0x1                         @ set up to invalide L2
-smi:    .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)
-	ldr	r4, scratchpad_base
-	ldr	r3, [r4,#0xBC]
-	ldr	r0, [r3,#12]
-	mov	r12, #0x2
-	.word 0xE1600070	@ Call SMI monitor (smieq)
-logic_l1_restore:
-	mov	r1, #0
-	/* Invalidate all instruction caches to PoU
-	 * and flush branch target cache */
-	mcr	p15, 0, r1, c7, c5, 0
-
-	ldr	r4, scratchpad_base
-	ldr	r3, [r4,#0xBC]
-	adds	r3, r3, #16
-	ldmia	r3!, {r4-r6}
-	mov	sp, r4
-	msr	spsr_cxsf, r5
-	mov	lr, r6
-
-	ldmia	r3!, {r4-r9}
-	/* Coprocessor access Control Register */
-	mcr p15, 0, r4, c1, c0, 2
-
-	/* TTBR0 */
-	MCR p15, 0, r5, c2, c0, 0
-	/* TTBR1 */
-	MCR p15, 0, r6, c2, c0, 1
-	/* Translation table base control register */
-	MCR p15, 0, r7, c2, c0, 2
-	/*domain access Control Register */
-	MCR p15, 0, r8, c3, c0, 0
-	/* data fault status Register */
-	MCR p15, 0, r9, c5, c0, 0
-
-	ldmia  r3!,{r4-r8}
-	/* instruction fault status Register */
-	MCR p15, 0, r4, c5, c0, 1
-	/*Data Auxiliary Fault Status Register */
-	MCR p15, 0, r5, c5, c1, 0
-	/*Instruction Auxiliary Fault Status Register*/
-	MCR p15, 0, r6, c5, c1, 1
-	/*Data Fault Address Register */
-	MCR p15, 0, r7, c6, c0, 0
-	/*Instruction Fault Address Register*/
-	MCR p15, 0, r8, c6, c0, 2
-	ldmia  r3!,{r4-r7}
-
-	/* user r/w thread and process ID */
-	MCR p15, 0, r4, c13, c0, 2
-	/* user ro thread and process ID */
-	MCR p15, 0, r5, c13, c0, 3
-	/*Privileged only thread and process ID */
-	MCR p15, 0, r6, c13, c0, 4
-	/* cache size selection */
-	MCR p15, 2, r7, c0, c0, 0
-	ldmia  r3!,{r4-r8}
-	/* Data TLB lockdown registers */
-	MCR p15, 0, r4, c10, c0, 0
-	/* Instruction TLB lockdown registers */
-	MCR p15, 0, r5, c10, c0, 1
-	/* Secure or Nonsecure Vector Base Address */
-	MCR p15, 0, r6, c12, c0, 0
-	/* FCSE PID */
-	MCR p15, 0, r7, c13, c0, 0
-	/* Context PID */
-	MCR p15, 0, r8, c13, c0, 1
-
-	ldmia  r3!,{r4-r5}
-	/* primary memory remap register */
-	MCR p15, 0, r4, c10, c2, 0
-	/*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 */
-
-	/* 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*/
-	and	r7, #0x7
-	cmp	r7, #0x0
-	beq	usettbr0
-ttbr_error:
-	/* More work needs to be done to support N[0:2] value other than 0
-	* So looping here so that the error can be detected
-	*/
-	b	ttbr_error
-usettbr0:
-	mrc	p15, 0, r2, c2, c0, 0
-	ldr	r5, ttbrbit_mask
-	and	r2, r5
-	mov	r4, pc
-	ldr	r5, table_index_mask
-	and	r4, r5 /* r4 = 31 to 20 bits of pc */
-	/* Extract the value to be written to table entry */
-	ldr	r1, table_entry
-	add	r1, r1, r4 /* r1 has value to be written to table entry*/
-	/* Getting the address of table entry to modify */
-	lsr	r4, #18
-	add	r2, r4 /* r2 has the location which needs to be modified */
-	/* 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 */
-	ldr	r5, scratchpad_base
-	str	r2, [r5, #0xC4]
-
-	mov	r0, #0
-	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
-	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
-	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
-	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
-	/* Restore control register  but dont enable caches here*/
-	/* Caches will be enabled after restoring MMU table entry */
-	ldmia	r3!, {r4}
-	/* Store previous value of control register in scratchpad */
-	str	r4, [r5, #0xC8]
-	ldr	r2, cache_pred_disable_mask
-	and	r4, r2
-	mcr	p15, 0, r4, c1, c0, 0
-
-	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+	/* Otherwise fall through to the save context code */
 save_context_wfi:
-	/*b	save_context_wfi*/	@ enable to debug save code
-	mov	r8, r0 /* Store SDRAM address in r8 */
+	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 */
+
+        /* 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
@@ -472,21 +213,27 @@
 	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 */
+	/*
+	 * 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*/
+	/*
+	 * 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 */
+	/*
+	 * 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
@@ -513,86 +260,51 @@
 	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
 
-	wfi                             @ wait for interrupt
+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
@@ -604,46 +316,421 @@
 	nop
 	nop
 	bl wait_sdrc_ok
-	/* restore regs and return */
-	ldmfd   sp!, {r0-r12, pc}
+
+/*
+ * ===================================
+ * == 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:
+	ldr	r5, pm_prepwstst_core_p
+	ldr	r4, [r5]
+	and	r4, r4, #0x3
+	cmp	r4, #0x0	@ Check if previous power state of CORE is OFF
+	bne	restore
+	adr	r0, es3_sdrc_fix
+	ldr	r1, sram_base
+	ldr	r2, es3_sdrc_fix_sz
+	mov	r2, r2, ror #2
+copy_to_sram:
+	ldmia	r0!, {r3}	@ val = *src
+	stmia	r1!, {r3}	@ *dst = val
+	subs	r2, r2, #0x1	@ num_words--
+	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:
+	/*
+	 * 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
+	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	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	r6, #0xff
+	ldr	r4, scratchpad_base
+	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
+	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	r6, #0xff
+	ldr	r4, scratchpad_base
+	ldr	r3, [r4, #0xBC]
+	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
+l2_inv_gp:
+	/* Execute smi to invalidate L2 cache */
+	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)
+	ldr	r4, scratchpad_base
+	ldr	r3, [r4,#0xBC]
+	ldr	r0, [r3,#12]
+	mov	r12, #0x2
+	.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
+	 */
+	mcr	p15, 0, r1, c7, c5, 0
+
+	ldr	r4, scratchpad_base
+	ldr	r3, [r4,#0xBC]
+	adds	r3, r3, #16
+	ldmia	r3!, {r4-r6}
+	mov	sp, r4
+	msr	spsr_cxsf, r5
+	mov	lr, r6
+
+	ldmia	r3!, {r4-r9}
+	/* Coprocessor access Control Register */
+	mcr p15, 0, r4, c1, c0, 2
+
+	/* TTBR0 */
+	MCR p15, 0, r5, c2, c0, 0
+	/* TTBR1 */
+	MCR p15, 0, r6, c2, c0, 1
+	/* Translation table base control register */
+	MCR p15, 0, r7, c2, c0, 2
+	/* Domain access Control Register */
+	MCR p15, 0, r8, c3, c0, 0
+	/* Data fault status Register */
+	MCR p15, 0, r9, c5, c0, 0
+
+	ldmia	r3!,{r4-r8}
+	/* Instruction fault status Register */
+	MCR p15, 0, r4, c5, c0, 1
+	/* Data Auxiliary Fault Status Register */
+	MCR p15, 0, r5, c5, c1, 0
+	/* Instruction Auxiliary Fault Status Register*/
+	MCR p15, 0, r6, c5, c1, 1
+	/* Data Fault Address Register */
+	MCR p15, 0, r7, c6, c0, 0
+	/* Instruction Fault Address Register*/
+	MCR p15, 0, r8, c6, c0, 2
+	ldmia	r3!,{r4-r7}
+
+	/* User r/w thread and process ID */
+	MCR p15, 0, r4, c13, c0, 2
+	/* User ro thread and process ID */
+	MCR p15, 0, r5, c13, c0, 3
+	/* Privileged only thread and process ID */
+	MCR p15, 0, r6, c13, c0, 4
+	/* Cache size selection */
+	MCR p15, 2, r7, c0, c0, 0
+	ldmia	r3!,{r4-r8}
+	/* Data TLB lockdown registers */
+	MCR p15, 0, r4, c10, c0, 0
+	/* Instruction TLB lockdown registers */
+	MCR p15, 0, r5, c10, c0, 1
+	/* Secure or Nonsecure Vector Base Address */
+	MCR p15, 0, r6, c12, c0, 0
+	/* FCSE PID */
+	MCR p15, 0, r7, c13, c0, 0
+	/* Context PID */
+	MCR p15, 0, r8, c13, c0, 1
+
+	ldmia	r3!,{r4-r5}
+	/* Primary memory remap register */
+	MCR p15, 0, r4, c10, c2, 0
+	/* 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
+
+	/* 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 */
+	and	r7, #0x7
+	cmp	r7, #0x0
+	beq	usettbr0
+ttbr_error:
+	/*
+	 * More work needs to be done to support N[0:2] value other than 0
+	 * So looping here so that the error can be detected
+	 */
+	b	ttbr_error
+usettbr0:
+	mrc	p15, 0, r2, c2, c0, 0
+	ldr	r5, ttbrbit_mask
+	and	r2, r5
+	mov	r4, pc
+	ldr	r5, table_index_mask
+	and	r4, r5			@ r4 = 31 to 20 bits of pc
+	/* Extract the value to be written to table entry */
+	ldr	r1, 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
+	/* 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
+	 */
+	ldr	r5, scratchpad_base
+	str	r2, [r5, #0xC4]
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
+	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
+	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
+	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
+	/*
+	 * Restore control register. This enables the MMU.
+	 * The caches and prediction are not enabled here, they
+	 * will be enabled after restoring the MMU table entry.
+	 */
+	ldmia	r3!, {r4}
+	/* Store previous value of control register in scratchpad */
+	str	r4, [r5, #0xC8]
+	ldr	r2, cache_pred_disable_mask
+	and	r4, r2
+	mcr	p15, 0, r4, c1, c0, 0
+
+/*
+ * ==============================
+ * == Exit point from OFF mode ==
+ * ==============================
+ */
+	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
+
+
+/*
+ * Internal functions
+ */
+
+/* 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 @@
 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 @@
 	.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 --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
new file mode 100644
index 0000000..60e7055
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -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 --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
new file mode 100644
index 0000000..77ecebf
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -0,0 +1,1029 @@
+/*
+ * 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(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 for sr_%s not found\n",
+			__func__, sr_info->voltdm->name);
+		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 for sr_%s not found\n",
+			__func__, sr_info->voltdm->name);
+		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__);
+		return -EINVAL;
+	}
+
+	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__);
+			return ret;
+		}
+	}
+
+	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)
+		return -EINVAL;
+
+	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__);
+		return PTR_ERR(dbg_dir);
+	}
+
+	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, 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__);
+		return PTR_ERR(nvalue_dir);
+	}
+
+	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);
+		return -ENODATA;
+	}
+
+	for (i = 0; i < sr_info->nvalue_count; i++) {
+		char *name;
+		char volt_name[32];
+
+		name = kzalloc(NVALUE_NAME_LEN + 1, GFP_KERNEL);
+		if (!name) {
+			dev_err(&pdev->dev, "%s: Unable to allocate memory"
+				" for n-value directory name\n",  __func__);
+			return -ENOMEM;
+		}
+
+		strcpy(name, "volt_");
+		sprintf(volt_name, "%d", volt_data[i].volt_nominal);
+		strcat(name, volt_name);
+		(void) debugfs_create_x32(name, S_IRUGO | S_IWUGO, 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 (!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 --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
new file mode 100644
index 0000000..786d685
--- /dev/null
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -0,0 +1,146 @@
+/*
+ * 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"
+
+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 --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S
index 92e6e1a..055310c 100644
--- a/arch/arm/mach-omap2/sram242x.S
+++ b/arch/arm/mach-omap2/sram242x.S
@@ -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 --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S
index ab49736..f900758 100644
--- a/arch/arm/mach-omap2/sram243x.S
+++ b/arch/arm/mach-omap2/sram243x.S
@@ -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 --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index 3637274..7f893a2 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -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 --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index e13c29e..4e48e78 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -195,7 +195,6 @@
 	.rating		= 300,
 	.read		= clocksource_read_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 24,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -203,7 +202,7 @@
 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 +215,10 @@
 
 	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))
+	if (clocksource_register_hz(&clocksource_gpt, tick_rate))
 		printk(err2, clocksource_gpt.name);
 }
 #endif
diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
index b11bf38..25eeada 100644
--- a/arch/arm/mach-omap2/usb-ehci.c
+++ b/arch/arm/mach-omap2/usb-ehci.c
@@ -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 @@
 	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 --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 7260558..5298949 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -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 @@
 	[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 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 @@
 	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 --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index 64a0112..8a3c05f 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -120,8 +120,8 @@
 	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 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	{ /* IRQ */
+		.name	= "mc",
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -223,7 +224,7 @@
 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 --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
new file mode 100644
index 0000000..ed6079c9
--- /dev/null
+++ b/arch/arm/mach-omap2/voltage.c
@@ -0,0 +1,1571 @@
+/*
+ * 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);
+	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 --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c
new file mode 100644
index 0000000..b0c4907
--- /dev/null
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -0,0 +1,54 @@
+/*
+ * 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>
+
+/*
+ * 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 --git a/arch/arm/mach-omap2/wd_timer.h b/arch/arm/mach-omap2/wd_timer.h
new file mode 100644
index 0000000..e0054a2
--- /dev/null
+++ b/arch/arm/mach-omap2/wd_timer.h
@@ -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 --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index c897e03..6604fc6 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -51,6 +51,13 @@
 	  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 --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
index eb6eabc..7f18cda 100644
--- a/arch/arm/mach-orion5x/Makefile
+++ b/arch/arm/mach-orion5x/Makefile
@@ -21,3 +21,4 @@
 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 --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h
index c47b033..c519610 100644
--- a/arch/arm/mach-orion5x/include/mach/io.h
+++ b/arch/arm/mach-orion5x/include/mach/io.h
@@ -38,8 +38,8 @@
 		__iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
-#define __arch_iounmap(a)	__arch_iounmap(a)
+#define __arch_ioremap		__arch_ioremap
+#define __arch_iounmap		__arch_iounmap
 #define __io(a)			__typesafe_io(a)
 #define __mem_pci(a)		(a)
 
diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
new file mode 100644
index 0000000..20a9b66
--- /dev/null
+++ b/arch/arm/mach-orion5x/ls-chl-setup.c
@@ -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 --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
index 9d1975f..a4a3819 100644
--- a/arch/arm/mach-pnx4008/clock.c
+++ b/arch/arm/mach-pnx4008/clock.c
@@ -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 --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index dd235ec..2fc9f94 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -50,6 +50,10 @@
 	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 @@
 	select PXA27x
 	select IWMMXT
 	select PXA25x
+	select MIGHT_HAVE_PCI
 
 config MACH_EM_X270
 	bool "CompuLab EM-x270 platform"
@@ -232,10 +237,6 @@
 	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 @@
 	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
@@ -540,6 +545,7 @@
 config ARCH_PXA_ESERIES
 	bool "PXA based Toshiba e-series PDAs"
 	select PXA25x
+	select FB_W100
 
 config MACH_E330
 	bool "Toshiba e330"
@@ -651,11 +657,17 @@
 	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 --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index e2f89c2..cc39d17 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -16,9 +16,10 @@
 # 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_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_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 --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 21e1889..ccb2d0c 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -567,27 +567,29 @@
  * 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 +601,33 @@
 	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 +642,11 @@
 	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 +688,7 @@
 	},
 	.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 +813,7 @@
 
 static void __init balloon3_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(balloon3_io_desc, ARRAY_SIZE(balloon3_io_desc));
 }
 
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
index 4bd7a3c..4284513 100644
--- a/arch/arm/mach-pxa/capc7117.c
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -149,7 +149,7 @@
 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 --git a/arch/arm/mach-pxa/clock-pxa2xx.c b/arch/arm/mach-pxa/clock-pxa2xx.c
new file mode 100644
index 0000000..1ce0904
--- /dev/null
+++ b/arch/arm/mach-pxa/clock-pxa2xx.c
@@ -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 --git a/arch/arm/mach-pxa/clock-pxa3xx.c b/arch/arm/mach-pxa/clock-pxa3xx.c
new file mode 100644
index 0000000..1b08a34
--- /dev/null
+++ b/arch/arm/mach-pxa/clock-pxa3xx.c
@@ -0,0 +1,218 @@
+/*
+ * 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);
+	unsigned int smcfs = (acsr >> 23) & 0x7;
+
+	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 --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index abba008..d515222 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -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 @@
 }
 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 --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index d848874..f9f349a 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -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 @@
 	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 @@
 		.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,12 +41,22 @@
 		.delay	= _delay,			\
 	}
 
-extern const struct clkops clk_cken_ops;
+#define DEFINE_PXA2_CKEN(_name, _cken, _rate, _delay)	\
+struct clk clk_##_name = {				\
+		.ops	= &clk_pxa2xx_cken_ops,		\
+		.rate	= _rate,			\
+		.cken	= CKEN_##_cken,			\
+		.delay	= _delay,			\
+	}
 
-void clk_cken_enable(struct clk *clk);
-void clk_cken_disable(struct clk *clk);
+extern const struct clkops clk_pxa2xx_cken_ops;
 
-#ifdef CONFIG_PXA3xx
+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	= &clk_pxa3xx_cken_ops,		\
@@ -56,14 +65,14 @@
 		.delay	= _delay,			\
 	}
 
-#define DEFINE_PXA3_CK(_name, _cken, _ops)		\
-struct clk clk_##_name = {				\
-		.ops	= _ops,				\
-		.cken	= CKEN_##_cken,			\
-	}
-
 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 --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c
index f1a7703..93f59f8 100644
--- a/arch/arm/mach-pxa/cm-x255.c
+++ b/arch/arm/mach-pxa/cm-x255.c
@@ -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 --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index a9926bb..b88d601a 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -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 --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index d34b99f..b734d84 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -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 @@
 	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 @@
 	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 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 @@
 #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 --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 922b107..7984268 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -857,7 +857,7 @@
 
 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 --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c
new file mode 100644
index 0000000..6b2c800
--- /dev/null
+++ b/arch/arm/mach-pxa/colibri-evalboard.c
@@ -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 =
+			GPIO39_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 --git a/arch/arm/mach-pxa/colibri-pxa270-evalboard.c b/arch/arm/mach-pxa/colibri-pxa270-evalboard.c
deleted file mode 100644
index 0f3b632..0000000
--- a/arch/arm/mach-pxa/colibri-pxa270-evalboard.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c
index 37f0f3e..07b62a0 100644
--- a/arch/arm/mach-pxa/colibri-pxa270-income.c
+++ b/arch/arm/mach-pxa/colibri-pxa270-income.c
@@ -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 @@
 
 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 --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index bc04510..6fc5d32 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -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 @@
 	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 @@
 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_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 --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index a70b256..fddb16d 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -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,
+	GPIO39_GPIO,	/* 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 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 @@
 
 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 --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index ca5f29e..ff9ff5f 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -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 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 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 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 --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c
index 199afa2..96b2d9f 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -64,55 +64,6 @@
 }
 #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 --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 821229ac..a5452a3 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -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 @@
 #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 @@
 #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 @@
 #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 --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
index 58093d9..6a7aeab 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
@@ -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 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 @@
 	 * 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 @@
 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 --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 57cacaf..a305424 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -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 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 @@
 
 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 --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index aaa1166..4c766e3 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -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 @@
 };
 #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 @@
 #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 @@
 {
 	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 @@
 	.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 @@
 	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 @@
 	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,
 	},
-};
-
-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,
+	[2] = {
+		/* DRCMR for RX */
+		.start	= 2,
+		.end	= 2,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		/* DRCMR for TX */
+		.start	= 3,
+		.end	= 3,
+		.flags	= IORESOURCE_DMA,
 	},
 };
 
-#endif /* CONFIG_PXA3xx */
+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),
+};
+#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 --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index ed0dbfdb..a78bb30 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -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 @@
 
 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_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 --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index b25690c..edca0a0 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -181,7 +181,7 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 142c711..87cec0a 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -798,7 +798,7 @@
 
 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 @@
 
 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 @@
 
 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 @@
 
 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 @@
 
 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 @@
 
 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 --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 6451e9c..d6e15f7 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -28,6 +28,8 @@
 
 #include <mach/reset.h>
 #include <mach/gpio.h>
+#include <mach/smemc.h>
+#include <mach/pxa3xx-regs.h>
 
 #include "generic.h"
 
@@ -35,9 +37,10 @@
 {
 	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 +74,17 @@
 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 +95,5 @@
 
 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 --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 4b1ad27..6205dc9 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -20,7 +20,12 @@
 #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 +37,14 @@
 
 #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 +55,8 @@
 
 #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 --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index 1e2a9a1..6fd319e 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -225,7 +225,7 @@
 
 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 --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index 7057a1f..657db46 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -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 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 @@
 
 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 --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
index 01b7f07..e8603eb 100644
--- a/arch/arm/mach-pxa/himalaya.c
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -160,7 +160,7 @@
 
 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 --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index 76d93a2..a908e0a 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -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 @@
 
 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 --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index d51ee3d..6cedc81 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -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 @@
 
 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 --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index e773dce..dd40e4a 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -187,7 +187,7 @@
 
 static void __init idp_map_io(void)
 {
-	pxa_map_io();
+	pxa25x_map_io();
 	iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
 }
 
diff --git a/arch/arm/mach-pxa/include/mach/addr-map.h b/arch/arm/mach-pxa/include/mach/addr-map.h
new file mode 100644
index 0000000..f4c0365
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/addr-map.h
@@ -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 --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h
index 561562b..7074e76 100644
--- a/arch/arm/mach-pxa/include/mach/balloon3.h
+++ b/arch/arm/mach-pxa/include/mach/balloon3.h
@@ -26,6 +26,8 @@
 #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 @@
 #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 @@
 #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 --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h
index 58dada1..388a96f 100644
--- a/arch/arm/mach-pxa/include/mach/colibri.h
+++ b/arch/arm/mach-pxa/include/mach/colibri.h
@@ -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 @@
 #define GPIO0_COLIBRI_PXA270_SD_DETECT	0
 #define GPIO113_COLIBRI_PXA270_TS_IRQ	113
 
+/* GPIO definitions for Colibri PXA300/310 */
+#define GPIO39_COLIBRI_PXA300_SD_DETECT	39
+
+/* GPIO definitions for Colibri PXA320 */
+#define GPIO28_COLIBRI_PXA320_SD_DETECT	28
+
 #endif /* _COLIBRI_H_ */
 
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index 814f145..6957ba5 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -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 --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index d372caa..a4285fc 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -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 --git a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
index 4fcddd9..ee6ced1 100644
--- a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
+++ b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
@@ -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 --git a/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h b/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h
deleted file mode 100644
index b87cecd..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h
+++ /dev/null
@@ -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 --git a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
index e91d63c..e4fb4668 100644
--- a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
@@ -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 --git a/arch/arm/mach-pxa/include/mach/regs-intc.h b/arch/arm/mach-pxa/include/mach/regs-intc.h
index 68464ce..662288e 100644
--- a/arch/arm/mach-pxa/include/mach/regs-intc.h
+++ b/arch/arm/mach-pxa/include/mach/regs-intc.h
@@ -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 --git a/arch/arm/mach-pxa/include/mach/smemc.h b/arch/arm/mach-pxa/include/mach/smemc.h
new file mode 100644
index 0000000..654adc9
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/smemc.h
@@ -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 --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 1beb40f..54e91c9 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -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,14 +48,27 @@
 
 static int pxa_internal_irq_nr;
 
+static inline int cpu_has_ipr(void)
+{
+	return !cpu_is_pxa25x();
+}
+
 static void pxa_mask_irq(unsigned int irq)
 {
-	_ICMR(irq) &= ~(1 << IRQ_BIT(irq));
+	void __iomem *base = get_irq_chip_data(irq);
+	uint32_t icmr = __raw_readl(base + ICMR);
+
+	icmr &= ~(1 << IRQ_BIT(irq));
+	__raw_writel(icmr, base + ICMR);
 }
 
 static void pxa_unmask_irq(unsigned int irq)
 {
-	_ICMR(irq) |= 1 << IRQ_BIT(irq);
+	void __iomem *base = get_irq_chip_data(irq);
+	uint32_t icmr = __raw_readl(base + ICMR);
+
+	icmr |= 1 << IRQ_BIT(irq);
+	__raw_writel(icmr, base + ICMR);
 }
 
 static struct irq_chip pxa_internal_irq_chip = {
@@ -86,12 +110,16 @@
 
 static void pxa_mask_low_gpio(unsigned int irq)
 {
-	ICMR &= ~(1 << (irq - PXA_IRQ(0)));
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	desc->chip->mask(irq);
 }
 
 static void pxa_unmask_low_gpio(unsigned int irq)
 {
-	ICMR |= 1 << (irq - PXA_IRQ(0));
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	desc->chip->unmask(irq);
 }
 
 static struct irq_chip pxa_low_gpio_chip = {
@@ -120,33 +148,45 @@
 	pxa_low_gpio_chip.set_wake = fn;
 }
 
+static inline void __iomem *irq_base(int i)
+{
+	static unsigned long phys_base[] = {
+		0x40d00000,
+		0x40d0009c,
+		0x40d00130,
+	};
+
+	return (void __iomem *)io_p2v(phys_base[i >> 5]);
+}
+
 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);
 
-	/* 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_init_low_gpio_irq(fn);
@@ -158,16 +198,18 @@
 
 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; i += 32) {
+		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 +217,20 @@
 
 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 += 32) {
+		void __iomem *base = irq_base(i);
+
+		__raw_writel(saved_icmr[i], base + ICMR);
+		__raw_writel(0, base + ICLR);
+	}
+
+	if (!cpu_is_pxa25x())
 		for (i = 0; i < pxa_internal_irq_nr; i++)
-			IPR(i) = saved_ipr[i];
-	}
+			__raw_writel(saved_ipr[i], IRQ_BASE + IPR(i));
 
-	for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
-		_ICMR(irq) = saved_icmr[i];
-		_ICLR(irq) = 0;
-	}
-
-	ICCR = 1;
+	__raw_writel(1, IRQ_BASE + ICCR);
 	return 0;
 }
 #else
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 41aa89e..ccb7bfa 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -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 @@
 
 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 --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 623af02..8ab62a6 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -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"
@@ -463,7 +464,7 @@
 	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 +496,7 @@
 
 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 --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 1499493..3072dbe 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -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"
@@ -525,7 +526,7 @@
 	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 +550,7 @@
 
 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 --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 9066376..41198f0 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -765,7 +765,7 @@
 
 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 --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index a980a5c..740c035 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -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"
@@ -565,7 +566,7 @@
 	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 +615,7 @@
 
 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 --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index f5fb915..faafea3 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -819,7 +819,7 @@
 
 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 --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index 116167aa..59cce78 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -94,7 +94,7 @@
 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 --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index ce092c5..a6f898c 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -313,7 +313,7 @@
 
 static void __init palmld_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(palmld_io_desc, ARRAY_SIZE(palmld_io_desc));
 }
 
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 862da81..df4d7d0 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -203,7 +203,7 @@
 
 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 --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index 2131d58..a09a237 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -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 @@
 /******************************************************************************
  * 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 @@
 	.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 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 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 @@
 		.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 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 @@
 	.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 @@
 	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 --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index a9dae7b..3f25014 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -374,7 +374,7 @@
 
 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 --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 00e2d7b..8aadad5 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -442,7 +442,7 @@
 
 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_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 --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index e5c9932..595f002 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -334,7 +334,7 @@
 
 static void __init palmtx_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 	iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
 }
 
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index af6203f..7bf4017 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -280,7 +280,7 @@
 
 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 --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index c77e8f3..1fc8a66 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -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_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 
 	/* initialize sleep mode regs (wake-up sources, etc) */
 	PGSR0 = 0x01308000;
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 93a191c..4f0ff1a 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -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 @@
 
 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 --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index de53f2e..3f5241c 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -23,6 +23,7 @@
 #include <linux/suspend.h>
 #include <linux/sysdev.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/gpio.h>
@@ -30,6 +31,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 +92,21 @@
 	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 +160,30 @@
  * 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 +204,12 @@
 	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 +222,17 @@
  */
 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);
 }
 
@@ -320,6 +320,22 @@
 }
 #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,
@@ -339,7 +355,9 @@
 		.cls	= &pxa2xx_mfp_sysclass,
 	}, {
 		.cls	= &pxa_gpio_sysclass,
-	},
+	}, {
+		.cls	= &pxa2xx_clock_sysclass,
+	}
 };
 
 static int __init pxa25x_init(void)
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index d1fbf29..b2130b7 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -17,7 +17,9 @@
 #include <linux/suspend.h>
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
+#include <linux/io.h>
 
+#include <asm/mach/map.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
@@ -27,6 +29,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 +111,9 @@
 }
 
 /*
- * 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 +132,15 @@
 	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 +166,38 @@
 }
 
 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 +226,7 @@
 	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 +258,6 @@
  */
 enum {
 	SLEEP_SAVE_PSTR,
-	SLEEP_SAVE_CKEN,
 	SLEEP_SAVE_MDREFR,
 	SLEEP_SAVE_PCFR,
 	SLEEP_SAVE_COUNT
@@ -254,21 +265,19 @@
 
 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);
 }
 
@@ -370,6 +379,27 @@
 	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 +435,9 @@
 		.cls	= &pxa2xx_mfp_sysclass,
 	}, {
 		.cls	= &pxa_gpio_sysclass,
-	},
+	}, {
+		.cls	= &pxa2xx_clock_sysclass,
+	}
 };
 
 static int __init pxa27x_init(void)
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index d1c747c..e14818f 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -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_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 @@
 	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 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 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,
 };
@@ -580,6 +384,22 @@
 	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 @@
 		.cls	= &pxa3xx_mfp_sysclass,
 	}, {
 		.cls	= &pxa_gpio_sysclass,
-	},
+	}, {
+		.cls	= &pxa3xx_clock_sysclass,
+	}
 };
 
 static int __init pxa3xx_init(void)
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c
index 7d29dd3..8aeacf9 100644
--- a/arch/arm/mach-pxa/pxa930.c
+++ b/arch/arm/mach-pxa/pxa930.c
@@ -192,7 +192,7 @@
 
 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 --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
new file mode 100644
index 0000000..437980f
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -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 --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 4121d03..8361151 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -588,6 +588,9 @@
 	.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 @@
 		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 @@
 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_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_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 --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index ffa50e6..c1ca8cb 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -597,7 +597,7 @@
 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 --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
new file mode 100644
index 0000000..e497922
--- /dev/null
+++ b/arch/arm/mach-pxa/saarb.c
@@ -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 --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 8fed027..e68d46d 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -579,7 +579,8 @@
 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;
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 52c30b0..c551da8 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -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
@@ -353,8 +353,8 @@
 
 	@ Let us ensure we jump to resume_after_mmu only when the mcr above
 	@ actually took effect.  They call it the "cpwait" operation.
-	mrc	p15, 0, r1, c2, c0, 0		@ queue a dependency on CP15
-	sub	pc, r2, r1, lsr #32		@ jump to virtual addr
+	mrc	p15, 0, r0, c2, c0, 0		@ queue a dependency on CP15
+	sub	pc, r2, r0, lsr #32		@ jump to virtual addr
 	nop
 	nop
 	nop
diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c
index d6f6904..232b731 100644
--- a/arch/arm/mach-pxa/smemc.c
+++ b/arch/arm/mach-pxa/smemc.c
@@ -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 @@
 	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 --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index f736119..0bc9387 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -23,10 +23,11 @@
 #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/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
+#include <linux/io.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -41,9 +42,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 +930,10 @@
 
 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 +982,7 @@
 #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 +992,7 @@
 #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 +1002,7 @@
 #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 --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 738adc1..9a14fdb 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -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 @@
 {
 	/* 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 @@
 
 #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 @@
 
 #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 --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 2ea7545..9cecf83 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -490,7 +490,7 @@
 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 --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
index dc30116..70191a9 100644
--- a/arch/arm/mach-pxa/tavorevb3.c
+++ b/arch/arm/mach-pxa/tavorevb3.c
@@ -127,7 +127,7 @@
 
 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 --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 293e40a..e7f64d9 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -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 @@
 	.rating         = 200,
 	.read           = pxa_read_oscr,
 	.mask           = CLOCKSOURCE_MASK(32),
-	.shift          = 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -145,7 +133,7 @@
 	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 @@
 		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 --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 0ee1df4..af152e7 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -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>
@@ -893,9 +894,11 @@
 
 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 +956,7 @@
 
 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 --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 565d062..423261d 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -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_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 --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 438fc9a..de69b20 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -983,7 +983,7 @@
 
 static void __init viper_map_io(void)
 {
-	pxa_map_io();
+	pxa25x_map_io();
 
 	iotable_init(viper_io_desc, ARRAY_SIZE(viper_io_desc));
 
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index f45ac09..b9b5797 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -719,7 +719,7 @@
 
 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 --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index 3260ce7..51c0281 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -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 @@
 
 	/* 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 @@
 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 --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index fefde98..a323e07 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -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 @@
 
 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 --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index dea46a2..bf034c7 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -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"
 
@@ -823,13 +824,16 @@
 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 void __init zeus_map_io(void)
 {
-	pxa_map_io();
+	pxa27x_map_io();
 
 	iotable_init(zeus_io_desc, ARRAY_SIZE(zeus_io_desc));
 
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 702f7a6..a4c784a 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -423,7 +423,7 @@
 
 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 --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 07c0815..1c6602c 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -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,16 +47,14 @@
 
 #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 <plat/sched_clock.h>
 
 #include "core.h"
 
-/* used by entry-macro.S and platsmp.c */
-void __iomem *gic_cpu_base_addr;
-
 #ifdef CONFIG_ZONE_DMA
 /*
  * Adjust the zones if there are restrictions for DMA access.
@@ -658,6 +656,12 @@
 #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 @@
 {
 	u32 val;
 
+	versatile_sched_clock_init(REFCOUNTER, 24000000);
+
 	/* 
 	 * set clock frequency: 
 	 *	REALVIEW_REFCLK is 32KHz
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 781bca6..693239d 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -53,7 +53,6 @@
 extern struct mmci_platform_data realview_mmc0_plat_data;
 extern struct mmci_platform_data realview_mmc1_plat_data;
 extern struct clcd_board clcd_plat_data;
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *timer0_va_base;
 extern void __iomem *timer1_va_base;
 extern void __iomem *timer2_va_base;
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
index f95521a..a87523d 100644
--- a/arch/arm/mach-realview/hotplug.c
+++ b/arch/arm/mach-realview/hotplug.c
@@ -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 @@
 	"	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 @@
 	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 @@
 		}
 
 		/*
-		 * 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 @@
  */
 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 --git a/arch/arm/mach-realview/include/mach/entry-macro.S b/arch/arm/mach-realview/include/mach/entry-macro.S
index 340a5c2..4071164 100644
--- a/arch/arm/mach-realview/include/mach/entry-macro.S
+++ b/arch/arm/mach-realview/include/mach/entry-macro.S
@@ -8,74 +8,11 @@
  * warranty of any kind, whether express or implied.
  */
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
 
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
 
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h
index d3cd265..c8221b3 100644
--- a/arch/arm/mach-realview/include/mach/smp.h
+++ b/arch/arm/mach-realview/include/mach/smp.h
@@ -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 --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 0092658..a22bf67 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -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 @@
  */
 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)
 {
 	if (machine_is_realview_eb_mp())
@@ -50,33 +62,22 @@
 		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 @@
 	 * 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 @@
 	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();
+	void __iomem *scu_base = scu_base_addr();
+	unsigned int i, ncores;
 
-	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_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 @@
 		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 @@
 	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) {
-		/*
-		 * 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());
 
-		scu_enable(scu_base_addr());
-		poke_milo();
-	}
+	/*
+	 * 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.
+	 */
+	__raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
+		     __io_address(REALVIEW_SYS_FLAGSSET));
 }
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index f269710..6ef5c5e 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -364,21 +364,19 @@
 		writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
 		/* core tile GIC, primary */
-		gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
-		gic_cpu_init(0, gic_cpu_base_addr);
+		gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
 
 #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
 		/* board GIC, secondary */
-		gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
-		gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
+		gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB_GIC_CPU_BASE));
 		gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
 #endif
 	} else {
 		/* board GIC, primary */
-		gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
-		gic_cpu_init(0, gic_cpu_base_addr);
+		gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+			 __io_address(REALVIEW_EB_GIC_CPU_BASE));
 	}
 }
 
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index a412561..cbdc97a 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -304,13 +304,14 @@
 static void __init gic_init_irq(void)
 {
 	/* ARM1176 DevChip GIC, primary */
-	gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, IRQ_DC1176_GIC_START,
+		 __io_address(REALVIEW_DC1176_GIC_DIST_BASE),
+		 __io_address(REALVIEW_DC1176_GIC_CPU_BASE));
 
 	/* board GIC, secondary */
-	gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
-	gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
+	gic_init(1, IRQ_PB1176_GIC_START,
+		 __io_address(REALVIEW_PB1176_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
 	gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
 }
 
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 117b95b..8e8ab7d 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -309,13 +309,13 @@
 	writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
 	/* ARM11MPCore test chip GIC, primary */
-	gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE),
+		 __io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
 
 	/* board GIC, secondary */
-	gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
-	gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
+	gic_init(1, IRQ_PB11MP_GIC_START,
+		 __io_address(REALVIEW_PB11MP_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
 	gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
 }
 
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 929b8dc..841118e 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -273,9 +273,9 @@
 static void __init gic_init_irq(void)
 {
 	/* ARM PB-A8 on-board GIC */
-	gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE);
-	gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START);
-	gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
+	gic_init(0, IRQ_PBA8_GIC_START,
+		 __io_address(REALVIEW_PBA8_GIC_DIST_BASE),
+		 __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
 }
 
 static void __init realview_pba8_timer_init(void)
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index b9f9e20..02b755b 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -313,15 +313,12 @@
 {
 	/* ARM PBX on-board GIC */
 	if (core_tile_pbx11mp() || core_tile_pbxa9mp()) {
-		gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
-			      29);
-		gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
+		gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+			 __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
 	} else {
-		gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE);
-		gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE),
-			      IRQ_PBX_GIC_START);
-		gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE));
+		gic_init(0, IRQ_PBX_GIC_START,
+			 __io_address(REALVIEW_PBX_GIC_DIST_BASE),
+			 __io_address(REALVIEW_PBX_GIC_CPU_BASE));
 	}
 }
 
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
index 6983cb4..e82ab4a 100644
--- a/arch/arm/mach-s3c2412/Kconfig
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -59,7 +59,7 @@
 	  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 --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index 82ce4aa..72ab289 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -24,8 +24,6 @@
 
 #include <mach/regs-irq.h>
 
-void __iomem *gic_cpu_base_addr;
-
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -122,9 +120,7 @@
 {
 	int irq;
 
-	gic_cpu_base_addr = S5P_VA_GIC_CPU;
-	gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
-	gic_cpu_init(0, S5P_VA_GIC_CPU);
+	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c
index 03652c3..afa5392 100644
--- a/arch/arm/mach-s5pv310/hotplug.c
+++ b/arch/arm/mach-s5pv310/hotplug.c
@@ -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;
@@ -33,13 +30,13 @@
 	 * Turn off coherency
 	 */
 	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, #0x20\n"
+	"	bic	%0, %0, %2\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	"	mrc	p15, 0, %0, c1, c0, 0\n"
 	"	bic	%0, %0, #0x04\n"
 	"	mcr	p15, 0, %0, c1, c0, 0\n"
 	  : "=&r" (v)
-	  : "r" (0)
+	  : "r" (0), "Ir" (CR_C)
 	  : "cc");
 }
 
@@ -49,17 +46,17 @@
 
 	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 @@
 		}
 
 		/*
-		 * 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 @@
  */
 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 --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
index b7ec252..393ccbd 100644
--- a/arch/arm/mach-s5pv310/include/mach/smp.h
+++ b/arch/arm/mach-s5pv310/include/mach/smp.h
@@ -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 --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
index d357c19..34093b0 100644
--- a/arch/arm/mach-s5pv310/platsmp.c
+++ b/arch/arm/mach-s5pv310/platsmp.c
@@ -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 @@
 
 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 @@
 
 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 @@
 	 * 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 @@
 	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 @@
 		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 @@
 	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 --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c
index 01b012a..b262d46 100644
--- a/arch/arm/mach-s5pv310/time.c
+++ b/arch/arm/mach-s5pv310/time.c
@@ -211,7 +211,6 @@
 	.rating		= 250,
 	.read		= s5pv310_pwm4_read,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
 };
 
@@ -230,10 +229,7 @@
 	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 --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index 5da8c35..42625e4 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -118,6 +118,16 @@
 	  (also known as the LART).  See <http://www.lartmaker.nl/> for
 	  information on the LART.
 
+config SA1100_NANOENGINE
+	bool "nanoEngine"
+	select CPU_FREQ_SA1110
+	select PCI
+	select PCI_NANOENGINE
+	help
+	  Say Y here if you are using the Bright Star Engineering nanoEngine.
+	  See <http://www.brightstareng.com/arm/nanoeng.htm> for information
+	  on the BSE nanoEngine.
+
 config SA1100_PLEB
 	bool "PLEB"
 	select CPU_FREQ_SA1100
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 89349c1..e697691 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -37,6 +37,9 @@
 obj-$(CONFIG_SA1100_LART)		+= lart.o
 led-$(CONFIG_SA1100_LART)		+= leds-lart.o
 
+obj-$(CONFIG_SA1100_NANOENGINE)		+= nanoengine.o
+obj-$(CONFIG_PCI_NANOENGINE)		+= pci-nanoengine.o
+
 obj-$(CONFIG_SA1100_PLEB)		+= pleb.o
 
 obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index 96f7dc1..07d4e8b 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -94,48 +94,47 @@
 
 #include "generic.h"
 
-typedef struct {
+struct sa1100_dram_regs {
 	int speed;
 	u32 mdcnfg;
 	u32 mdcas0;
 	u32 mdcas1;
 	u32 mdcas2;
-} sa1100_dram_regs_t;
+};
 
 
 static struct cpufreq_driver sa1100_driver;
 
-static sa1100_dram_regs_t sa1100_dram_settings[] =
-{
-	/* speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2  clock frequency */
-	{  59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  59.0 MHz */
-	{  73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  73.7 MHz */
-	{  88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  88.5 MHz */
-	{ 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 103.2 MHz */
-	{ 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 118.0 MHz */
-	{ 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 132.7 MHz */
-	{ 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff }, /* 147.5 MHz */
-	{ 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff }, /* 162.2 MHz */
-	{ 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff }, /* 176.9 MHz */
-	{ 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff }, /* 191.7 MHz */
-	{ 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 206.4 MHz */
-	{ 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 221.2 MHz */
-	{ 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 }, /* 235.9 MHz */
-	{ 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 250.7 MHz */
-	{ 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 265.4 MHz */
-	{ 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 }, /* 280.2 MHz */
+static struct sa1100_dram_regs sa1100_dram_settings[] = {
+	/*speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2,   clock freq */
+	{ 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  59.0 MHz */
+	{ 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  73.7 MHz */
+	{ 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  88.5 MHz */
+	{103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
+	{118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
+	{132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
+	{147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
+	{162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
+	{176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
+	{191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
+	{206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
+	{221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
+	{235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
+	{250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
+	{265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
+	{280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
 	{ 0, 0, 0, 0, 0 } /* last entry */
 };
 
 static void sa1100_update_dram_timings(int current_speed, int new_speed)
 {
-	sa1100_dram_regs_t *settings = sa1100_dram_settings;
+	struct sa1100_dram_regs *settings = sa1100_dram_settings;
 
 	/* find speed */
 	while (settings->speed != 0) {
-		if(new_speed == settings->speed)
+		if (new_speed == settings->speed)
 			break;
-		
+
 		settings++;
 	}
 
@@ -149,7 +148,7 @@
 		/* We're going FASTER, so first relax the memory
 		 * timings before changing the core frequency
 		 */
-		
+
 		/* Half the memory access clock */
 		MDCNFG |= MDCNFG_CDB2;
 
@@ -187,7 +186,7 @@
 	struct cpufreq_freqs freqs;
 
 	new_ppcr = sa11x0_freq_to_ppcr(target_freq);
-	switch(relation){
+	switch (relation) {
 	case CPUFREQ_RELATION_L:
 		if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
 			new_ppcr--;
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 7252874..675bf8e 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -16,28 +16,24 @@
  *
  * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type
  */
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
 
-#include <mach/hardware.h>
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
+
+#include <mach/hardware.h>
 
 #include "generic.h"
 
 #undef DEBUG
 
-static struct cpufreq_driver sa1110_driver;
-
 struct sdram_params {
-	const char name[16];
+	const char name[20];
 	u_char  rows;		/* bits				 */
 	u_char  cas_latency;	/* cycles			 */
 	u_char  tck;		/* clock cycle time (ns)	 */
@@ -107,6 +103,15 @@
 		.twr		= 8,
 		.refresh	= 64000,
 		.cas_latency	= 3,
+	}, {	/* Micron MT48LC8M16A2TG-75 */
+		.name		= "MT48LC8M16A2TG-75",
+		.rows		= 12,
+		.tck		= 8,
+		.trcd		= 20,
+		.trp		= 20,
+		.twr		= 8,
+		.refresh	= 64000,
+		.cas_latency	= 3,
 	},
 };
 
@@ -180,11 +185,13 @@
 		sd->mdrefr |= MDREFR_K1DB2;
 
 	/* initial number of '1's in MDCAS + 1 */
-	set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
+	set_mdcas(sd->mdcas, sd_khz >= 62000,
+		ns_to_cycles(sdram->trcd, mem_khz));
 
 #ifdef DEBUG
-	printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
-		sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
+	printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
+		sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
+		sd->mdcas[2]);
 #endif
 }
 
@@ -213,7 +220,7 @@
 
 #ifdef DEBUG
 	mdelay(250);
-	printk("new dri value = %d\n", dri);
+	printk(KERN_DEBUG "new dri value = %d\n", dri);
 #endif
 
 	sdram_set_refresh(dri);
@@ -232,7 +239,7 @@
 	unsigned long flags;
 	unsigned int ppcr, unused;
 
-	switch(relation){
+	switch (relation) {
 	case CPUFREQ_RELATION_L:
 		ppcr = sa11x0_freq_to_ppcr(target_freq);
 		if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
@@ -280,11 +287,10 @@
 	 * We wait 20ms to be safe.
 	 */
 	sdram_set_refresh(2);
-	if (!irqs_disabled()) {
+	if (!irqs_disabled())
 		msleep(20);
-	} else {
+	else
 		mdelay(20);
-	}
 
 	/*
 	 * Reprogram the DRAM timings with interrupts disabled, and
@@ -295,7 +301,7 @@
 	local_irq_save(flags);
 	asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
 	udelay(10);
-	__asm__ __volatile__("					\n\
+	__asm__ __volatile__("\n\
 		b	2f					\n\
 		.align	5					\n\
 1:		str	%3, [%1, #0]		@ MDCNFG	\n\
@@ -336,7 +342,9 @@
 	return 0;
 }
 
-static struct cpufreq_driver sa1110_driver = {
+/* sa1110_driver needs __refdata because it must remain after init registers
+ * it with cpufreq_register_driver() */
+static struct cpufreq_driver sa1110_driver __refdata = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1110_target,
@@ -349,7 +357,8 @@
 {
 	struct sdram_params *sdram;
 
-	for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); sdram++)
+	for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
+	     sdram++)
 		if (strcmp(name, sdram->name) == 0)
 			return sdram;
 
@@ -369,14 +378,14 @@
 	if (!name[0]) {
 		if (machine_is_assabet())
 			name = "TC59SM716-CL3";
-
 		if (machine_is_pt_system3())
 			name = "K4S641632D";
-
 		if (machine_is_h3100())
 			name = "KM416S4030CT";
 		if (machine_is_jornada720())
-		        name = "K4S281632B-1H";
+			name = "K4S281632B-1H";
+		if (machine_is_nanoengine())
+			name = "MT48LC8M16A2TG-75";
 	}
 
 	sdram = sa1110_find_sdram(name);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 3c1fcd6..59d14f0 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -16,9 +16,7 @@
 #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>
@@ -110,27 +108,6 @@
 }
 
 /*
- * 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 +140,15 @@
 
 static struct resource sa11x0udc_resources[] = {
 	[0] = {
-		.start	= 0x80000000,
-		.end	= 0x8000ffff,
+		.start	= __PREG(Ser0UDCCR),
+		.end	= __PREG(Ser0UDCCR) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser0UDC,
+		.end	= IRQ_Ser0UDC,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0udc_dma_mask = 0xffffffffUL;
@@ -184,10 +166,15 @@
 
 static struct resource sa11x0uart1_resources[] = {
 	[0] = {
-		.start	= 0x80010000,
-		.end	= 0x8001ffff,
+		.start	= __PREG(Ser1UTCR0),
+		.end	= __PREG(Ser1UTCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser1UART,
+		.end	= IRQ_Ser1UART,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device sa11x0uart1_device = {
@@ -199,10 +186,15 @@
 
 static struct resource sa11x0uart3_resources[] = {
 	[0] = {
-		.start	= 0x80050000,
-		.end	= 0x8005ffff,
+		.start	= __PREG(Ser3UTCR0),
+		.end	= __PREG(Ser3UTCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser3UART,
+		.end	= IRQ_Ser3UART,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device sa11x0uart3_device = {
@@ -214,10 +206,15 @@
 
 static struct resource sa11x0mcp_resources[] = {
 	[0] = {
-		.start	= 0x80060000,
-		.end	= 0x8006ffff,
+		.start	= __PREG(Ser4MCCR0),
+		.end	= __PREG(Ser4MCCR0) + 0xffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser4MCP,
+		.end	= IRQ_Ser4MCP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
@@ -244,6 +241,11 @@
 		.end	= 0x8007ffff,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		.start	= IRQ_Ser4SSP,
+		.end	= IRQ_Ser4SSP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h
index 99f5856..967ae76 100644
--- a/arch/arm/mach-sa1100/include/mach/hardware.h
+++ b/arch/arm/mach-sa1100/include/mach/hardware.h
@@ -76,4 +76,12 @@
 #include "SA-1101.h"
 #endif
 
+#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
+#define PCIBIOS_MIN_IO		0
+#define PCIBIOS_MIN_MEM		0
+#define pcibios_assign_all_busses()	1
+#define HAVE_ARCH_PCI_SET_DMA_MASK	1
+#endif
+
+
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-sa1100/include/mach/nanoengine.h b/arch/arm/mach-sa1100/include/mach/nanoengine.h
new file mode 100644
index 0000000..14f8382
--- /dev/null
+++ b/arch/arm/mach-sa1100/include/mach/nanoengine.h
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-sa1100/include/mach/nanoengine.h
+ *
+ * This file contains the hardware specific definitions for nanoEngine.
+ * Only include this file from SA1100-specific files.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_ARCH_NANOENGINE_H
+#define __ASM_ARCH_NANOENGINE_H
+
+#include <mach/irqs.h>
+
+#define GPIO_PC_READY0	GPIO_GPIO(11) /* ready for socket 0 (active high)*/
+#define GPIO_PC_READY1	GPIO_GPIO(12) /* ready for socket 1 (active high) */
+#define GPIO_PC_CD0	GPIO_GPIO(13) /* detect for socket 0 (active low) */
+#define GPIO_PC_CD1	GPIO_GPIO(14) /* detect for socket 1 (active low) */
+#define GPIO_PC_RESET0	GPIO_GPIO(15) /* reset socket 0 */
+#define GPIO_PC_RESET1	GPIO_GPIO(16) /* reset socket 1 */
+
+#define NANOENGINE_IRQ_GPIO_PCI		IRQ_GPIO0
+#define NANOENGINE_IRQ_GPIO_PC_READY0	IRQ_GPIO11
+#define NANOENGINE_IRQ_GPIO_PC_READY1	IRQ_GPIO12
+#define NANOENGINE_IRQ_GPIO_PC_CD0	IRQ_GPIO13
+#define NANOENGINE_IRQ_GPIO_PC_CD1	IRQ_GPIO14
+
+/*
+ * nanoEngine Memory Map:
+ *
+ * 0000.0000 - 003F.0000 -   4 MB Flash
+ * C000.0000 - C1FF.FFFF -  32 MB SDRAM
+ * 1860.0000 - 186F.FFFF -   1 MB Internal PCI Memory Read/Write
+ * 18A1.0000 - 18A1.FFFF -  64 KB Internal PCI Config Space
+ * 4000.0000 - 47FF.FFFF - 128 MB External Bus I/O - Multiplexed Mode
+ * 4800.0000 - 4FFF.FFFF - 128 MB External Bus I/O - Non-Multiplexed Mode
+ *
+ */
+
+#define NANO_PCI_MEM_RW_PHYS		0x18600000
+#define NANO_PCI_MEM_RW_VIRT		0xf1000000
+#define NANO_PCI_MEM_RW_SIZE		SZ_1M
+#define NANO_PCI_CONFIG_SPACE_PHYS	0x18A10000
+#define NANO_PCI_CONFIG_SPACE_VIRT	0xf2000000
+#define NANO_PCI_CONFIG_SPACE_SIZE	SZ_64K
+
+#endif
+
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
new file mode 100644
index 0000000..72087f0
--- /dev/null
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -0,0 +1,119 @@
+/*
+ * linux/arch/arm/mach-sa1100/nanoengine.c
+ *
+ * Bright Star Engineering's nanoEngine board init code.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/root_dev.h>
+
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "generic.h"
+
+/* Flash bank 0 */
+static struct mtd_partition nanoengine_partitions[] = {
+	{
+		.name	= "nanoEngine boot firmware and parameter table",
+		.size		= 0x00010000,  /* 32K */
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "kernel/initrd reserved",
+		.size		= 0x002f0000,
+		.offset		= 0x00010000,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "experimental filesystem allocation",
+		.size		= 0x00100000,
+		.offset		= 0x00300000,
+		.mask_flags	= MTD_WRITEABLE,
+	}
+};
+
+static struct flash_platform_data nanoengine_flash_data = {
+	.map_name	= "jedec_probe",
+	.parts		= nanoengine_partitions,
+	.nr_parts	= ARRAY_SIZE(nanoengine_partitions),
+};
+
+static struct resource nanoengine_flash_resources[] = {
+	{
+		.start	= SA1100_CS0_PHYS,
+		.end	= SA1100_CS0_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= SA1100_CS1_PHYS,
+		.end	= SA1100_CS1_PHYS + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct map_desc nanoengine_io_desc[] __initdata = {
+	{
+		/* System Registers */
+		.virtual	= 0xf0000000,
+		.pfn		= __phys_to_pfn(0x10000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {
+		/* Internal PCI Memory Read/Write */
+		.virtual	= NANO_PCI_MEM_RW_VIRT,
+		.pfn		= __phys_to_pfn(NANO_PCI_MEM_RW_PHYS),
+		.length		= NANO_PCI_MEM_RW_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		/* Internal PCI Config Space */
+		.virtual	= NANO_PCI_CONFIG_SPACE_VIRT,
+		.pfn		= __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS),
+		.length		= NANO_PCI_CONFIG_SPACE_SIZE,
+		.type		= MT_DEVICE
+	}
+};
+
+static void __init nanoengine_map_io(void)
+{
+	sa1100_map_io();
+	iotable_init(nanoengine_io_desc, ARRAY_SIZE(nanoengine_io_desc));
+
+	sa1100_register_uart(0, 1);
+	sa1100_register_uart(1, 2);
+	sa1100_register_uart(2, 3);
+	Ser1SDCR0 |= SDCR0_UART;
+	/* disable IRDA -- UART2 is used as a normal serial port */
+	Ser2UTCR4 = 0;
+	Ser2HSCR0 = 0;
+}
+
+static void __init nanoengine_init(void)
+{
+	sa11x0_register_mtd(&nanoengine_flash_data, nanoengine_flash_resources,
+		ARRAY_SIZE(nanoengine_flash_resources));
+}
+
+MACHINE_START(NANOENGINE, "BSE nanoEngine")
+	.boot_params	= 0xc0000000,
+	.map_io		= nanoengine_map_io,
+	.init_irq	= sa1100_init_irq,
+	.timer		= &sa1100_timer,
+	.init_machine	= nanoengine_init,
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c
new file mode 100644
index 0000000..fba7a91
--- /dev/null
+++ b/arch/arm/mach-sa1100/pci-nanoengine.c
@@ -0,0 +1,284 @@
+/*
+ * linux/arch/arm/mach-sa1100/pci-nanoengine.c
+ *
+ * PCI functions for BSE nanoEngine PCI
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#include <mach/nanoengine.h>
+
+static DEFINE_SPINLOCK(nano_lock);
+
+static int nanoengine_get_pci_address(struct pci_bus *bus,
+	unsigned int devfn, int where, unsigned long *address)
+{
+	int ret = PCIBIOS_DEVICE_NOT_FOUND;
+	unsigned int busnr = bus->number;
+
+	*address = NANO_PCI_CONFIG_SPACE_VIRT +
+		((bus->number << 16) | (devfn << 8) | (where & ~3));
+
+	ret = (busnr > 255 || devfn > 255 || where > 255) ?
+		PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+	return ret;
+}
+
+static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+	int size, u32 *val)
+{
+	int ret;
+	unsigned long address;
+	unsigned long flags;
+	u32 v;
+
+	/* nanoEngine PCI bridge does not return -1 for a non-existing
+	 * device. We must fake the answer. We know that the only valid
+	 * device is device zero at bus 0, which is the network chip. */
+	if (bus->number != 0 || (devfn >> 3) != 0) {
+		v = -1;
+		nanoengine_get_pci_address(bus, devfn, where, &address);
+		goto exit_function;
+	}
+
+	spin_lock_irqsave(&nano_lock, flags);
+
+	ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+	v = __raw_readl(address);
+
+	spin_unlock_irqrestore(&nano_lock, flags);
+
+	v >>= ((where & 3) * 8);
+	v &= (unsigned long)(-1) >> ((4 - size) * 8);
+
+exit_function:
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+	int size, u32 val)
+{
+	int ret;
+	unsigned long address;
+	unsigned long flags;
+	unsigned shift;
+	u32 v;
+
+	shift = (where & 3) * 8;
+
+	spin_lock_irqsave(&nano_lock, flags);
+
+	ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+	v = __raw_readl(address);
+	switch (size) {
+	case 1:
+		v &= ~(0xFF << shift);
+		v |= val << shift;
+		break;
+	case 2:
+		v &= ~(0xFFFF << shift);
+		v |= val << shift;
+		break;
+	case 4:
+		v = val;
+		break;
+	}
+	__raw_writel(v, address);
+
+	spin_unlock_irqrestore(&nano_lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_nano_ops = {
+	.read	= nanoengine_read_config,
+	.write	= nanoengine_write_config,
+};
+
+static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return NANOENGINE_IRQ_GPIO_PCI;
+}
+
+struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &pci_nano_ops, sys);
+}
+
+static struct resource pci_io_ports = {
+	.name	= "PCI IO",
+	.start	= 0x400,
+	.end	= 0x7FF,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource pci_non_prefetchable_memory = {
+	.name	= "PCI non-prefetchable",
+	.start	= NANO_PCI_MEM_RW_PHYS,
+	/* nanoEngine documentation says there is a 1 Megabyte window here,
+	 * but PCI reports just 128 + 8 kbytes. */
+	.end	= NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1,
+/*	.end	= NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/
+	.flags	= IORESOURCE_MEM,
+};
+
+/*
+ * nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it
+ * overlaps with previously defined memory.
+ *
+ * Here is what happens:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000)
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+ *
+ * On the other hand, if we do not request the prefetchable memory resource,
+ * linux will alloc it first and the two non-prefetchable memory areas that
+ * are our real interest will not be mapped. So we choose to map it to an
+ * unused area. It gets recognized as expansion ROM, but becomes disabled.
+ *
+ * Here is what happens then:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref]
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+
+# lspci -vv -s 0000:00:00.0
+00:00.0 Class 0200: Device 8086:1209 (rev 09)
+        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
+        Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx-
+        Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes
+        Interrupt: pin A routed to IRQ 0
+        Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K]
+        Region 1: I/O ports at 0400 [size=64]
+        Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K]
+        [virtual] Expansion ROM at 78000000 [disabled] [size=1M]
+        Capabilities: [dc] Power Management version 2
+                Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
+                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
+        Kernel driver in use: e100
+        Kernel modules: e100
+ *
+ */
+static struct resource pci_prefetchable_memory = {
+	.name	= "PCI prefetchable",
+	.start	= 0x78000000,
+	.end	= 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1,
+	.flags	= IORESOURCE_MEM  | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_nanoengine_setup_resources(struct resource **resource)
+{
+	if (request_resource(&ioport_resource, &pci_io_ports)) {
+		printk(KERN_ERR "PCI: unable to allocate io port region\n");
+		return -EBUSY;
+	}
+	if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) {
+		release_resource(&pci_io_ports);
+		printk(KERN_ERR "PCI: unable to allocate non prefetchable\n");
+		return -EBUSY;
+	}
+	if (request_resource(&iomem_resource, &pci_prefetchable_memory)) {
+		release_resource(&pci_io_ports);
+		release_resource(&pci_non_prefetchable_memory);
+		printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
+		return -EBUSY;
+	}
+	resource[0] = &pci_io_ports;
+	resource[1] = &pci_non_prefetchable_memory;
+	resource[2] = &pci_prefetchable_memory;
+
+	return 1;
+}
+
+int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
+{
+	int ret = 0;
+
+	if (nr == 0) {
+		sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
+		sys->io_offset = 0x400;
+		ret = pci_nanoengine_setup_resources(sys->resource);
+		/* Enable alternate memory bus master mode, see
+		 * "Intel StrongARM SA1110 Developer's Manual",
+		 * section 10.8, "Alternate Memory Bus Master Mode". */
+		GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+		GAFR |= GPIO_MBGNT | GPIO_MBREQ;
+		TUCR |= TUCR_MBGPIO;
+	}
+
+	return ret;
+}
+
+static struct hw_pci nanoengine_pci __initdata = {
+	.map_irq		= pci_nanoengine_map_irq,
+	.nr_controllers		= 1,
+	.scan			= pci_nanoengine_scan_bus,
+	.setup			= pci_nanoengine_setup,
+};
+
+static int __init nanoengine_pci_init(void)
+{
+	if (machine_is_nanoengine())
+		pci_common_init(&nanoengine_pci);
+	return 0;
+}
+
+subsys_initcall(nanoengine_pci_init);
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 27692d0..cfb7607 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -166,9 +166,6 @@
 	PCFR = 0;
 	PSDR = 0;
 
-	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
-			      ARRAY_SIZE(simpad_flash_resources));
-	sa11x0_register_mcp(&simpad_mcp_data);
 }
 
 static void simpad_power_off(void)
@@ -216,6 +213,10 @@
 
 	pm_power_off = simpad_power_off;
 
+	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
+			      ARRAY_SIZE(simpad_flash_resources));
+	sa11x0_register_mcp(&simpad_mcp_data);
+
 	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	if(ret)
 		printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 74b6e0e..ae4f3d8 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -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 @@
 	.rating		= 200,
 	.read		= sa1100_read_oscr,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -97,6 +123,9 @@
 	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 @@
 		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 --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 51dcd59..4d1b4c5 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -5,26 +5,27 @@
 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,15 @@
 
 endchoice
 
+config MACH_AG5EVM
+	bool "AG5EVM board"
+	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 +74,8 @@
 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 +86,8 @@
 	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 --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index ae416fe..e2507f6 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -9,14 +9,34 @@
 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 --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
new file mode 100644
index 0000000..c18a740
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -0,0 +1,315 @@
+/*
+ * 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 <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,
+};
+
+static struct platform_device *ag5evm_devices[] __initdata = {
+	&eth_device,
+	&keysc_device,
+	&fsi_device,
+	&mmc_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);
+}
+
+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);
+
+#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 --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index d440e5f..cd79d7c 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -61,6 +61,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <asm/setup.h>
 
 /*
  * Address	Interface		BusWidth	note
@@ -272,6 +273,15 @@
 	},
 };
 
+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 +289,7 @@
 			  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 = {
@@ -501,7 +512,12 @@
 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 +525,7 @@
 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 +538,6 @@
 	},
 };
 
-/* 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 +643,8 @@
 		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 +652,14 @@
 		/* 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)
@@ -764,10 +746,15 @@
 	},
 };
 
+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 +781,25 @@
 	},
 };
 
+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",
@@ -1181,7 +1187,7 @@
 	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);
@@ -1355,6 +1361,7 @@
 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 --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
index 3b83d63..686b304 100644
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -367,6 +367,7 @@
 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 --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
index 5b3b582..c13f012 100644
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -394,6 +394,7 @@
 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 --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
new file mode 100644
index 0000000..5bcf5c1
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -0,0 +1,1200 @@
+/*
+ * 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 |  ON  |  ON  |  X
+ * MMC1	  ON	|  OFF |  ON  |  X   | ON
+ * SDHI1  OFF	|  ON  |   X  |  OFF | ON
+ *
+ */
+
+/*
+ * 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		= 2,
+		.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)
+{
+	if (gpio_is_valid(GPIO_PORT41))
+		return !gpio_get_value(GPIO_PORT41);
+	else
+		return -ENXIO;
+}
+
+/* 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,
+};
+
+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_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
+
+/* 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_NEEDS_POLL,
+};
+
+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 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,
+	},
+};
+
+#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 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);
+
+	/* 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 --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
index 9f78729..6b186ae 100644
--- a/arch/arm/mach-shmobile/clock-sh7367.c
+++ b/arch/arm/mach-shmobile/clock-sh7367.c
@@ -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 --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 3aa0260..9aa8d68 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -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
@@ -507,7 +507,7 @@
        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 +543,7 @@
 	[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 +597,10 @@
 	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 +612,7 @@
 	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 +635,7 @@
 	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 --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c
index f91395a..9594246 100644
--- a/arch/arm/mach-shmobile/clock-sh7377.c
+++ b/arch/arm/mach-shmobile/clock-sh7377.c
@@ -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 --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
new file mode 100644
index 0000000..720a714
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -0,0 +1,356 @@
+/*
+ * 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);
+
+	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, 8, 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,
+	MSTP125, MSTP116,
+	MSTP219,
+	MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+	MSTP331, MSTP329, 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 */
+	[MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
+	[MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */
+	[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 */
+	[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 }
+
+static struct clk_lookup lookups[] = {
+	/* main clocks */
+	CLKDEV_CON_ID("r_clk", &r_clk),
+
+	/* MSTP32 clocks */
+	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
+	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */
+	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
+	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
+	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("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 --git a/arch/arm/mach-shmobile/entry-gic.S b/arch/arm/mach-shmobile/entry-gic.S
new file mode 100644
index 0000000..e20239b
--- /dev/null
+++ b/arch/arm/mach-shmobile/entry-gic.S
@@ -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 --git a/arch/arm/mach-shmobile/entry-intc.S b/arch/arm/mach-shmobile/entry-intc.S
new file mode 100644
index 0000000..cac0a7a
--- /dev/null
+++ b/arch/arm/mach-shmobile/entry-intc.S
@@ -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 --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
new file mode 100644
index 0000000..d4cec6b
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -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 --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c
new file mode 100644
index 0000000..238a0d9
--- /dev/null
+++ b/arch/arm/mach-shmobile/hotplug.c
@@ -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 --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index efeef77..013ac0e 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -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 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 --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S
index f428c4d..d791f10 100644
--- a/arch/arm/mach-shmobile/include/mach/entry-macro.S
+++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S
@@ -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]
+	.endm
 
-	/* 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]
+	.macro  test_for_ipi, irqnr, irqstat, base, tmp
+	.endm
 
-	/* Handle invalid vector number case */
-	cmp	\irqnr, #0
-	beq	1000f
+	.macro  test_for_ltirq, irqnr, irqstat, base, tmp
+	.endm
 
-	/* Convert vector to irq number, same as the evt2irq() macro */
-	lsr	\irqnr, \irqnr, #0x5
-	subs	\irqnr, \irqnr, #16
-
-1000:
+	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
diff --git a/arch/arm/mach-shmobile/include/mach/hardware.h b/arch/arm/mach-shmobile/include/mach/hardware.h
index 3f0ef19..99264a5 100644
--- a/arch/arm/mach-shmobile/include/mach/hardware.h
+++ b/arch/arm/mach-shmobile/include/mach/hardware.h
@@ -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 --git a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
new file mode 100644
index 0000000..e3ebfa7
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
@@ -0,0 +1,87 @@
+LIST "partner-jet-setup.txt"
+LIST "(C) Copyright 2010 Renesas Solutions Corp"
+LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
+
+LIST "RWT Setting"
+EW 0xE6020004, 0xA500
+EW 0xE6030004, 0xA500
+
+DD 0x01001000, 0x01001000
+
+LIST "GPIO Setting"
+EB 0xE6051013, 0xA2
+
+LIST "CPG"
+ED 0xE6150080, 0x00000180
+ED 0xE61500C0, 0x00000002
+
+WAIT 1, 0xFE40009C
+
+LIST "FRQCR"
+ED 0xE6150000, 0x2D1305C3
+ED 0xE61500E0, 0x9E40358E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE61500E4, 0x00002000
+
+WAIT 1, 0xFE40009C
+
+LIST "PLL"
+ED 0xE6150028, 0x00004000
+
+WAIT 1, 0xFE40009C
+
+ED 0xE615002C, 0x93000040
+
+WAIT 1, 0xFE40009C
+
+LIST "BSC"
+ED 0xFEC10000, 0x00E0001B
+
+LIST "SBSC1"
+ED 0xFE400354, 0x01AD8000
+ED 0xFE400354, 0x01AD8001
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400008, 0xBCC90151
+ED 0xFE400040, 0x41774113
+ED 0xFE400044, 0x2712E229
+ED 0xFE400048, 0x20C18505
+ED 0xFE40004C, 0x00110209
+ED 0xFE400010, 0x00000087
+
+WAIT 10, 0xFE40009C
+
+ED 0xFE400084, 0x0000003F
+EB 0xFE500000, 0x00
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400084, 0x0000FF0A
+EB 0xFE500000, 0x00
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400084, 0x00002201
+EB 0xFE500000, 0x00
+ED 0xFE400084, 0x00000302
+EB 0xFE500000, 0x00
+EB 0xFE5C0000, 0x00
+ED 0xFE400008, 0xBCC90159
+ED 0xFE40008C, 0x88800004
+ED 0xFE400094, 0x00000004
+ED 0xFE400028, 0xA55A0032
+ED 0xFE40002C, 0xA55A000C
+ED 0xFE400020, 0xA55A2048
+ED 0xFE400008, 0xBCC90959
+
+LIST "Change CPGA setting"
+ED 0xE61500E0, 0x9E40352E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE6150354, 0x00000002
diff --git a/arch/arm/mach-shmobile/include/mach/head-mackerel.txt b/arch/arm/mach-shmobile/include/mach/head-mackerel.txt
new file mode 100644
index 0000000..e3ebfa7
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/head-mackerel.txt
@@ -0,0 +1,87 @@
+LIST "partner-jet-setup.txt"
+LIST "(C) Copyright 2010 Renesas Solutions Corp"
+LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
+
+LIST "RWT Setting"
+EW 0xE6020004, 0xA500
+EW 0xE6030004, 0xA500
+
+DD 0x01001000, 0x01001000
+
+LIST "GPIO Setting"
+EB 0xE6051013, 0xA2
+
+LIST "CPG"
+ED 0xE6150080, 0x00000180
+ED 0xE61500C0, 0x00000002
+
+WAIT 1, 0xFE40009C
+
+LIST "FRQCR"
+ED 0xE6150000, 0x2D1305C3
+ED 0xE61500E0, 0x9E40358E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE61500E4, 0x00002000
+
+WAIT 1, 0xFE40009C
+
+LIST "PLL"
+ED 0xE6150028, 0x00004000
+
+WAIT 1, 0xFE40009C
+
+ED 0xE615002C, 0x93000040
+
+WAIT 1, 0xFE40009C
+
+LIST "BSC"
+ED 0xFEC10000, 0x00E0001B
+
+LIST "SBSC1"
+ED 0xFE400354, 0x01AD8000
+ED 0xFE400354, 0x01AD8001
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400008, 0xBCC90151
+ED 0xFE400040, 0x41774113
+ED 0xFE400044, 0x2712E229
+ED 0xFE400048, 0x20C18505
+ED 0xFE40004C, 0x00110209
+ED 0xFE400010, 0x00000087
+
+WAIT 10, 0xFE40009C
+
+ED 0xFE400084, 0x0000003F
+EB 0xFE500000, 0x00
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400084, 0x0000FF0A
+EB 0xFE500000, 0x00
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400084, 0x00002201
+EB 0xFE500000, 0x00
+ED 0xFE400084, 0x00000302
+EB 0xFE500000, 0x00
+EB 0xFE5C0000, 0x00
+ED 0xFE400008, 0xBCC90159
+ED 0xFE40008C, 0x88800004
+ED 0xFE400094, 0x00000004
+ED 0xFE400028, 0xA55A0032
+ED 0xFE40002C, 0xA55A000C
+ED 0xFE400020, 0xA55A2048
+ED 0xFE400008, 0xBCC90959
+
+LIST "Change CPGA setting"
+ED 0xE61500E0, 0x9E40352E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE6150354, 0x00000002
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
index fa15b5f..dcb714f 100644
--- a/arch/arm/mach-shmobile/include/mach/irqs.h
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -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 --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index e4f9004..5736efc 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -455,6 +455,8 @@
 	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 --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
new file mode 100644
index 0000000..ceb2cdc
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
@@ -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 --git a/arch/arm/mach-shmobile/include/mach/smp.h b/arch/arm/mach-shmobile/include/mach/smp.h
new file mode 100644
index 0000000..50db94e
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/smp.h
@@ -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 --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h
new file mode 100644
index 0000000..6d6a205
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot.h
@@ -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 --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
new file mode 100644
index 0000000..aa6111f
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
@@ -0,0 +1,65 @@
+#ifndef __ZBOOT_MACRO_H
+#define __ZBOOT_MACRO_H
+
+/* The LIST command is used to include comments in the script */
+.macro	LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro ED, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STR	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro EW, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STRH	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro EB, addr, data
+	LDR	r0, 1f
+	LDR	r1, 2f
+	STRB	r1, [r0]
+	B	3f
+1 :	.long	\addr
+2 :	.long	\data
+3 :
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro  WAIT, time, reg
+	LDR	r1, 1f
+	LDR	r0, 2f
+	STR	r0, [r1]
+10 :
+	LDR	r0, [r1]
+	CMP	r0, #0x00000000
+	BNE	10b
+	NOP
+	B	3f
+1 :	.long	\reg
+2 :	.long	\time * 100
+3 :
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro  DD, start, end
+	LDR	r1, 1f
+	B	2f
+1 :	.long	\start
+2 :
+.endm
+
+#endif /* __ZBOOT_MACRO_H */
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
new file mode 100644
index 0000000..322d8d5
--- /dev/null
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -0,0 +1,267 @@
+/*
+ * 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_base = __io(0xf0001000);
+	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+
+	gic_init(0, 29, gic_base, gic_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 --git a/arch/arm/mach-shmobile/localtimer.c b/arch/arm/mach-shmobile/localtimer.c
new file mode 100644
index 0000000..2111c28
--- /dev/null
+++ b/arch/arm/mach-shmobile/localtimer.c
@@ -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 --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c
new file mode 100644
index 0000000..3eed44e
--- /dev/null
+++ b/arch/arm/mach-shmobile/pfc-sh73a0.c
@@ -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 --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
new file mode 100644
index 0000000..65e879b
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -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 --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 564a6d0..2e3e11e 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -416,6 +416,16 @@
 		.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 --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
new file mode 100644
index 0000000..f1eff8b
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -0,0 +1,412 @@
+/*
+ * 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,
+	.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,
+	.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,
+	.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,
+	.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,
+	.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,
+	.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,
+	.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,
+	.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,
+	.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 --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
new file mode 100644
index 0000000..a156d21
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -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 --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
index ba32a15..3970a9c 100644
--- a/arch/arm/mach-tcc8k/clock.c
+++ b/arch/arm/mach-tcc8k/clock.c
@@ -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 --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c
index 78d0600..e0a8d60 100644
--- a/arch/arm/mach-tcc8k/time.c
+++ b/arch/arm/mach-tcc8k/time.c
@@ -35,7 +35,6 @@
 	.rating		= 200,
 	.read		= tcc_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 28,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -103,9 +102,7 @@
 {
 	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 --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index ae19f95..77948e0 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -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 --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 94fd859..083a4cf 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -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 --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index 8e7f115..a5cb1ce 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -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;
@@ -29,13 +26,13 @@
 	 * Turn off coherency
 	 */
 	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, #0x20\n"
+	"	bic	%0, %0, %2\n"
 	"	mcr	p15, 0, %0, c1, c0, 1\n"
 	"	mrc	p15, 0, %0, c1, c0, 0\n"
 	"	bic	%0, %0, #0x04\n"
 	"	mcr	p15, 0, %0, c1, c0, 0\n"
 	  : "=&r" (v)
-	  : "r" (0)
+	  : "r" (0), "Ir" (CR_C)
 	  : "cc");
 }
 
@@ -45,17 +42,17 @@
 
 	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 @@
 		/*}*/
 
 		/*
-		 * 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 @@
  */
 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 --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S
index 2ba9e5c..dd165c5 100644
--- a/arch/arm/mach-tegra/include/mach/entry-macro.S
+++ b/arch/arm/mach-tegra/include/mach/entry-macro.S
@@ -16,8 +16,8 @@
 #include <mach/io.h>
 
 #if defined(CONFIG_ARM_GIC)
-
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 	/* Uses the GIC interrupt controller built into the cpu */
 #define ICTRL_BASE (IO_CPU_VIRT + 0x100)
@@ -32,68 +32,6 @@
 
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
-
-	/*
-	 * The interrupt numbering scheme is defined in the
-	 * interrupt controller spec.  To wit:
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-28 are reserved
-	 * 29-31 are local.  We allow 30 to be used for the watchdog.
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * For now, we ignore all local interrupts so only return an interrupt
-	 * if it's between 30 and 1020.  The test_for_ipi routine below will
-	 * pick up on IPIs.
-	 *
-	 * A simple read from the controller will tell us the number of the
-	 * highest priority enabled interrupt.  We then just need to check
-	 * whether it is in the valid range for an IRQ (30-1020 inclusive).
-	 */
-
-	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-	/* bits 12-10 = src CPU, 9-0 = int # */
-	ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-	ldr		\tmp, =1021
-
-	bic     \irqnr, \irqstat, #0x1c00
-
-	cmp     \irqnr, #29
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	cmp	\irqnr, #16
-	strcc	\irqstat, [\base, #GIC_CPU_EOI]
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	mov 	\tmp, #0
-	cmp	\irqnr, #29
-	moveq	\tmp, #1
-	streq	\irqstat, [\base, #GIC_CPU_EOI]
-	cmp	\tmp, #0
-	.endm
-
 #else
 	/* legacy interrupt controller for AP16 */
 	.macro	disable_fiq
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
index f0981b1..4cea223 100644
--- a/arch/arm/mach-tegra/include/mach/io.h
+++ b/arch/arm/mach-tegra/include/mach/io.h
@@ -65,8 +65,8 @@
 
 #ifndef __ASSEMBLER__
 
-#define __arch_ioremap(p, s, t)	tegra_ioremap(p, s, t)
-#define __arch_iounmap(v)	tegra_iounmap(v)
+#define __arch_ioremap		tegra_ioremap
+#define __arch_iounmap		tegra_iounmap
 
 void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
 void tegra_iounmap(volatile void __iomem *addr);
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h
index e4a34a3..c8221b3 100644
--- a/arch/arm/mach-tegra/include/mach/smp.h
+++ b/arch/arm/mach-tegra/include/mach/smp.h
@@ -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)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-	gic_raise_softirq(mask, 1);
-}
-
-/*
- * Do nothing on MPcore.
- */
-static inline void smp_cross_call_done(cpumask_t callmap)
-{
+	gic_raise_softirq(mask, ipi);
 }
 
 #endif
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 50a8dfb..5407de0 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -94,8 +94,8 @@
 		writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
 	}
 
-	gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
-	gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+	gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
+		 IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
 
 	gic = get_irq_chip(29);
 	gic_unmask_irq = gic->unmask;
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1c0fd92..ec1f689 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -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 @@
 
 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 @@
 {
 	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 @@
 	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 --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index ae3b308..f0dae6d 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -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 --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 9057d6f..7b8ad1f 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -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 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 @@
 	.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 @@
 		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 --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c
index 7458fc6..fabcc49 100644
--- a/arch/arm/mach-u300/clock.c
+++ b/arch/arm/mach-u300/clock.c
@@ -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 --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index 3fc4472..3ec58bd 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -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 @@
  * 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 @@
 	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 @@
 	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 --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 9e27a84..12052e8 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -2,14 +2,16 @@
 # 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
+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_MOP)	+= 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 --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c
new file mode 100644
index 0000000..70318c3
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-keypads.c
@@ -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 --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index bac9956..4b99667 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -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 @@
 };
 
 /*
+ * 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 @@
 	.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 --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index cac83a6..a1c9ea1 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -13,25 +13,26 @@
 #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"
 
@@ -69,22 +70,12 @@
 	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 = {
@@ -93,9 +84,9 @@
 
 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 +100,6 @@
 	.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 +110,34 @@
 	.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 +167,49 @@
 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 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)
+static void __init mop500_i2c_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_i2c0(&u8500_i2c0_data);
+	db8500_add_i2c1(&u8500_i2c1_data);
+	db8500_add_i2c2(&u8500_i2c2_data);
+	db8500_add_i2c3(&u8500_i2c3_data);
 }
 
-/*
- * 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    = &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 mop500_spi_init(void)
+{
+	db8500_add_ssp0(&ssp0_platform_data);
+}
+
+static void __init mop500_uart_init(void)
+{
+	db8500_add_uart0();
+	db8500_add_uart1();
+	db8500_add_uart2();
+}
+
 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 --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index 2d24032..3104ae2 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -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 --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c
new file mode 100644
index 0000000..54712ac
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500-sdi.c
@@ -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 --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 1ca094a..39d370c 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -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 --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index 1675047..ccff2dae1 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -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
@@ -133,7 +138,7 @@
 {
 	void __iomem *addr = __io_address(UX500_PRCMU_BASE)
 		+ PRCM_TCR;
-	u32 tcr = readl(addr);
+	u32 tcr;
 	int mtu = (int) clk->data;
 	/*
 	 * One of these is selected eventually
@@ -144,6 +149,14 @@
 	unsigned long mturate;
 	unsigned long retclk;
 
+	/*
+	 * 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);
+
+	tcr = readl(addr);
+
 	/* Get the rate from the parent as a default */
 	if (clk->parent_periph)
 		mturate = clk_get_rate(clk->parent_periph);
@@ -153,45 +166,6 @@
 		/* 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 +291,7 @@
 };
 
 static struct clk clk_32khz = {
+	.name =  "clk_32khz",
 	.rate = 32000,
 };
 
@@ -366,94 +341,96 @@
  */
 
 /* 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 +531,7 @@
 
 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 +576,183 @@
 	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 +763,8 @@
 		/* 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 +773,12 @@
 	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 --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h
index a058025..0744907 100644
--- a/arch/arm/mach-ux500/clock.h
+++ b/arch/arm/mach-ux500/clock.h
@@ -90,6 +90,10 @@
 
 	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 --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index 2f87075..acc841e 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -8,14 +8,19 @@
 #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_io_desc[] __initdata = {
 	__IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
 	__IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K),
@@ -110,19 +115,32 @@
 };
 
 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)
 {
 	ux500_map_io();
@@ -132,7 +150,9 @@
 
 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 --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 4acab75..c0f34a4 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -22,23 +22,15 @@
 #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_io_desc[] __initdata = {
 	__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),
@@ -46,13 +38,18 @@
 	__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),
+};
+
+static struct map_desc u8500_v2_io_desc[] __initdata = {
+	__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
 };
 
 /*
@@ -125,14 +122,38 @@
 	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));
+		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));
 
 	/* Read out the ASIC ID as early as we can */
 	get_db8500_asic_id();
 }
 
+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,
+};
+
+static void __init db8500_add_gpios(void)
+{
+	struct nmk_gpio_platform_data pdata = {
+		/* No custom data yet */
+	};
+
+	dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base),
+			 IRQ_DB8500_GPIO0, &pdata);
+}
+
 /*
  * This function is called from the board init
  */
@@ -152,12 +173,13 @@
 	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 --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 608a137..5730409 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -6,7 +6,6 @@
  */
 
 #include <linux/platform_device.h>
-#include <linux/amba/bus.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 
@@ -20,6 +19,7 @@
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/prcmu.h>
 
 #include "clock.h"
 
@@ -45,29 +45,22 @@
 	__IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K),
 };
 
-static struct amba_device *ux500_amba_devs[] __initdata = {
-	&ux500_pl031_device,
-};
-
 void __init ux500_map_io(void)
 {
 	iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc));
 }
 
-void __init ux500_init_devices(void)
-{
-	amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs));
-}
-
 void __init ux500_init_irq(void)
 {
-	gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
-	gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+	gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE),
+		 __io_address(UX500_GIC_CPU_BASE));
 
 	/*
 	 * Init clocks here so that they are available for system timer
 	 * initialization.
 	 */
+	if (cpu_is_u8500())
+		prcmu_early_init();
 	clk_init();
 }
 
diff --git a/arch/arm/mach-ux500/cpufreq.c b/arch/arm/mach-ux500/cpufreq.c
new file mode 100644
index 0000000..5c5b747
--- /dev/null
+++ b/arch/arm/mach-ux500/cpufreq.c
@@ -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 --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
new file mode 100644
index 0000000..fe69f5f
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -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 --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
new file mode 100644
index 0000000..cbadc11
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-common.h
@@ -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 --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c
deleted file mode 100644
index 33e5b56..0000000
--- a/arch/arm/mach-ux500/devices-db5500.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h
new file mode 100644
index 0000000..c8d7901
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-db5500.h
@@ -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 --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 4a94be3..23c695d5 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -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 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 --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
new file mode 100644
index 0000000..3a770c7
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-db8500.h
@@ -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 --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c
index 8a26889..ea0a2f9 100644
--- a/arch/arm/mach-ux500/devices.c
+++ b/arch/arm/mach-ux500/devices.c
@@ -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 --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c
new file mode 100644
index 0000000..32a061f
--- /dev/null
+++ b/arch/arm/mach-ux500/dma-db5500.c
@@ -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 --git a/arch/arm/mach-ux500/headsmp.S b/arch/arm/mach-ux500/headsmp.S
index a6be2cd..64fa451 100644
--- a/arch/arm/mach-ux500/headsmp.S
+++ b/arch/arm/mach-ux500/headsmp.S
@@ -23,7 +23,6 @@
 	ldmia	r4, {r5, r6}
 	sub	r4, r4, r5
 	add	r6, r6, r4
-	dsb
 pen:	ldr	r7, [r6]
 	cmp	r7, r0
 	bne	pen
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
index b782a03..dd8037e 100644
--- a/arch/arm/mach-ux500/hotplug.c
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -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 @@
 
 int platform_cpu_kill(unsigned int cpu)
 {
-	return wait_for_completion_timeout(&cpu_killed, 5000);
+	return 1;
 }
 
 /*
@@ -48,19 +45,6 @@
  */
 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 --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 3eafc0e..bd88c1e 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -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 --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index f07d098..0fefb34 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -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 --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index b91a4d1..020b636 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -14,27 +14,10 @@
 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 --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S
index 60ea88d..a37f585 100644
--- a/arch/arm/mach-ux500/include/mach/entry-macro.S
+++ b/arch/arm/mach-ux500/include/mach/entry-macro.S
@@ -11,7 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
 		.macro	disable_fiq
 		.endm
@@ -22,68 +23,3 @@
 
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an
-		 * interrupt if it's between 30 and 1020. The test_for_ipi
-		 * routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number
-		 * of the highest priority enabled interrupt. We then just
-		 * need to check whether it is in the valid range for an
-		 * IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		/* bits 12-10 = src CPU, 9-0 = int # */
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ
-		 * acknowledge register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of
-		 * interrupt on the controller, since this requires the
-		 * original irqstat value which we won't easily be able
-		 * to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base
-		 * are preserved..
-		 */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov 	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h
index d548a62..3c4cd31 100644
--- a/arch/arm/mach-ux500/include/mach/gpio.h
+++ b/arch/arm/mach-ux500/include/mach/gpio.h
@@ -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 --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index 32e883a..6295cc5 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -142,6 +142,8 @@
 #endif
 }
 
+#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
+
 #endif
 
 #endif				/* __MACH_HARDWARE_H */
diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
index cca4f70..7cdeb2a 100644
--- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
+++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
@@ -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 --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index 693aa57..880ae45 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -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.
diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox-db5500.h
similarity index 100%
rename from arch/arm/mach-ux500/include/mach/mbox.h
rename to arch/arm/mach-ux500/include/mach/mbox-db5500.h
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-defs.h b/arch/arm/mach-ux500/include/mach/prcmu-defs.h
new file mode 100644
index 0000000..848ba64
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu-defs.h
@@ -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 --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
index 8885f39..455467e 100644
--- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h
+++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
@@ -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 --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h
index 549843f..c49e456 100644
--- a/arch/arm/mach-ux500/include/mach/prcmu.h
+++ b/arch/arm/mach-ux500/include/mach/prcmu.h
@@ -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 --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index 54bbe64..469877e 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -18,14 +18,19 @@
 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 --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h
index 197e841..ca2b15b 100644
--- a/arch/arm/mach-ux500/include/mach/smp.h
+++ b/arch/arm/mach-ux500/include/mach/smp.h
@@ -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 @@
 /*
  * 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 --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 0271ca0a..9a6614c 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -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 --git a/arch/arm/mach-ux500/mbox-db5500.c b/arch/arm/mach-ux500/mbox-db5500.c
new file mode 100644
index 0000000..cbf1571
--- /dev/null
+++ b/arch/arm/mach-ux500/mbox-db5500.c
@@ -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 --git a/arch/arm/mach-ux500/mbox.c b/arch/arm/mach-ux500/mbox.c
deleted file mode 100644
index 6343538..0000000
--- a/arch/arm/mach-ux500/mbox.c
+++ /dev/null
@@ -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 --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem-irq-db5500.c
similarity index 100%
rename from arch/arm/mach-ux500/modem_irq.c
rename to arch/arm/mach-ux500/modem-irq-db5500.c
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 9e4c678..d77e76c 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
 
@@ -26,31 +25,37 @@
  * 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 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 +79,9 @@
 	 * 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,9 +100,6 @@
 
 static void __init wakeup_secondary(void)
 {
-	/* nobody is to be released from the pen yet */
-	pen_release = -1;
-
 	/*
 	 * write the address of secondary startup into the backup ram register
 	 * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
@@ -126,41 +126,27 @@
  */
 void __init smp_init_cpus(void)
 {
-	unsigned int i, ncores = get_core_count();
+	unsigned int i, ncores;
+
+	ncores = scu_get_core_count(__io_address(UX500_SCU_BASE));
+
+	/* sanity check */
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "U8500: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
 
 	for (i = 0; i < ncores; i++)
 		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 = get_core_count();
-	unsigned int cpu = smp_processor_id();
 	int i;
 
-	/* 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())	{
-		printk(KERN_WARNING
-		       "U8500: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, num_possible_cpus());
-		ncores = num_possible_cpus();
-	}
-
-	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,13 +154,6 @@
 	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(__io_address(UX500_SCU_BASE));
+	wakeup_secondary();
 }
diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c
index 293274d..c522d26 100644
--- a/arch/arm/mach-ux500/prcmu.c
+++ b/arch/arm/mach-ux500/prcmu.c
@@ -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 @@
 }
 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_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 @@
 	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 --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig
index c781f30..3f7b5e9 100644
--- a/arch/arm/mach-versatile/Kconfig
+++ b/arch/arm/mach-versatile/Kconfig
@@ -4,6 +4,7 @@
 config ARCH_VERSATILE_PB
 	bool "Support Versatile/PB platform"
 	select CPU_ARM926T
+	select MIGHT_HAVE_PCI
 	default y
 	help
 	  Include support for the ARM(R) Versatile/PB platform.
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index e38acb0..13a83e4 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -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"
 
@@ -886,6 +887,12 @@
 }
 
 /*
+ * 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 +907,8 @@
 {
 	u32 val;
 
+	versatile_sched_clock_init(REFCOUNTER, 24000000);
+
 	/* 
 	 * set clock frequency: 
 	 *	VERSATILE_REFCLK is 32KHz
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 1b71b77..2c0ac7d 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -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 --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
index 57dd95c..362780d 100644
--- a/arch/arm/mach-vexpress/core.h
+++ b/arch/arm/mach-vexpress/core.h
@@ -22,5 +22,3 @@
 
 void v2m_map_io(struct map_desc *tile, size_t num);
 extern struct sys_timer v2m_timer;
-
-extern void __iomem *gic_cpu_base_addr;
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index fd25ccd..e628402 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -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 @@
 	v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
 }
 
-void __iomem *gic_cpu_base_addr;
-
 static void __init ct_ca9x4_init_irq(void)
 {
-	gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU);
-	gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29);
-	gic_cpu_init(0, gic_cpu_base_addr);
+	gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
+		 MMIO_P2V(A9_MPCORE_GIC_CPU));
 }
 
 #if 0
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
new file mode 100644
index 0000000..ea4cbfb
--- /dev/null
+++ b/arch/arm/mach-vexpress/hotplug.c
@@ -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 --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S
index 20e9fb5..73c1129 100644
--- a/arch/arm/mach-vexpress/include/mach/entry-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S
@@ -1,67 +1,7 @@
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
 	.macro	disable_fiq
 	.endm
 
-	.macro	get_irqnr_preamble, base, tmp
-	ldr	\base, =gic_cpu_base_addr
-	ldr	\base, [\base]
-	.endm
-
 	.macro	arch_ret_to_user, tmp1, tmp2
 	.endm
-
-	/*
-	 * The interrupt numbering scheme is defined in the
-	 * interrupt controller spec.  To wit:
-	 *
-	 * Interrupts 0-15 are IPI
-	 * 16-28 are reserved
-	 * 29-31 are local.  We allow 30 to be used for the watchdog.
-	 * 32-1020 are global
-	 * 1021-1022 are reserved
-	 * 1023 is "spurious" (no interrupt)
-	 *
-	 * For now, we ignore all local interrupts so only return an interrupt if it's
-	 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-	 *
-	 * A simple read from the controller will tell us the number of the highest
-	 * priority enabled interrupt.  We then just need to check whether it is in the
-	 * valid range for an IRQ (30-1020 inclusive).
-	 */
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-	ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-	ldr	\tmp, =1021
-	bic     \irqnr, \irqstat, #0x1c00
-	cmp     \irqnr, #29
-	cmpcc	\irqnr, \irqnr
-	cmpne	\irqnr, \tmp
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* We assume that irqstat (the raw value of the IRQ acknowledge
-	 * register) is preserved from the macro above.
-	 * If there is an IPI, we immediately signal end of interrupt on the
-	 * controller, since this requires the original irqstat value which
-	 * we won't easily be able to recreate later.
-	 */
-
-	.macro test_for_ipi, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	cmp	\irqnr, #16
-	strcc	\irqstat, [\base, #GIC_CPU_EOI]
-	cmpcs	\irqnr, \irqnr
-	.endm
-
-	/* As above, this assumes that irqstat and base are preserved.. */
-
-	.macro test_for_ltirq, irqnr, irqstat, base, tmp
-	bic	\irqnr, \irqstat, #0x1c00
-	mov 	\tmp, #0
-	cmp	\irqnr, #29
-	moveq	\tmp, #1
-	streq	\irqstat, [\base, #GIC_CPU_EOI]
-	cmp	\tmp, #0
-	.endm
-
diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h
index 5a6da4f..4c05e4a 100644
--- a/arch/arm/mach-vexpress/include/mach/smp.h
+++ b/arch/arm/mach-vexpress/include/mach/smp.h
@@ -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 --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 6709706..b1687b6 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -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 @@
  */
 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 MMIO_P2V(A9_MPCORE_SCU);
@@ -44,21 +56,18 @@
 
 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 @@
 	 * 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 @@
 	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 @@
 		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 @@
 	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 --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 7eaa232..a9ed342 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -11,18 +11,18 @@
 #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 <mach/clkdev.h>
 #include <mach/motherboard.h>
 
-#include <plat/timer-sp.h>
+#include <plat/sched_clock.h>
 
 #include "core.h"
 
@@ -50,6 +50,8 @@
 
 static void __init v2m_timer_init(void)
 {
+	versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
+
 	writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
 	writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
 
diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h
index c56ddab..b88a1b1 100644
--- a/arch/arm/mach-w90x900/clock.h
+++ b/arch/arm/mach-w90x900/clock.h
@@ -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 --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c
index b80f769..4b089cb 100644
--- a/arch/arm/mach-w90x900/time.c
+++ b/arch/arm/mach-w90x900/time.c
@@ -153,7 +153,6 @@
 	.rating	= 200,
 	.read	= nuc900_get_cycles,
 	.mask	= CLOCKSOURCE_MASK(TDR_SHIFT),
-	.shift	= 10,
 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -176,9 +175,7 @@
 	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 --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 4414a01..fcc1e62 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -382,6 +382,12 @@
 	  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
@@ -599,6 +605,14 @@
 	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 @@
 	  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_V7
+	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 @@
 	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_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 --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index d63b6c4..00d74a0 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -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 --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
index 6e77c04..e0b0e7a 100644
--- a/arch/arm/mm/cache-feroceon-l2.c
+++ b/arch/arm/mm/cache-feroceon-l2.c
@@ -13,13 +13,9 @@
  */
 
 #include <linux/init.h>
+#include <linux/highmem.h>
 #include <asm/cacheflush.h>
-#include <asm/kmap_types.h>
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
 #include <plat/cache-feroceon-l2.h>
-#include "mm.h"
 
 /*
  * Low-level cache maintenance operations.
@@ -39,27 +35,30 @@
  * between which we don't want to be preempted.
  */
 
-static inline unsigned long l2_start_va(unsigned long paddr)
+static inline unsigned long l2_get_va(unsigned long paddr)
 {
 #ifdef CONFIG_HIGHMEM
 	/*
-	 * Let's do our own fixmap stuff in a minimal way here.
 	 * Because range ops can't be done on physical addresses,
 	 * we simply install a virtual mapping for it only for the
 	 * TLB lookup to occur, hence no need to flush the untouched
-	 * memory mapping.  This is protected with the disabling of
-	 * interrupts by the caller.
+	 * memory mapping afterwards (note: a cache flush may happen
+	 * in some circumstances depending on the path taken in kunmap_atomic).
 	 */
-	unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
-	unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-	set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0);
-	local_flush_tlb_kernel_page(vaddr);
-	return vaddr + (paddr & ~PAGE_MASK);
+	void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT);
+	return (unsigned long)vaddr + (paddr & ~PAGE_MASK);
 #else
 	return __phys_to_virt(paddr);
 #endif
 }
 
+static inline void l2_put_va(unsigned long vaddr)
+{
+#ifdef CONFIG_HIGHMEM
+	kunmap_atomic((void *)vaddr);
+#endif
+}
+
 static inline void l2_clean_pa(unsigned long addr)
 {
 	__asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
@@ -76,13 +75,14 @@
 	 */
 	BUG_ON((start ^ end) >> PAGE_SHIFT);
 
-	raw_local_irq_save(flags);
-	va_start = l2_start_va(start);
+	va_start = l2_get_va(start);
 	va_end = va_start + (end - start);
+	raw_local_irq_save(flags);
 	__asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
 		"mcr p15, 1, %1, c15, c9, 5"
 		: : "r" (va_start), "r" (va_end));
 	raw_local_irq_restore(flags);
+	l2_put_va(va_start);
 }
 
 static inline void l2_clean_inv_pa(unsigned long addr)
@@ -106,13 +106,14 @@
 	 */
 	BUG_ON((start ^ end) >> PAGE_SHIFT);
 
-	raw_local_irq_save(flags);
-	va_start = l2_start_va(start);
+	va_start = l2_get_va(start);
 	va_end = va_start + (end - start);
+	raw_local_irq_save(flags);
 	__asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
 		"mcr p15, 1, %1, c15, c11, 5"
 		: : "r" (va_start), "r" (va_end));
 	raw_local_irq_restore(flags);
+	l2_put_va(va_start);
 }
 
 static inline void l2_inv_all(void)
diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c
index c315492..5a32020 100644
--- a/arch/arm/mm/cache-xsc3l2.c
+++ b/arch/arm/mm/cache-xsc3l2.c
@@ -17,14 +17,10 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 #include <linux/init.h>
+#include <linux/highmem.h>
 #include <asm/system.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
-#include <asm/kmap_types.h>
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-#include "mm.h"
 
 #define CR_L2	(1 << 26)
 
@@ -71,16 +67,15 @@
 	dsb();
 }
 
+static inline void l2_unmap_va(unsigned long va)
+{
 #ifdef CONFIG_HIGHMEM
-#define l2_map_save_flags(x)		raw_local_save_flags(x)
-#define l2_map_restore_flags(x)		raw_local_irq_restore(x)
-#else
-#define l2_map_save_flags(x)		((x) = 0)
-#define l2_map_restore_flags(x)		((void)(x))
+	if (va != -1)
+		kunmap_atomic((void *)va);
 #endif
+}
 
-static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
-				      unsigned long flags)
+static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va)
 {
 #ifdef CONFIG_HIGHMEM
 	unsigned long va = prev_va & PAGE_MASK;
@@ -89,17 +84,10 @@
 		/*
 		 * Switching to a new page.  Because cache ops are
 		 * using virtual addresses only, we must put a mapping
-		 * in place for it.  We also enable interrupts for a
-		 * short while and disable them again to protect this
-		 * mapping.
+		 * in place for it.
 		 */
-		unsigned long idx;
-		raw_local_irq_restore(flags);
-		idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
-		va = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-		raw_local_irq_restore(flags | PSR_I_BIT);
-		set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0);
-		local_flush_tlb_kernel_page(va);
+		l2_unmap_va(prev_va);
+		va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT);
 	}
 	return va + (pa_offset >> (32 - PAGE_SHIFT));
 #else
@@ -109,7 +97,7 @@
 
 static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
 {
-	unsigned long vaddr, flags;
+	unsigned long vaddr;
 
 	if (start == 0 && end == -1ul) {
 		xsc3_l2_inv_all();
@@ -117,13 +105,12 @@
 	}
 
 	vaddr = -1;  /* to force the first mapping */
-	l2_map_save_flags(flags);
 
 	/*
 	 * Clean and invalidate partial first cache line.
 	 */
 	if (start & (CACHE_LINE_SIZE - 1)) {
-		vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags);
+		vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr);
 		xsc3_l2_clean_mva(vaddr);
 		xsc3_l2_inv_mva(vaddr);
 		start = (start | (CACHE_LINE_SIZE - 1)) + 1;
@@ -133,7 +120,7 @@
 	 * Invalidate all full cache lines between 'start' and 'end'.
 	 */
 	while (start < (end & ~(CACHE_LINE_SIZE - 1))) {
-		vaddr = l2_map_va(start, vaddr, flags);
+		vaddr = l2_map_va(start, vaddr);
 		xsc3_l2_inv_mva(vaddr);
 		start += CACHE_LINE_SIZE;
 	}
@@ -142,31 +129,30 @@
 	 * Clean and invalidate partial last cache line.
 	 */
 	if (start < end) {
-		vaddr = l2_map_va(start, vaddr, flags);
+		vaddr = l2_map_va(start, vaddr);
 		xsc3_l2_clean_mva(vaddr);
 		xsc3_l2_inv_mva(vaddr);
 	}
 
-	l2_map_restore_flags(flags);
+	l2_unmap_va(vaddr);
 
 	dsb();
 }
 
 static void xsc3_l2_clean_range(unsigned long start, unsigned long end)
 {
-	unsigned long vaddr, flags;
+	unsigned long vaddr;
 
 	vaddr = -1;  /* to force the first mapping */
-	l2_map_save_flags(flags);
 
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
-		vaddr = l2_map_va(start, vaddr, flags);
+		vaddr = l2_map_va(start, vaddr);
 		xsc3_l2_clean_mva(vaddr);
 		start += CACHE_LINE_SIZE;
 	}
 
-	l2_map_restore_flags(flags);
+	l2_unmap_va(vaddr);
 
 	dsb();
 }
@@ -193,7 +179,7 @@
 
 static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
 {
-	unsigned long vaddr, flags;
+	unsigned long vaddr;
 
 	if (start == 0 && end == -1ul) {
 		xsc3_l2_flush_all();
@@ -201,17 +187,16 @@
 	}
 
 	vaddr = -1;  /* to force the first mapping */
-	l2_map_save_flags(flags);
 
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
-		vaddr = l2_map_va(start, vaddr, flags);
+		vaddr = l2_map_va(start, vaddr);
 		xsc3_l2_clean_mva(vaddr);
 		xsc3_l2_inv_mva(vaddr);
 		start += CACHE_LINE_SIZE;
 	}
 
-	l2_map_restore_flags(flags);
+	l2_unmap_va(vaddr);
 
 	dsb();
 }
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ac6a361..6b48e0a 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/highmem.h>
 
 #include <asm/memory.h>
 #include <asm/highmem.h>
@@ -311,7 +312,7 @@
 		addr = page_address(page);
 
 	if (addr)
-		*handle = page_to_dma(dev, page);
+		*handle = pfn_to_dma(dev, page_to_pfn(page));
 
 	return addr;
 }
@@ -406,7 +407,7 @@
 	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);
 
@@ -480,10 +481,10 @@
 				op(vaddr, len, dir);
 				kunmap_high(page);
 			} else if (cache_is_vipt()) {
-				pte_t saved_pte;
-				vaddr = kmap_high_l1_vipt(page, &saved_pte);
+				/* unmapped pages might still be cached */
+				vaddr = kmap_atomic(page);
 				op(vaddr + offset, len, dir);
-				kunmap_high_l1_vipt(page, saved_pte);
+				kunmap_atomic(vaddr);
 			}
 		} else {
 			vaddr = page_address(page) + offset;
@@ -554,17 +555,20 @@
 	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);
@@ -585,8 +589,10 @@
 	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);
 
@@ -611,6 +617,8 @@
 		__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);
 
@@ -635,5 +643,16 @@
 		__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 --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 83e59f8..01210db 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -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 --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 1e21e12..f10f9ba 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -108,7 +108,7 @@
 
 		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 --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 391ffae..c29f283 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
+#include <linux/highmem.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
@@ -180,10 +181,10 @@
 			__cpuc_flush_dcache_area(addr, PAGE_SIZE);
 			kunmap_high(page);
 		} else if (cache_is_vipt()) {
-			pte_t saved_pte;
-			addr = kmap_high_l1_vipt(page, &saved_pte);
+			/* unmapped pages might still be cached */
+			addr = kmap_atomic(page);
 			__cpuc_flush_dcache_area(addr, PAGE_SIZE);
-			kunmap_high_l1_vipt(page, saved_pte);
+			kunmap_atomic(addr);
 		}
 	}
 
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index c435fd9..807c057 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -140,90 +140,3 @@
 	pte = TOP_PTE(vaddr);
 	return pte_page(*pte);
 }
-
-#ifdef CONFIG_CPU_CACHE_VIPT
-
-#include <linux/percpu.h>
-
-/*
- * The VIVT cache of a highmem page is always flushed before the page
- * is unmapped. Hence unmapped highmem pages need no cache maintenance
- * in that case.
- *
- * However unmapped pages may still be cached with a VIPT cache, and
- * it is not possible to perform cache maintenance on them using physical
- * addresses unfortunately.  So we have no choice but to set up a temporary
- * virtual mapping for that purpose.
- *
- * Yet this VIPT cache maintenance may be triggered from DMA support
- * functions which are possibly called from interrupt context. As we don't
- * want to keep interrupt disabled all the time when such maintenance is
- * taking place, we therefore allow for some reentrancy by preserving and
- * restoring the previous fixmap entry before the interrupted context is
- * resumed.  If the reentrancy depth is 0 then there is no need to restore
- * the previous fixmap, and leaving the current one in place allow it to
- * be reused the next time without a TLB flush (common with DMA).
- */
-
-static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);
-
-void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
-{
-	unsigned int idx, cpu;
-	int *depth;
-	unsigned long vaddr, flags;
-	pte_t pte, *ptep;
-
-	if (!in_interrupt())
-		preempt_disable();
-
-	cpu = smp_processor_id();
-	depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
-
-	idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-	ptep = TOP_PTE(vaddr);
-	pte = mk_pte(page, kmap_prot);
-
-	raw_local_irq_save(flags);
-	(*depth)++;
-	if (pte_val(*ptep) == pte_val(pte)) {
-		*saved_pte = pte;
-	} else {
-		*saved_pte = *ptep;
-		set_pte_ext(ptep, pte, 0);
-		local_flush_tlb_kernel_page(vaddr);
-	}
-	raw_local_irq_restore(flags);
-
-	return (void *)vaddr;
-}
-
-void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte)
-{
-	unsigned int idx, cpu = smp_processor_id();
-	int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
-	unsigned long vaddr, flags;
-	pte_t pte, *ptep;
-
-	idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-	ptep = TOP_PTE(vaddr);
-	pte = mk_pte(page, kmap_prot);
-
-	BUG_ON(pte_val(*ptep) != pte_val(pte));
-	BUG_ON(*depth <= 0);
-
-	raw_local_irq_save(flags);
-	(*depth)--;
-	if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) {
-		set_pte_ext(ptep, saved_pte, 0);
-		local_flush_tlb_kernel_page(vaddr);
-	}
-	raw_local_irq_restore(flags);
-
-	if (!in_interrupt())
-		preempt_enable();
-}
-
-#endif  /* CONFIG_CPU_CACHE_VIPT */
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
new file mode 100644
index 0000000..5729944
--- /dev/null
+++ b/arch/arm/mm/idmap.c
@@ -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 --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 55c17a6..ab50627 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -204,12 +204,8 @@
 	/*
 	 * 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 --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 6630620..36960df 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -16,7 +16,7 @@
 }
 
 struct mem_type {
-	unsigned int prot_pte;
+	pteval_t prot_pte;
 	unsigned int prot_l1;
 	unsigned int prot_sect;
 	unsigned int domain;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 72ad3e1..3c67e92 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -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 @@
 	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 @@
 }
 #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 @@
 	},
 	[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 @@
 	},
 	[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 @@
 
 	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 @@
 {
 	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_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 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 @@
 {
 	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 @@
 	 * 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 @@
 	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 --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 69bbfc6..93292a1 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -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 @@
 	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));
 
@@ -73,28 +71,29 @@
 	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 --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index b795afd..e32fa49 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -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 --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 9b9ff5d..b49fab2 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -124,15 +124,13 @@
  *	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,26 @@
 	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]
+	str	r3, [r0, #2048]!
 	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
 #endif
 	mov	pc, lr
@@ -273,8 +274,6 @@
 	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 +312,10 @@
 #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 --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 523408c..5a37c5e 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -500,8 +500,8 @@
 	@
 	@ 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 --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
index 558cdfa..07f23bb 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/plat-iop/time.c
@@ -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 @@
 	.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 @@
 	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 @@
 {
 	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 @@
 	 * 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 @@
 		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 @@
 	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 --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 64e3a64..389f217 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -21,10 +21,6 @@
 
 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 @@
 
 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 @@
 	  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 --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 3726709..5fd20e9 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -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 --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index 0be1ac7..175e364 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -209,7 +209,7 @@
 		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 @@
 		}
 		audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
 	}
-#endif
+#endif /* if defined(CONFIG_SOC_IMX25) */
 	audmux_debugfs_init();
 
 	return 0;
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
new file mode 100644
index 0000000..9a4e8a2
--- /dev/null
+++ b/arch/arm/plat-mxc/avic.c
@@ -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(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 mxc_irq_chip mxc_avic_chip = {
+	.base = {
+		.ack = mxc_mask_irq,
+		.mask = mxc_mask_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 --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index 039538e..ce81481 100644
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -144,7 +144,6 @@
 	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 --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index 735776d..e9bcefe 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -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 @@
 	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 @@
 	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 --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index 9aa6f3e..2537166 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -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
 
 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 --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index 45aefeb..75cd2ec 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-esdhc.c b/arch/arm/plat-mxc/devices/platform-esdhc.c
deleted file mode 100644
index 2605bfa..0000000
--- a/arch/arm/plat-mxc/devices/platform-esdhc.c
+++ /dev/null
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
index 11d087f..269ec78 100644
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -16,22 +16,22 @@
 		.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
diff --git a/arch/arm/plat-mxc/devices/platform-flexcan.c b/arch/arm/plat-mxc/devices/platform-flexcan.c
index 5e97a01..4e8497a 100644
--- a/arch/arm/plat-mxc/devices/platform-flexcan.c
+++ b/arch/arm/plat-mxc/devices/platform-flexcan.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
new file mode 100644
index 0000000..59c33f6
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
index 3a705c7..33530d2 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-dma.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c
@@ -31,25 +31,25 @@
 		},							\
 	}
 
-#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 @@
 	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 @@
 	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 --git a/arch/arm/plat-mxc/devices/platform-imx-fb.c b/arch/arm/plat-mxc/devices/platform-imx-fb.c
new file mode 100644
index 0000000..6100a7d
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-fb.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index 6795884..72ba880 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -30,7 +30,7 @@
 	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 @@
 	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 @@
 };
 #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 @@
 	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,16 @@
 	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 */
 
 struct platform_device *__init imx_add_imx_i2c(
 		const struct imx_imx_i2c_data *data,
diff --git a/arch/arm/plat-mxc/devices/platform-imx-keypad.c b/arch/arm/plat-mxc/devices/platform-imx-keypad.c
new file mode 100644
index 0000000..40238f0
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-keypad.c
@@ -0,0 +1,62 @@
+/*
+ * 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 */
+
+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 --git a/arch/arm/plat-mxc/devices/platform-imx-ssi.c b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
index 38a7a0b..2569c8d 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-ssi.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
@@ -30,14 +30,14 @@
 };
 #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 @@
 };
 #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 --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index 2039640..3c854c2 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -47,7 +47,7 @@
 };
 #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 @@
 	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 @@
 };
 #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 @@
 	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 @@
 	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 @@
 	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 --git a/arch/arm/plat-mxc/devices/platform-imx2-wdt.c b/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
new file mode 100644
index 0000000..e0aec61
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-imx21-hcd.c b/arch/arm/plat-mxc/devices/platform-imx21-hcd.c
new file mode 100644
index 0000000..5770a42
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx21-hcd.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-imx_udc.c b/arch/arm/plat-mxc/devices/platform-imx_udc.c
new file mode 100644
index 0000000..6fd675d
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx_udc.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c b/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c
new file mode 100644
index 0000000..10653cc
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-mx1-camera.c b/arch/arm/plat-mxc/devices/platform-mx1-camera.c
new file mode 100644
index 0000000..edcc581
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mx1-camera.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-mx2-camera.c b/arch/arm/plat-mxc/devices/platform-mx2-camera.c
new file mode 100644
index 0000000..b3f4828
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mx2-camera.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
new file mode 100644
index 0000000..cc488f4
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
new file mode 100644
index 0000000..90d762f
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-mxc_nand.c b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
index 3fdcc32..1568f39 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc_nand.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
@@ -31,27 +31,27 @@
 	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 --git a/arch/arm/plat-mxc/devices/platform-mxc_pwm.c b/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
new file mode 100644
index 0000000..3d8ebdb
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
@@ -0,0 +1,60 @@
+/*
+ * 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 */
+
+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 --git a/arch/arm/plat-mxc/devices/platform-mxc_rnga.c b/arch/arm/plat-mxc/devices/platform-mxc_rnga.c
new file mode 100644
index 0000000..b4b7612
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mxc_rnga.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-mxc_w1.c b/arch/arm/plat-mxc/devices/platform-mxc_w1.c
new file mode 100644
index 0000000..96fa5ea
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-mxc_w1.c
@@ -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 --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
new file mode 100644
index 0000000..b352564
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -0,0 +1,74 @@
+/*
+ * 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 */
+
+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 --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
index 17f724c..8ea49ad 100644
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-spi_imx.c
@@ -30,7 +30,7 @@
 };
 #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 @@
 	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 @@
 };
 #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 @@
 	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,7 @@
 	imx51_ecspi_data_entry(0, 1),
 	imx51_ecspi_data_entry(1, 2),
 };
-#endif /* ifdef CONFIG_ARCH_MX51 */
+#endif /* ifdef CONFIG_SOC_IMX51 */
 
 struct platform_device *__init imx_add_spi_imx(
 		const struct imx_spi_imx_data *data,
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
index 9915607..8772ce3 100644
--- a/arch/arm/plat-mxc/ehci.c
+++ b/arch/arm/plat-mxc/ehci.c
@@ -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 @@
 			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 @@
 			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 @@
 			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 @@
 		/* 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 @@
 		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 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 @@
 		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 @@
 			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 @@
 					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 @@
 				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 --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c
index ee9582f..d69d343 100644
--- a/arch/arm/plat-mxc/epit.c
+++ b/arch/arm/plat-mxc/epit.c
@@ -93,7 +93,6 @@
 	.rating		= 200,
 	.read		= epit_read,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -101,9 +100,7 @@
 {
 	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 --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 9c3e362..bc2c7bc 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -175,7 +175,7 @@
 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 @@
 {
 	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++) {
@@ -349,3 +349,113 @@
 
 	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 --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 7a1e1f8..aea2cd3 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -20,7 +20,9 @@
 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 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 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 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 --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index d56213f..3b3a37c 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -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 --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 8c6896f..8658c9c 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -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 @@
 		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 @@
 		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 @@
 		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,6 +228,31 @@
 		const struct imx_mxc_nand_data *data,
 		const struct mxc_nand_platform_data *pdata);
 
+struct imx_mxc_pwm_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+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_sdhci_esdhc_imx_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+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;
@@ -110,13 +264,3 @@
 struct platform_device *__init imx_add_spi_imx(
 		const struct imx_spi_imx_data *data,
 		const struct spi_imx_master *pdata);
-
-#include <mach/esdhc.h>
-struct imx_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,
-		const struct esdhc_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index aeb0869..bd9bb97 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -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 --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index af33b74..0044e2f 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index ebadf4a..26bb1ba 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/imxfb.h b/arch/arm/plat-mxc/include/mach/imxfb.h
index 5263506..9de8f06 100644
--- a/arch/arm/plat-mxc/include/mach/imxfb.h
+++ b/arch/arm/plat-mxc/include/mach/imxfb.h
@@ -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 @@
 };
 
 void set_imx_fb_info(struct imx_fb_platform_data *);
+#endif /* ifndef __MACH_IMXFB_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx50.h b/arch/arm/plat-mxc/include/mach/iomux-mx50.h
new file mode 100644
index 0000000..058a922
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx50.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index d7a41e9..b6767f9 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
new file mode 100644
index 0000000..5deee01
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
@@ -0,0 +1,323 @@
+/*
+ * 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_CONFIG_SION = 0x1 << 4, /* LOOPBACK:MUX SION bit */
+} 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_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 --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
index 0880a4a..2277b01 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
@@ -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
@@ -107,13 +123,13 @@
 /*
  * 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 --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 86781f7..58a49cc 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -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)
diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
index 564ec9d..8386140 100644
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ b/arch/arm/plat-mxc/include/mach/memory.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mx1.h b/arch/arm/plat-mxc/include/mach/mx1.h
index 641b246..75d9621 100644
--- a/arch/arm/plat-mxc/include/mach/mx1.h
+++ b/arch/arm/plat-mxc/include/mach/mx1.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h
index 8bc5972..6cd049e 100644
--- a/arch/arm/plat-mxc/include/mach/mx21.h
+++ b/arch/arm/plat-mxc/include/mach/mx21.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
index cf46a45..087cd7a 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
index 2237ba2..cbc43ad 100644
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ b/arch/arm/plat-mxc/include/mach/mx27.h
@@ -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 @@
 #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 @@
 #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 --git a/arch/arm/plat-mxc/include/mach/mx2x.h b/arch/arm/plat-mxc/include/mach/mx2x.h
index afb895a..6d07839 100644
--- a/arch/arm/plat-mxc/include/mach/mx2x.h
+++ b/arch/arm/plat-mxc/include/mach/mx2x.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index 61cfe82..79e7fc0 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -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 @@
 #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 @@
 #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 @@
 #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 @@
 
 #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 --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
index 6267cff..d13dbfe 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
index d1bd26d..388a407 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -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 @@
 }
 #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 --git a/arch/arm/plat-mxc/include/mach/mx50.h b/arch/arm/plat-mxc/include/mach/mx50.h
new file mode 100644
index 0000000..aaec2a6
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx50.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
index 2af7a10..873807f 100644
--- a/arch/arm/plat-mxc/include/mach/mx51.h
+++ b/arch/arm/plat-mxc/include/mach/mx51.h
@@ -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
@@ -375,7 +337,7 @@
 #define MX51_MXC_INT_FIRI		93
 #define MX51_MXC_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 --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
new file mode 100644
index 0000000..9577cdb
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx53.h
@@ -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_MMC_SDHC1_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00004000)
+#define MX53_MMC_SDHC2_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00008000)
+#define MX53_UART3_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x0000C000)
+#define MX53_CSPI1_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00010000)
+#define MX53_SSI2_BASE_ADDR		(MX53_SPBA0_BASE_ADDR + 0x00014000)
+#define MX53_MMC_SDHC3_BASE_ADDR	(MX53_SPBA0_BASE_ADDR + 0x00020000)
+#define MX53_MMC_SDHC4_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_CSPI2_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_CSPI3_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_MXC_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_MMC_SDHC1	1
+#define MX53_INT_MMC_SDHC2	2
+#define MX53_INT_MMC_SDHC3	3
+#define MX53_INT_MMC_SDHC4	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_CSPI1	36
+#define MX53_INT_CSPI2	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 --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index a42c720..04c7a26 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -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 @@
 # 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 @@
 # 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 --git a/arch/arm/plat-mxc/include/mach/mxc91231.h b/arch/arm/plat-mxc/include/mach/mxc91231.h
index 0ca3101..765190f 100644
--- a/arch/arm/plat-mxc/include/mach/mxc91231.h
+++ b/arch/arm/plat-mxc/include/mach/mxc91231.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
index 7fc5f99..a523a40 100644
--- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h
index 9be1122..913e043 100644
--- a/arch/arm/plat-mxc/include/mach/sdma.h
+++ b/arch/arm/plat-mxc/include/mach/sdma.h
@@ -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 --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index 9dd9c20..3a70ebf 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -63,6 +63,8 @@
 #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)
 {
@@ -102,6 +104,12 @@
 	case MACH_TYPE_EUKREA_CPUIMX51SD:
 		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 --git a/arch/arm/plat-mxc/iomux-v3.c b/arch/arm/plat-mxc/iomux-v3.c
index b318c6a..99a9cdb 100644
--- a/arch/arm/plat-mxc/iomux-v3.c
+++ b/arch/arm/plat-mxc/iomux-v3.c
@@ -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 (!(pad->pad_ctrl & NO_PAD_CTRL) && pad->pad_ctrl_ofs)
-		__raw_writel(pad->pad_ctrl, base + pad->pad_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);
+
 	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 --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
new file mode 100644
index 0000000..0c799ac
--- /dev/null
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -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 --git a/arch/arm/plat-mxc/irq-common.h b/arch/arm/plat-mxc/irq-common.h
new file mode 100644
index 0000000..7203543
--- /dev/null
+++ b/arch/arm/plat-mxc/irq-common.h
@@ -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 --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c
deleted file mode 100644
index 7331f2a..0000000
--- a/arch/arm/plat-mxc/irq.c
+++ /dev/null
@@ -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 --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
index 925bce4..3455fc0 100644
--- a/arch/arm/plat-mxc/system.c
+++ b/arch/arm/plat-mxc/system.c
@@ -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 @@
 		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 --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index f9a1b05..9f0c261 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -120,7 +120,6 @@
 	.rating		= 200,
 	.read		= mx1_2_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift 		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -131,9 +130,7 @@
 	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 --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index 3703ab2..e69ed8a 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -21,6 +21,8 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 
+#include "irq-common.h"
+
 /*
  *****************************************
  * TZIC Registers                        *
@@ -47,6 +49,25 @@
 
 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
  *
@@ -104,12 +125,17 @@
 	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",
+		.ack = tzic_mask_irq,
+		.mask = tzic_mask_irq,
+		.unmask = tzic_unmask_irq,
+		.set_wake = tzic_set_wake_irq,
+	},
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = tzic_set_irq_fiq,
+#endif
 };
 
 /*
@@ -141,10 +167,16 @@
 	/* 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 --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig
index 5da3f97..187f4e8 100644
--- a/arch/arm/plat-nomadik/Kconfig
+++ b/arch/arm/plat-nomadik/Kconfig
@@ -14,6 +14,7 @@
 
 config HAS_MTU
 	bool
+	select HAVE_SCHED_CLOCK
 	help
 	  Support for Multi Timer Unit. MTU provides access
 	  to multiple interrupt generating programmable
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c
index 85e6fd21..eda4e3a 100644
--- a/arch/arm/plat-nomadik/gpio.c
+++ b/arch/arm/plat-nomadik/gpio.c
@@ -119,7 +119,7 @@
 }
 
 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 @@
 	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 @@
  * 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 @@
 		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 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 @@
 }
 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
@@ -634,7 +672,7 @@
 
 	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 --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
index 8c5ae3f..05a3936 100644
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ b/arch/arm/plat-nomadik/include/plat/pincfg.h
@@ -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 @@
 #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 --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index 63cdc60..4172340 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -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 @@
  * 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;
+	cyc = -readl(mtu_base + MTU_VAL(0));
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
-/* Just kick sched_clock every so often */
-static void cnt32_to_63_keepwarm(unsigned long data)
+static void notrace nomadik_update_sched_clock(void)
 {
-	mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
-	(void) sched_clock();
-}
-
-/*
- * 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)
-{
-	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 @@
 	} 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 @@
 	/* 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 --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 92c5bb7..18fe3cb 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -11,13 +11,14 @@
 
 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 @@
 	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,6 +141,9 @@
 
          Say N unless you know you need this.
 
+config OMAP_IOMMU_IVA2
+	bool
+
 choice
 	prompt "System timer"
 	default OMAP_32K_TIMER if !ARCH_OMAP15XX
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 8722a13..ea46440 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -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>
@@ -45,7 +48,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 +57,7 @@
 #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 +66,7 @@
 #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 +75,7 @@
 #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 +84,7 @@
 #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 +96,7 @@
  * 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 +106,6 @@
 	.rating		= 250,
 	.read		= omap_32k_read_dummy,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 10,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -111,10 +113,25 @@
  * 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
+
+unsigned long long notrace 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);
+}
+
+static void notrace omap_update_sched_clock(void)
+{
+	u32 cyc = clocksource_32k.read(&clocksource_32k);
+	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 /**
@@ -168,13 +185,13 @@
 		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;
 }
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index fc81912..10245b8 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -232,46 +232,6 @@
 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 --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 2c28265..c4b2b47 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -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.
@@ -53,7 +57,11 @@
 
 #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 @@
 	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 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 @@
 #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 @@
 #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 @@
 	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 @@
 {
 	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 @@
 		} 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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 	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 @@
 	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));
+	p->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(src_start, CSSA, lch);
 
-	if (cpu_class_is_omap2())
-		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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 	}
 
 	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 @@
 	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));
+	p->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(dest_start, CDSA, lch);
 
-	if (cpu_class_is_omap2())
-		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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 		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 @@
 
 	/* 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 @@
 {
 	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 @@
 			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 @@
 		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 @@
 		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 @@
 		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 @@
 	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 @@
 		 * 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 @@
 
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 	 * 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 @@
 
 			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));
+	l = p->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;
-
+	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 @@
 
 	/* 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 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 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 @@
 
 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 @@
 			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 @@
 {
 	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 @@
 {
 	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 @@
 }
 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 @@
 					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 @@
 
 	/* 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 @@
 				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 @@
 			}
 			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 @@
 					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 @@
 		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 @@
 		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 *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 @@
 	}
 	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 @@
 	/* 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 @@
 	/* 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 @@
 	/* 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 @@
 	/* 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 @@
 		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 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 @@
 	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 @@
 		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(OMAP2_DMA_CSR_CLEAR_MASK, 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,10 +1892,10 @@
 		if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
-		status = dma_read(CSR(ch));
+		status = p->dma_read(CSR, ch);
 	}
 
-	dma_write(status, CSR(ch));
+	p->dma_write(status, CSR, ch);
 
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
@@ -2017,13 +1909,13 @@
 	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 +1941,66 @@
 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 +2017,23 @@
 			 * 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],
+			sprintf(&irq_name[0], "%d", ch);
+			dma_irq = platform_get_irq_byname(pdev, irq_name);
+
+			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 (r != 0) {
-				int i;
-
-				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 (ret != 0)
+				goto exit_dma_irq_fail;
 		}
 	}
 
@@ -2200,46 +2042,91 @@
 				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);
-
-out_unmap:
-	iounmap(omap_dma_base);
-
-	return r;
+	return ret;
 }
 
-arch_initcall(omap_init_dma);
+static int __devexit omap_system_dma_remove(struct platform_device *pdev)
+{
+	int dma_irq;
+
+	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;
+}
+
+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 --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index c05c653..1f98e0b 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -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 @@
 	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 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 @@
 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 },
-};
-
-#endif
-
+/*
+ * TODO: Cleanup gpio_bank usage as it is having information
+ * related to all instances of the device
+ */
 static struct gpio_bank *gpio_bank;
-static int gpio_bank_count;
+
+static int bank_width;
+
+/* 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	u32			val;
 	u32			l;
 
+	if (!bank->dbck_flag)
+		return;
+
 	if (debounce < 32)
 		debounce = 0x01;
 	else if (debounce > 7936)
@@ -651,7 +504,7 @@
 
 	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 @@
 	__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 @@
 
 	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 @@
 
 	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 @@
 	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;
@@ -989,7 +840,7 @@
 	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 +897,7 @@
 	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);
@@ -1296,7 +1147,8 @@
 	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 +1170,10 @@
 	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;
@@ -1377,6 +1233,7 @@
 	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);
 
@@ -1489,7 +1346,8 @@
 {
 	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 +1362,8 @@
 {
 	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 +1399,8 @@
 
 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 +1443,7 @@
 
 	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 +1505,13 @@
 	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 +1540,16 @@
 
 /*---------------------------------------------------------------------*/
 
-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 +1562,190 @@
  */
 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);
-		}
-#endif
-	}
-#endif
-
-#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]);
-		}
-	}
-#endif
-
-
-#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;
-	}
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-	if (cpu_is_omap44xx()) {
-		gpio_bank_count = OMAP34XX_NR_GPIOS;
-		gpio_bank = gpio_bank_44xx;
-	}
-#endif
-	for (i = 0; i < gpio_bank_count; i++) {
-		int j, gpio_count = 16;
-
-		bank = &gpio_bank[i];
-		spin_lock_init(&bank->lock);
-
-		/* 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;
-		}
-
-		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);
-
-			gpio_count = 32; /* 7xx has 32-bit GPIOs */
-		}
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if ((bank->method == METHOD_GPIO_24XX) ||
-				(bank->method == METHOD_GPIO_44XX)) {
+			/* 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 (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);
-
-				/*
-				 * 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;
+			if (id < ARRAY_SIZE(non_wakeup_gpios))
+				bank->non_wakeup_gpios = non_wakeup_gpios[id];
 		}
-#endif
-
-		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;
+	} 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);
 		}
-		bank->chip.ngpio = gpio_count;
+		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);
 
-		gpiochip_add(&bank->chip);
-
-		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);
+			/*
+			 * 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);
 		}
-		set_irq_chained_handler(bank->irq, gpio_irq_handler);
-		set_irq_data(bank->irq, bank);
-
-		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);
+		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);
 		}
 	}
+}
 
-	/* 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);
+static void __init omap_gpio_chip_init(struct gpio_bank *bank)
+{
+	int j;
+	static int gpio;
 
-	/* Enable autoidle for the OCP interface */
-	if (cpu_is_omap24xx())
-		omap_writel(1 << 0, 0x48019010);
-	if (cpu_is_omap34xx())
-		omap_writel(1 << 0, 0x48306814);
+	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 += bank_width;
+	}
+	bank->chip.ngpio = bank_width;
 
-	omap_gpio_show_rev();
+	gpiochip_add(&bank->chip);
+
+	for (j = bank->virtual_irq_start;
+		     j < bank->virtual_irq_start + bank_width; 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);
+}
+
+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;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	pdata = pdev->dev.platform_data;
+
+	if (!gpio_init_done) {
+		int ret;
+
+		ret = init_gpio_info(pdev);
+		if (ret)
+			return ret;
+	}
+
+	id = pdev->id;
+	bank = &gpio_bank[id];
+
+	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;
+	}
+
+	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;
+	}
+
+	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;
+	}
+
+	pm_runtime_enable(bank->dev);
+	pm_runtime_get_sync(bank->dev);
+
+	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 +1863,7 @@
 
 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 +1879,7 @@
 		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 +2040,6 @@
 	/* 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 +2070,6 @@
 
 	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 +2094,28 @@
 }
 #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 --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index a5ce4f0..a4f8003 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -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 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 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 @@
 	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 @@
 	omap_pm_set_max_mpu_wakeup_lat(dev, t);
 }
 
-static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id)
+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,
+	},
+};
+
+#ifdef CONFIG_ARCH_OMAP2PLUS
+static inline int omap2_i2c_add_bus(int bus_id)
 {
-	struct resource *res;
-	resource_size_t *irq;
+	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;
 
-	res = pdev->resource;
-
-	if (!cpu_is_omap44xx())
-		irq = omap2_i2c_irq;
-	else
-		irq = omap4_i2c_irq;
-
-	if (bus_id == 1) {
-		res[0].start = OMAP2_I2C_BASE1;
-		res[0].end = res[0].start + OMAP_I2C_SIZE;
-	}
-
-	res[1].start = irq[bus_id - 1];
 	omap2_i2c_mux_pins(bus_id);
 
+	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;
+	}
+
+	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;
+	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);
 
-		pd = pdev->dev.platform_data;
-		pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	}
-
-	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 --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h
index bb937f3..256ab3f 100644
--- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
+++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h
@@ -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 @@
 #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_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 --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index fef4696..8eb0ada 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -49,13 +49,18 @@
 /* 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 @@
  *
  * 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 @@
 	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 --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h
deleted file mode 100644
index ba0a6c0..0000000
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ /dev/null
@@ -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 --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index a9d69a0..6b8088e 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -27,6 +27,8 @@
 #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;
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index 0cce4ca..d1c916f 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -21,142 +21,16 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
+#include <linux/platform_device.h>
+
+/*
+ * 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"
 
-/* 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
-
-#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
-
-/*----------------------------------------------------------------------------*/
-
 /* DMA channels for omap1 */
 #define OMAP_DMA_NO_DEVICE		0
 #define OMAP_DMA_MCSI1_TX		1
@@ -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 @@
 #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 --git a/arch/arm/plat-omap/include/plat/fpga.h b/arch/arm/plat-omap/include/plat/fpga.h
index f1864a6..ae39bcb 100644
--- a/arch/arm/plat-omap/include/plat/fpga.h
+++ b/arch/arm/plat-omap/include/plat/fpga.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index de1c604..d6f9fa0f 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 9fd99b9..85ded59 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -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 @@
 };
 
 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 --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
index 36a0bef..878d632 100644
--- a/arch/arm/plat-omap/include/plat/i2c.h
+++ b/arch/arm/plat-omap/include/plat/i2c.h
@@ -36,6 +36,19 @@
 }
 #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 --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h
index 128b549..ef4106c 100644
--- a/arch/arm/plat-omap/include/plat/io.h
+++ b/arch/arm/plat-omap/include/plat/io.h
@@ -291,11 +291,12 @@
 }
 #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 --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 33c7d41..69230d6 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -50,6 +50,8 @@
 	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 @@
 	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 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 --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 65e20a6..2910de9 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/keypad.h b/arch/arm/plat-omap/include/plat/keypad.h
index 3ae52cc..793ce9d 100644
--- a/arch/arm/plat-omap/include/plat/keypad.h
+++ b/arch/arm/plat-omap/include/plat/keypad.h
@@ -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 @@
 /* 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 --git a/arch/arm/plat-omap/include/plat/l4_3xxx.h b/arch/arm/plat-omap/include/plat/l4_3xxx.h
new file mode 100644
index 0000000..5e19493
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/l4_3xxx.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h
index 9976565..cc3921e 100644
--- a/arch/arm/plat-omap/include/plat/mailbox.h
+++ b/arch/arm/plat-omap/include/plat/mailbox.h
@@ -46,8 +46,8 @@
 	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_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 --git a/arch/arm/plat-omap/include/plat/memory.h b/arch/arm/plat-omap/include/plat/memory.h
index d5306be..f8d922f 100644
--- a/arch/arm/plat-omap/include/plat/memory.h
+++ b/arch/arm/plat-omap/include/plat/memory.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index 728fbb9..c0a7520 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -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 @@
  * 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 @@
  * 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 @@
  * 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 --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index c8dae02..2682043 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h
index 8b3f12f..ea2b8a6 100644
--- a/arch/arm/plat-omap/include/plat/omap44xx.h
+++ b/arch/arm/plat-omap/include/plat/omap44xx.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 28e2d1a..e4c349f 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -107,6 +107,7 @@
 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 --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 7eaa8ed..6864a99 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -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 @@
 #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 @@
  * 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 @@
  * @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 @@
 	}				fw;
 	u8				addr_cnt;
 	u8				width;
-	u8				thread_cnt;
-	u8				max_burst_len;
 	u8				user;
 	u8				flags;
 };
@@ -231,11 +242,12 @@
 /* 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)
@@ -357,14 +369,14 @@
  * 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 @@
  * @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 @@
  * @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 @@
  * @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 @@
 	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 @@
 	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 @@
 	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 @@
 					   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 --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h
deleted file mode 100644
index 9ca420d..0000000
--- a/arch/arm/plat-omap/include/plat/powerdomain.h
+++ /dev/null
@@ -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 --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index ab77442..2fdf8c8 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -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 @@
 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 --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index 19145f5..cec5d56 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-omap/include/plat/smartreflex.h
new file mode 100644
index 0000000..6568c88
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/smartreflex.h
@@ -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 --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h
index ecd6a48..7a10257 100644
--- a/arch/arm/plat-omap/include/plat/smp.h
+++ b/arch/arm/plat-omap/include/plat/smp.h
@@ -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 @@
 /*
  * 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 --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index 5905100..9967d5e 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -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 @@
 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 --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index 9036e37..ad98b85 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -145,8 +145,11 @@
 		/* 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 --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 59c7fe7..450a332 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -11,6 +11,7 @@
 	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 @@
 	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_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 --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
new file mode 100644
index 0000000..0ff1233
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -0,0 +1,146 @@
+/*
+ * 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
+
+#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;
+};
+
+/* API to get the voltagedomain pointer */
+struct voltagedomain *omap_voltage_domain_lookup(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);
+int omap_voltage_late_init(void);
+#else
+static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
+		struct omap_volt_pmic_info *pmic_info) {}
+static inline  void omap_change_voltscale_method(struct voltagedomain *voltdm,
+		int voltscale_method) {}
+static inline int omap_voltage_late_init(void)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif
diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c
index b0078cf..f1295fa 100644
--- a/arch/arm/plat-omap/io.c
+++ b/arch/arm/plat-omap/io.c
@@ -136,61 +136,3 @@
 		__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 --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 6cd151b..b1107c0 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -830,6 +830,28 @@
 }
 
 /**
+ * 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 @@
 	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 --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index 8ce0de2..6dc1296 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -87,35 +87,43 @@
 }
 #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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		 * 'pa' is cotinuous(linear).
 		 */
 		pa += bytes;
+		da += bytes;
 		len -= bytes;
 	}
 	BUG_ON(len);
@@ -695,18 +706,18 @@
 	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 @@
 {
 	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 @@
 	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 --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index d2fafb8..459b319 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -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 @@
 	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 @@
 		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 @@
 	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,73 +250,77 @@
 	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 (unlikely(ret))
+				goto fail_startup;
+		} else
+			goto fail_startup;
+	}
 
-		if (ret) {
-			mutex_unlock(&mbox_configured_lock);
-			return ret;
+	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;
 		}
-		mbox_configured++;
-		mutex_unlock(&mbox_configured_lock);
-	}
+		mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
+		if (!mq) {
+			ret = -ENOMEM;
+			goto fail_alloc_txq;
+		}
+		mbox->txq = mq;
 
-	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;
+		mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
+		if (!mq) {
+			ret = -ENOMEM;
+			goto fail_alloc_rxq;
+		}
+		mbox->rxq = mq;
+		mq->mbox = mbox;
 	}
-
-	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;
-	}
-	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)
-			mbox->ops->shutdown(mbox);
-		mutex_unlock(&mbox_configured_lock);
+	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);
 }
 
-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;
@@ -324,12 +339,16 @@
 	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 +372,8 @@
 			ret = PTR_ERR(mbox->dev);
 			goto err_out;
 		}
+
+		BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
 	}
 	return 0;
 
@@ -391,7 +412,8 @@
 
 	/* 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 --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index eac4b97..b5a6e17 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -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 @@
 	 * 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 @@
 	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 @@
 		goto err_kfree;
 	}
 
-	mcbsp->free = 0;
+	mcbsp->free = false;
 	mcbsp->reg_cache = reg_cache;
 	spin_unlock(&mcbsp->lock);
 
@@ -815,7 +817,7 @@
 	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 @@
 	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 @@
 
 	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 @@
 
 		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 --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index e129ce8..b0471bb2 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -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 @@
 	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 --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index abe933c..57adb27 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -280,6 +280,34 @@
 /* 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 --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 74dac41..e26e504 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -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 @@
 	_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 --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index 715a301..c3da247 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -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 @@
 
 /*
  * 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 DEFINE_CLOCK_DATA(cd);
 
-static unsigned long tclk2ns_scale;
-
-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 struct clocksource orion_clksrc = {
 	.name		= "orion_clocksource",
-	.shift		= 20,
 	.rating		= 300,
 	.read		= orion_clksrc_read,
 	.mask		= CLOCKSOURCE_MASK(32),
@@ -245,8 +218,7 @@
 	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 --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 4aacdd1..3aca5ba 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -6,6 +6,7 @@
 
 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 --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h
index 9e604c8..75f6564 100644
--- a/arch/arm/plat-pxa/include/plat/mfp.h
+++ b/arch/arm/plat-pxa/include/plat/mfp.h
@@ -423,7 +423,7 @@
 	((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_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 --git a/arch/arm/plat-pxa/include/plat/ssp.h b/arch/arm/plat-pxa/include/plat/ssp.h
deleted file mode 100644
index fe43150..0000000
--- a/arch/arm/plat-pxa/include/plat/ssp.h
+++ /dev/null
@@ -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 --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index c6357e5..58b7980 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -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 --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index 298bafc..2572260 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -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 --git a/arch/arm/plat-spear/include/plat/keyboard.h b/arch/arm/plat-spear/include/plat/keyboard.h
new file mode 100644
index 0000000..68b5394
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/keyboard.h
@@ -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 --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c
index ab21165..839c88d 100644
--- a/arch/arm/plat-spear/time.c
+++ b/arch/arm/plat-spear/time.c
@@ -81,8 +81,6 @@
 	.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 @@
 	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 --git a/arch/arm/plat-stmp3xxx/clock.c b/arch/arm/plat-stmp3xxx/clock.c
index e593a2a..2e712e1 100644
--- a/arch/arm/plat-stmp3xxx/clock.c
+++ b/arch/arm/plat-stmp3xxx/clock.c
@@ -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 --git a/arch/arm/plat-stmp3xxx/timer.c b/arch/arm/plat-stmp3xxx/timer.c
index 063c7bc..c395630 100644
--- a/arch/arm/plat-stmp3xxx/timer.c
+++ b/arch/arm/plat-stmp3xxx/timer.c
@@ -89,7 +89,6 @@
 	.rating         = 250,
 	.read           = stmp3xxx_clock_read,
 	.mask           = CLOCKSOURCE_MASK(16),
-	.shift          = 10,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -106,8 +105,6 @@
  */
 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 @@
 
 	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 --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 5cf88e8..16dde08 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -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 --git a/arch/arm/plat-versatile/include/plat/sched_clock.h b/arch/arm/plat-versatile/include/plat/sched_clock.h
new file mode 100644
index 0000000..5c3e4fc
--- /dev/null
+++ b/arch/arm/plat-versatile/include/plat/sched_clock.h
@@ -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 --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c
index 9768cf7..3d6a4c2 100644
--- a/arch/arm/plat-versatile/sched-clock.c
+++ b/arch/arm/plat-versatile/sched-clock.c
@@ -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 <linux/sched.h>
 
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include <asm/sched_clock.h>
+#include <plat/sched_clock.h>
 
-#ifdef VERSATILE_SYS_BASE
-#define REFCOUNTER	(__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
-#endif
-
-#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 --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/plat-versatile/timer-sp.c
deleted file mode 100644
index fb0d1c2..0000000
--- a/arch/arm/plat-versatile/timer-sp.c
+++ /dev/null
@@ -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 --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 8063a32..0797cb5 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -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 @@
 	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 @@
 	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 --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
index fc767ac..52295ff 100644
--- a/arch/blackfin/mach-bf527/boards/ad7160eval.c
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -83,7 +83,7 @@
 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,
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 2c31af7..50533ed 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -82,11 +82,13 @@
 		.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"
 	},
 };
 
@@ -118,7 +120,7 @@
 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,
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index 9a736a8..d06177b 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -46,11 +46,13 @@
 		.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"
 	},
 };
 
@@ -82,7 +84,7 @@
 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,
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 9222bc0..35a88a5 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -86,11 +86,13 @@
 		.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"
 	},
 };
 
@@ -122,7 +124,7 @@
 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,
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
index 9ec5757..130861b 100644
--- a/arch/blackfin/mach-bf527/boards/tll6527m.c
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -91,7 +91,7 @@
 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,
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index f0c0eef..4c2ee67 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -482,11 +482,13 @@
 		.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"
 	},
 };
 
@@ -518,7 +520,7 @@
 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,
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 216e269..4f03fbc 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -587,11 +587,13 @@
 		.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"
 	},
 };
 
@@ -623,7 +625,7 @@
 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,
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 39e534f..f099b82 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -1542,7 +1542,7 @@
  * 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 +2185,7 @@
 };
 
 static int
-pfmfs_delete_dentry(struct dentry *dentry)
+pfmfs_delete_dentry(const struct dentry *dentry)
 {
 	return 1;
 }
@@ -2233,7 +2233,7 @@
 	}
 	path.mnt = mntget(pfmfs_mnt);
 
-	path.dentry->d_op = &pfmfs_dentry_operations;
+	d_set_d_op(path.dentry, &pfmfs_dentry_operations);
 	d_add(path.dentry, inode);
 
 	file = alloc_file(&path, FMODE_READ, &pfm_file_ops);
diff --git a/arch/mips/include/asm/ioctls.h b/arch/mips/include/asm/ioctls.h
index d87cb04..d967b89 100644
--- a/arch/mips/include/asm/ioctls.h
+++ b/arch/mips/include/asm/ioctls.h
@@ -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 --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 5c7c6fc..183e0d2 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1047,6 +1047,6 @@
 
 	return 0;
 }
-arch_initcall(init_hw_perf_events);
+early_initcall(init_hw_perf_events);
 
 #endif /* defined(CONFIG_CPU_MIPS32)... */
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index c2e4459..ac11754 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -459,7 +459,7 @@
 			tmp = CROSS_GxICR(irq, new);
 
 			x &= GxICR_LEVEL | GxICR_ENABLE;
-			if (GxICR(irq) & GxICR_REQUEST) {
+			if (GxICR(irq) & GxICR_REQUEST)
 				x |= GxICR_REQUEST | GxICR_DETECT;
 			CROSS_GxICR(irq, new) = x;
 			tmp = CROSS_GxICR(irq, new);
diff --git a/arch/parisc/include/asm/ioctls.h b/arch/parisc/include/asm/ioctls.h
index 4e06144..6ba80d0 100644
--- a/arch/parisc/include/asm/ioctls.h
+++ b/arch/parisc/include/asm/ioctls.h
@@ -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 --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 66d1f17..11bdd68 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -92,8 +92,6 @@
 
 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 @@
 	 * 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)
+	acquire_console_sem();
+	for_each_console(tmp)
 		if (tmp == &pdc_cons)
 			break;
+	release_console_sem();
 
 	if (!tmp) {
 		printk(KERN_INFO "PDC console driver not registered anymore, not creating %s\n", pdc_cons.name);
diff --git a/arch/powerpc/include/asm/ioctls.h b/arch/powerpc/include/asm/ioctls.h
index 8519200..c7dc17c 100644
--- a/arch/powerpc/include/asm/ioctls.h
+++ b/arch/powerpc/include/asm/ioctls.h
@@ -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 --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c
index 7c07de0..b150b51 100644
--- a/arch/powerpc/kernel/e500-pmu.c
+++ b/arch/powerpc/kernel/e500-pmu.c
@@ -126,4 +126,4 @@
 	return register_fsl_emb_pmu(&e500_pmu);
 }
 
-arch_initcall(init_e500_pmu);
+early_initcall(init_e500_pmu);
diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c
index 09d7202..2cc5e03 100644
--- a/arch/powerpc/kernel/mpc7450-pmu.c
+++ b/arch/powerpc/kernel/mpc7450-pmu.c
@@ -414,4 +414,4 @@
 	return register_power_pmu(&mpc7450_pmu);
 }
 
-arch_initcall(init_mpc7450_pmu);
+early_initcall(init_mpc7450_pmu);
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 3129c85..5674807 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1379,7 +1379,7 @@
 		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 --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
index 7ecca59..4dcf5f8 100644
--- a/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -681,7 +681,7 @@
 	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 --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/kernel/power4-pmu.c
index 2a361cd..ead8b3c 100644
--- a/arch/powerpc/kernel/power4-pmu.c
+++ b/arch/powerpc/kernel/power4-pmu.c
@@ -613,4 +613,4 @@
 	return register_power_pmu(&power4_pmu);
 }
 
-arch_initcall(init_power4_pmu);
+early_initcall(init_power4_pmu);
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c
index 199de52..eca0ac5 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/kernel/power5+-pmu.c
@@ -682,4 +682,4 @@
 	return register_power_pmu(&power5p_pmu);
 }
 
-arch_initcall(init_power5p_pmu);
+early_initcall(init_power5p_pmu);
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c
index 98b6a72..d5ff0f6 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/kernel/power5-pmu.c
@@ -621,4 +621,4 @@
 	return register_power_pmu(&power5_pmu);
 }
 
-arch_initcall(init_power5_pmu);
+early_initcall(init_power5_pmu);
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c
index 84a607b..3160392 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/kernel/power6-pmu.c
@@ -544,4 +544,4 @@
 	return register_power_pmu(&power6_pmu);
 }
 
-arch_initcall(init_power6_pmu);
+early_initcall(init_power6_pmu);
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c
index 852f7b7..593740f 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/kernel/power7-pmu.c
@@ -369,4 +369,4 @@
 	return register_power_pmu(&power7_pmu);
 }
 
-arch_initcall(init_power7_pmu);
+early_initcall(init_power7_pmu);
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 3fee685..9a6e093 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -494,4 +494,4 @@
 	return register_power_pmu(&ppc970_pmu);
 }
 
-arch_initcall(init_ppc970_pmu);
+early_initcall(init_ppc970_pmu);
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 3532b92..856e9c3 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -71,12 +71,18 @@
 	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 @@
 
 	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 --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index e0b98e7..ff19efd 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
 
 config SCHED_OMIT_FRAME_POINTER
-	bool
-	default y
+	def_bool y
 
 source "init/Kconfig"
 
@@ -143,20 +130,21 @@
 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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 	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 @@
 	  If unsure, say Y.
 
 config CHSC_SCH
-	tristate "Support for CHSC subchannels"
+	def_tristate y
+	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 @@
 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 @@
 	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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 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 @@
 	  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 --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index 05221b1..2b380df 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -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 @@
 	  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 --git a/arch/s390/defconfig b/arch/s390/defconfig
index e40ac6e..d796971 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -2,16 +2,12 @@
 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_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_COMPAT_BRK is not set
+CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
@@ -20,24 +16,12 @@
 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_BINFMT_MISC=m
-CONFIG_PFAULT=y
 CONFIG_HZ_100=y
 CONFIG_KEXEC=y
-CONFIG_S390_GUEST=y
 CONFIG_PM=y
 CONFIG_HIBERNATION=y
 CONFIG_PACKET=y
@@ -46,16 +30,15 @@
 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 +52,14 @@
 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 +71,92 @@
 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_DEBUG_FORCE_WEAK_PER_CPU=y
+CONFIG_KPROBES_SANITY_TEST=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 --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile
index b08d2ab..2e671d5 100644
--- a/arch/s390/hypfs/Makefile
+++ b/arch/s390/hypfs/Makefile
@@ -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 --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h
index fa487d4..80c1526 100644
--- a/arch/s390/hypfs/hypfs.h
+++ b/arch/s390/hypfs/hypfs.h
@@ -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 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 --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c
new file mode 100644
index 0000000..b478013
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_dbfs.c
@@ -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 --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index cd4a81b..6023c6d 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -555,81 +555,38 @@
 	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 @@
 		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 @@
 	debugfs_remove(dbfs_d204_file);
 	diag224_delete_name_table();
 	diag204_free_buffer();
+	hypfs_dbfs_remove_file(&dbfs_file_d204);
 }
 
 /*
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index 26cf177..e547960 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -20,8 +20,6 @@
 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 @@
 	return data;
 }
 
-static void diag2fc_free(void *data)
+static void diag2fc_free(const void *data)
 {
 	vfree(data);
 }
@@ -239,43 +237,29 @@
 	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 @@
 		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 --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 47cc446..6fe874f 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -46,8 +46,6 @@
 /* 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 @@
 {
 	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 @@
 	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 @@
 {
 	hypfs_diag_exit();
 	hypfs_vm_exit();
-	debugfs_remove(hypfs_dbfs_dir);
+	hypfs_dbfs_exit();
 	unregister_filesystem(&hypfs_type);
 	kobject_put(s390_kobj);
 }
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index e850111..ff6f62e 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -204,6 +204,8 @@
 			    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 --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 40e2ab0..0814348 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -202,7 +202,7 @@
 
 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 --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h
index b604a91..0be28ef 100644
--- a/arch/s390/include/asm/dasd.h
+++ b/arch/s390/include/asm/dasd.h
@@ -73,6 +73,7 @@
  * 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 @@
 #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 --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h
index 96c14a9..3c29be4 100644
--- a/arch/s390/include/asm/ftrace.h
+++ b/arch/s390/include/asm/ftrace.h
@@ -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 --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h
index 881d945..e4155d3 100644
--- a/arch/s390/include/asm/hardirq.h
+++ b/arch/s390/include/asm/hardirq.h
@@ -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 --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index 7da991a..db14a31 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -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 --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 330f68c..a231a94 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -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 @@
 /* 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 @@
 	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 --git a/arch/s390/include/asm/mutex.h b/arch/s390/include/asm/mutex.h
index 458c1f7..688271f 100644
--- a/arch/s390/include/asm/mutex.h
+++ b/arch/s390/include/asm/mutex.h
@@ -7,3 +7,5 @@
  */
 
 #include <asm-generic/mutex-dec.h>
+
+#define arch_mutex_cpu_relax()	barrier()
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 8d6f871..bf3de04 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -32,7 +32,6 @@
 }
 
 extern void s390_adjust_jiffies(void);
-extern void print_cpu_info(void);
 extern int get_cpu_capability(unsigned int *);
 
 /*
@@ -81,7 +80,8 @@
 	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;
 };
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index d9d42b1..9ad628a 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -331,10 +331,60 @@
 	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 --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index 46e96bc..350e7ee 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -361,6 +361,7 @@
 	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 --git a/arch/s390/include/asm/s390_ext.h b/arch/s390/include/asm/s390_ext.h
index 1a9307e..080876d 100644
--- a/arch/s390/include/asm/s390_ext.h
+++ b/arch/s390/include/asm/s390_ext.h
@@ -1,32 +1,17 @@
+/*
+ *    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/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)
- */
-
 #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 --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index edc03cb..045e009f 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -20,7 +20,6 @@
 
 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 @@
 
 #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 --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
index 3ad16db..6710b0e 100644
--- a/arch/s390/include/asm/system.h
+++ b/arch/s390/include/asm/system.h
@@ -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 @@
 	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_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 */
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 5baf023..ebc7709 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -74,7 +74,7 @@
 /* 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 @@
 #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 @@
 #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,6 +115,7 @@
 #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)
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index 09d345a..88829a4 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -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 @@
 	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 --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 33982e7..fe03c14 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -23,14 +23,16 @@
 {
 	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 @@
 	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 --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h
index 3141025..12b8238 100644
--- a/arch/s390/kernel/compat_ptrace.h
+++ b/arch/s390/kernel/compat_ptrace.h
@@ -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;
+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 */
+};
 
-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 user_regs_struct32
+struct compat_user_regs_struct
 {
 	psw_compat_t psw;
 	u32 gprs[NUM_GPRS];
@@ -50,14 +29,14 @@
 	 * 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 @@
 	__u32   len;
 	__u32   kernel_addr;
 	__u32   process_addr;
-} ptrace_area_emu31;
+} compat_ptrace_area;
 
 #endif /* _PTRACE32_H */
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1ecc337..648f642 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -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_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 @@
 1:	stm	%r10,%r11,\lc_sum
 	.endm
 
+	.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_BASE savearea
 	stm	%r12,%r15,\savearea
 	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
 	.endm
 
-	.macro	SAVE_ALL_SVC psworg,savearea
-	la	%r12,\psworg
-	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
-	.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 @@
 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 @@
 	ssm	__SF_EMPTY(%r15)
 	.endm
 
+	.section .kprobes.text, "ax"
+
 /*
  * Scheduler resume function, called by switch_to
  *  gpr2 = (task_struct *) prev
@@ -198,31 +200,21 @@
 	.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 @@
 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_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_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 @@
 # 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 @@
 # _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 @@
 # _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 @@
 	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 @@
 	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 @@
 	.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 @@
 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 @@
 	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 @@
 # 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 @@
 # 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 @@
 #
 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 @@
 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 @@
 	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 @@
 	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 @@
 	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 @@
 #		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 @@
 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 @@
 	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 @@
 	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 @@
 	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_go:
 #endif
 
+	.section .kprobes.text, "ax"
+
 #ifdef CONFIG_CHECK_STACK
 /*
  * The synchronous or the asynchronous stack overflowed. We are dead.
@@ -943,12 +942,13 @@
 	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 @@
 .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 --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 95c1dfc..17a6f83 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -12,7 +12,7 @@
 
 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 --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 8f3e802..9d3603d 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -51,7 +51,7 @@
 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 @@
 	ssm	__SF_EMPTY(%r15)
 	.endm
 
+	.section .kprobes.text, "ax"
+
 /*
  * Scheduler resume function, called by switch_to
  *  gpr2 = (task_struct *) prev
@@ -206,30 +208,21 @@
  */
 	.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 @@
 	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 @@
 # _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 @@
 	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 @@
 	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 @@
 	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 @@
 	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_go:
 #endif
 
+	.section .kprobes.text, "ax"
+
 #ifdef CONFIG_CHECK_STACK
 /*
  * The synchronous or the asynchronous stack overflowed. We are dead.
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 6a83d05..78bdf0e 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -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 @@
 		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 --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 026a37a..ea5099c 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -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 @@
 	}
 
 	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 --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 2564793..1d05d66 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -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}};
+struct kretprobe_blackpoint kretprobe_blacklist[] = { };
 
-int __kprobes arch_prepare_kprobe(struct kprobe *p)
+static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)
 {
-	/* 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;
-}
-
-int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction)
-{
-	switch (*(__u8 *) instruction) {
+	switch (insn[0] >> 8) {
 	case 0x0c:	/* bassm */
 	case 0x0b:	/* bsm	 */
 	case 0x83:	/* diag  */
@@ -68,7 +48,7 @@
 	case 0xad:	/* stosm */
 		return -EINVAL;
 	}
-	switch (*(__u16 *) instruction) {
+	switch (insn[0]) {
 	case 0x0101:	/* pr	 */
 	case 0xb25a:	/* bsa	 */
 	case 0xb240:	/* bakr  */
@@ -81,93 +61,92 @@
 	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;
+	int 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;
-	}
-
-	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 @@
 	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 @@
 	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)
+{
+	kcb->prev_kprobe.kp = __get_cpu_var(current_kprobe);
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	__get_cpu_var(current_kprobe) = p;
+}
+
+/*
+ * 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) = 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));
-}
-
-static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
-						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);
 }
 
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
@@ -251,79 +234,104 @@
 	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 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 @@
 	 *	 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 @@
 			/* 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 @@
 
 		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 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 (fixup & FIXUP_PSW_NORMAL)
+		ip += (unsigned long) p->addr - (unsigned long) p->ainsn.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_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_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_RETURN_REGISTER) {
+		int reg = (p->ainsn.insn[0] & 0xf0) >> 4;
+		regs->gprs[reg] += (unsigned long) p->addr -
+				   (unsigned long) p->ainsn.insn;
+	}
 
-	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;
-
-	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 @@
 	 * 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 @@
 		 * 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 @@
 		 * 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 @@
 		 * 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_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 @@
 
 	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 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 @@
 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 --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index dfe015d..1e6a557 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -7,6 +7,8 @@
 
 #include <asm/asm-offsets.h>
 
+	.section .kprobes.text, "ax"
+
 	.globl ftrace_stub
 ftrace_stub:
 	br	%r14
@@ -16,22 +18,12 @@
 #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 @@
 	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 --git a/arch/s390/kernel/mcount64.S b/arch/s390/kernel/mcount64.S
index c37211c..e736672 100644
--- a/arch/s390/kernel/mcount64.S
+++ b/arch/s390/kernel/mcount64.S
@@ -7,6 +7,8 @@
 
 #include <asm/asm-offsets.h>
 
+	.section .kprobes.text, "ax"
+
 	.globl ftrace_stub
 ftrace_stub:
 	br	%r14
@@ -16,12 +18,6 @@
 #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 @@
 	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 --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 1995c17..fab8843 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -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 @@
 	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 --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index ec2e03b..6ba4222 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -32,6 +32,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/syscalls.h>
 #include <linux/compat.h>
+#include <linux/kprobes.h>
 #include <asm/compat.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -41,6 +42,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 +77,8 @@
  */
 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 +113,17 @@
 	}
 }
 
-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 +213,10 @@
 	/* 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;
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 644548e..311e9d7 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -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 @@
 }
 
 /*
- * 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 @@
 	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 @@
 				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 @@
 			   "machine = %04X\n",
 			   n, id->version, id->ident, id->machine);
 	}
-	preempt_enable();
+	put_online_cpus();
 	return 0;
 }
 
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 019bb71..ef86ad2 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -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 @@
 	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;
+	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;
 
-	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
+	/* TIF_SINGLE_STEP overrides the user specified PER registers. */
+	new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?
+		&per_single_step : &thread->per_user;
+
+	/* Take care of the PER enablement bit in the PSW. */
+	if (!(new->control & PER_EVENT_MASK)) {
 		regs->psw.mask &= ~PSW_MASK_PER;
-
-	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;
-
-	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);
+		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 @@
 # 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 @@
 
 	} 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 @@
 	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 @@
 
 	} 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 @@
  */
 
 /*
+ * 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 @@
 
 	} 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 @@
 }
 
 /*
+ * 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 @@
 
 	} 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.
-		 * 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.
-		 */
-		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 @@
 {
 	unsigned long addr = caddr;
 	unsigned long data = cdata;
-	ptrace_area_emu31 parea; 
+	compat_ptrace_area parea;
 	int copied, ret;
 
 	switch (request) {
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index bd1db50..1850299 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -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/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/module.h>
+#include <linux/kernel.h>
+#include <linux/ftrace.h>
+#include <linux/errno.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 @@
 
 int register_external_interrupt(__u16 code, ext_int_handler_t handler)
 {
-        ext_int_info_t *p;
-        int index;
+	struct ext_int_info *p;
+	int index;
 
-	p = kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
-        if (p == NULL)
-                return -ENOMEM;
-        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;
 }
-
-int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
-				      ext_int_info_t *p)
-{
-        int index;
-
-        if (p == NULL)
-                return -EINVAL;
-        p->code = code;
-        p->handler = handler;
-	index = ext_hash(code);
-        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 @@
 	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 @@
 	irq_exit();
 	set_irq_regs(old_regs);
 }
-
-EXPORT_SYMBOL(register_external_interrupt);
-EXPORT_SYMBOL(unregister_external_interrupt);
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index ee7ac8b..abbb3c3 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -505,7 +505,7 @@
 			 * 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 --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 94cf510..63a97db 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -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 @@
 {
 	unsigned long bits;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++;
 	/*
 	 * handle bit signal external calls
 	 *
@@ -469,25 +471,25 @@
 	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 task_struct *p;
+struct create_idle {
+	struct work_struct work;
+	struct task_struct *idle;
+	struct completion done;
+	int cpu;
+};
 
-	/*
-	 *  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;
+static void __cpuinit smp_fork_idle(struct work_struct *work)
+{
+	struct create_idle *c_idle;
+
+	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 @@
 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 @@
 
 	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 @@
 	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 @@
 		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 @@
 #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 @@
 	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 --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index f754a6d..9e7b039 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -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 @@
 /*
  * 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 @@
 				       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 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 --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 7064082..5eb78dd 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -365,12 +365,10 @@
 		((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 +449,8 @@
 		"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 +686,7 @@
 	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 +731,6 @@
         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 --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 7eff9b7..1ccdf4d 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -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 @@
 }
 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 @@
 	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 @@
 	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 --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index a725158..f66a1bd 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -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 @@
 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 --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 7c37ec3..0f53110 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -47,7 +47,6 @@
 	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 @@
 		if (clock_saved)
 			local_tick_enable(clock_saved);
 	} while (get_clock() < end);
-	set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
 /*
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index fe5701e..2c57806 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -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 @@
 	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 @@
 	 * 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 @@
 /*
  * '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 @@
 	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 @@
 	}
 }
 
-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 --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 2e9d78d..fff2522 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -1,7 +1,7 @@
 config SUPERH
 	def_bool y
 	select EMBEDDED
-	select HAVE_CLK
+	select CLKDEV_LOOKUP
 	select HAVE_IDE if HAS_IOPORT
 	select HAVE_MEMBLOCK
 	select HAVE_OPROFILE
@@ -162,7 +162,8 @@
 	def_bool y
 
 config NO_IOPORT
-	bool
+	def_bool !PCI
+	depends on !SH_CAYMAN && !SH_SH4202_MICRODEV
 
 config IO_TRAPPED
 	bool
@@ -275,6 +276,7 @@
 	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 +348,8 @@
 	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 +358,7 @@
 	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 +413,7 @@
 	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 +424,7 @@
 	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 +432,14 @@
 	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 +457,7 @@
 	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 +465,9 @@
 	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 +492,7 @@
 	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 +582,6 @@
 	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 --git a/arch/sh/boards/board-secureedge5410.c b/arch/sh/boards/board-secureedge5410.c
index 32f875e..f968f17 100644
--- a/arch/sh/boards/board-secureedge5410.c
+++ b/arch/sh/boards/board-secureedge5410.c
@@ -29,8 +29,6 @@
  */
 static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id)
 {
-	ctrl_delay();	/* dummy read */
-
 	printk("SnapGear: erase switch interrupt!\n");
 
 	return IRQ_HANDLED;
diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c
index a5ecfba..87618c9 100644
--- a/arch/sh/boards/mach-highlander/setup.c
+++ b/arch/sh/boards/mach-highlander/setup.c
@@ -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 --git a/arch/sh/boards/mach-rsk/devices-rsk7203.c b/arch/sh/boards/mach-rsk/devices-rsk7203.c
index 4fa08ba..a8089f7 100644
--- a/arch/sh/boards/mach-rsk/devices-rsk7203.c
+++ b/arch/sh/boards/mach-rsk/devices-rsk7203.c
@@ -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 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 --git a/arch/sh/boards/mach-sdk7786/Makefile b/arch/sh/boards/mach-sdk7786/Makefile
index 23ff7d4..8ae56e9 100644
--- a/arch/sh/boards/mach-sdk7786/Makefile
+++ b/arch/sh/boards/mach-sdk7786/Makefile
@@ -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 --git a/arch/sh/boards/mach-sdk7786/nmi.c b/arch/sh/boards/mach-sdk7786/nmi.c
new file mode 100644
index 0000000..edcfa1f
--- /dev/null
+++ b/arch/sh/boards/mach-sdk7786/nmi.c
@@ -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 --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c
index 7e0c4e3..75e4ddb 100644
--- a/arch/sh/boards/mach-sdk7786/setup.c
+++ b/arch/sh/boards/mach-sdk7786/setup.c
@@ -237,6 +237,7 @@
 	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 --git a/arch/sh/boards/mach-se/7206/irq.c b/arch/sh/boards/mach-se/7206/irq.c
index d96194960..9070d7e 100644
--- a/arch/sh/boards/mach-se/7206/irq.c
+++ b/arch/sh/boards/mach-se/7206/irq.c
@@ -140,7 +140,7 @@
 	make_se7206_irq(IRQ1_IRQ); /* ATA */
 	make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
 
-	__raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR); /* ICR1 */
+	__raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */
 
 	/* FPGA System register setup*/
 	__raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */
diff --git a/arch/sh/boards/mach-se/7206/setup.c b/arch/sh/boards/mach-se/7206/setup.c
index 7f4871c..33039e0 100644
--- a/arch/sh/boards/mach-se/7206/setup.c
+++ b/arch/sh/boards/mach-se/7206/setup.c
@@ -79,6 +79,11 @@
 }
 __initcall(se7206_devices_setup);
 
+static int se7206_mode_pins(void)
+{
+	return MODE_PIN1 | MODE_PIN2;
+}
+
 /*
  * The Machine Vector
  */
@@ -87,4 +92,5 @@
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 256,
 	.mv_init_irq		= init_se7206_IRQ,
+	.mv_mode_pins		= se7206_mode_pins,
 };
diff --git a/arch/sh/boards/mach-se/board-se7619.c b/arch/sh/boards/mach-se/board-se7619.c
index 1d0ef7f..82b6d4a 100644
--- a/arch/sh/boards/mach-se/board-se7619.c
+++ b/arch/sh/boards/mach-se/board-se7619.c
@@ -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 --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig
index 9ad904a..cc61eda 100644
--- a/arch/sh/configs/migor_defconfig
+++ b/arch/sh/configs/migor_defconfig
@@ -54,6 +54,8 @@
 # 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 --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 60ee09a..a09c77d 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -382,14 +382,13 @@
 	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 --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
index 7b42c24..afc2455 100644
--- a/arch/sh/drivers/push-switch.c
+++ b/arch/sh/drivers/push-switch.c
@@ -107,7 +107,7 @@
 		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 --git a/arch/sh/include/asm/clkdev.h b/arch/sh/include/asm/clkdev.h
index 5645f35..6ba9186 100644
--- a/arch/sh/include/asm/clkdev.h
+++ b/arch/sh/include/asm/clkdev.h
@@ -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 --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index b237d52..89ab2c5 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -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,
@@ -15,12 +16,6 @@
  * 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 +26,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,15 +40,196 @@
 #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 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; })
 
-#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(); })
+#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))
+
+#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_; })
+
+#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)); })
+
+#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)
+
+#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)		\
+{									\
+	type ret;							\
+	jump_to_uncached();						\
+	ret = __raw_read##bwlq(addr);					\
+	back_to_cached();						\
+	return ret;							\
+}									\
+									\
+static inline void write##bwlq##_uncached(type v, unsigned long addr)	\
+{									\
+	jump_to_uncached();						\
+	__raw_write##bwlq(v, addr);					\
+	back_to_cached();						\
+}
+
+__BUILD_UNCACHED_IO(b, u8)
+__BUILD_UNCACHED_IO(w, u16)
+__BUILD_UNCACHED_IO(l, u32)
+__BUILD_UNCACHED_IO(q, u64)
+
+#define __BUILD_MEMORY_STRING(pfx, bwlq, type)				\
+									\
+static inline void							\
+pfx##writes##bwlq(volatile void __iomem *mem, const void *addr,		\
+		  unsigned int count)					\
+{									\
+	const volatile type *__addr = addr;				\
+									\
+	while (count--) {						\
+		__raw_write##bwlq(*__addr, mem);			\
+		__addr++;						\
+	}								\
+}									\
+									\
+static inline void pfx##reads##bwlq(volatile void __iomem *mem,		\
+				    void *addr, unsigned int count)	\
+{									\
+	volatile type *__addr = addr;					\
+									\
+	while (count--) {						\
+		*__addr = __raw_read##bwlq(mem);			\
+		__addr++;						\
+	}								\
+}
+
+__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(__raw_, l, u32)
+#endif
+
+__BUILD_MEMORY_STRING(__raw_, q, u64)
+
+#ifdef CONFIG_HAS_IOPORT
+
+/*
+ * Slowdown I/O port space accesses for antique hardware.
+ */
+#undef CONF_SLOWDOWN_IO
+
+/*
+ * 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;
+
+static inline void __set_io_port_base(unsigned long pbase)
+{
+	*(unsigned long *)&sh_io_port_base = pbase;
+	barrier();
+}
+
+#ifdef CONFIG_GENERIC_IOMAP
+#define __ioport_map ioport_map
+#else
+extern void __iomem *__ioport_map(unsigned long addr, unsigned int size);
+#endif
+
+#ifdef CONF_SLOWDOWN_IO
+#define SLOW_DOWN_IO __raw_readw(sh_io_port_base)
+#else
+#define SLOW_DOWN_IO
+#endif
+
+#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;							\
+}
+
+#define __BUILD_IOPORT_PFX(bus, bwlq, type)				\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, ,)			\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO)
+
+#define BUILDIO_IOPORT(bwlq, type)					\
+	__BUILD_IOPORT_PFX(, bwlq, type)
+
+BUILDIO_IOPORT(b, u8)
+BUILDIO_IOPORT(w, u16)
+BUILDIO_IOPORT(l, u32)
+BUILDIO_IOPORT(q, u64)
+
+#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++;						\
+	}								\
+}
+
+__BUILD_IOPORT_STRING(b, u8)
+__BUILD_IOPORT_STRING(w, u16)
+__BUILD_IOPORT_STRING(l, u32)
+__BUILD_IOPORT_STRING(q, u64)
+
+#endif
 
 /*
  * Legacy SuperH on-chip I/O functions
@@ -130,139 +277,11 @@
 	__raw_writeq(v, addr);
 }
 
-extern unsigned long generic_io_base;
-
-static inline void ctrl_delay(void)
-{
-	__raw_readw(generic_io_base);
-}
-
-#define __BUILD_UNCACHED_IO(bwlq, type)					\
-static inline type read##bwlq##_uncached(unsigned long addr)		\
-{									\
-	type ret;							\
-	jump_to_uncached();						\
-	ret = __raw_read##bwlq(addr);					\
-	back_to_cached();						\
-	return ret;							\
-}									\
-									\
-static inline void write##bwlq##_uncached(type v, unsigned long addr)	\
-{									\
-	jump_to_uncached();						\
-	__raw_write##bwlq(v, addr);					\
-	back_to_cached();						\
-}
-
-__BUILD_UNCACHED_IO(b, u8)
-__BUILD_UNCACHED_IO(w, u16)
-__BUILD_UNCACHED_IO(l, u32)
-__BUILD_UNCACHED_IO(q, u64)
-
-#define __BUILD_MEMORY_STRING(bwlq, type)				\
-									\
-static inline void __raw_writes##bwlq(volatile void __iomem *mem,	\
-				const void *addr, unsigned int count)	\
-{									\
-	const volatile type *__addr = addr;				\
-									\
-	while (count--) {						\
-		__raw_write##bwlq(*__addr, mem);			\
-		__addr++;						\
-	}								\
-}									\
-									\
-static inline void __raw_reads##bwlq(volatile void __iomem *mem,	\
-			       void *addr, unsigned int count)		\
-{									\
-	volatile type *__addr = addr;					\
-									\
-	while (count--) {						\
-		*__addr = __raw_read##bwlq(mem);			\
-		__addr++;						\
-	}								\
-}
-
-__BUILD_MEMORY_STRING(b, u8)
-__BUILD_MEMORY_STRING(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)
-#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
-
-#define readb_relaxed(a)	readb(a)
-#define readw_relaxed(a)	readw(a)
-#define readl_relaxed(a)	readl(a)
-#define readq_relaxed(a)	readq(a)
-
-#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)))
-
-#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))
-
-#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))
-
-#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))
-#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)
-
-#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 IO_SPACE_LIMIT 0xffffffff
 
 /* synco on SH-4A, otherwise a nop */
 #define mmiowb()		wmb()
 
-#define IO_SPACE_LIMIT 0xffffffff
-
-#ifdef CONFIG_HAS_IOPORT
-
-/*
- * 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 __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n))
-
-#endif
-
 /* 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);
@@ -395,10 +414,6 @@
 #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 --git a/arch/sh/include/asm/io_generic.h b/arch/sh/include/asm/io_generic.h
index 491df93..b5f6956 100644
--- a/arch/sh/include/asm/io_generic.h
+++ b/arch/sh/include/asm/io_generic.h
@@ -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 --git a/arch/sh/include/asm/ioctls.h b/arch/sh/include/asm/ioctls.h
index eb6c4c6..84e85a7 100644
--- a/arch/sh/include/asm/ioctls.h
+++ b/arch/sh/include/asm/ioctls.h
@@ -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 --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h
index a0b0cf7..dd5d6e5 100644
--- a/arch/sh/include/asm/machvec.h
+++ b/arch/sh/include/asm/machvec.h
@@ -23,27 +23,6 @@
 	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
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index f6edc10..de167d3 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -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 --git a/arch/sh/include/asm/ptrace_32.h b/arch/sh/include/asm/ptrace_32.h
index 35d9e25..6c2239c 100644
--- a/arch/sh/include/asm/ptrace_32.h
+++ b/arch/sh/include/asm/ptrace_32.h
@@ -76,7 +76,7 @@
 #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 --git a/arch/sh/include/asm/ptrace_64.h b/arch/sh/include/asm/ptrace_64.h
index d43c1cb..bf9be77 100644
--- a/arch/sh/include/asm/ptrace_64.h
+++ b/arch/sh/include/asm/ptrace_64.h
@@ -13,7 +13,7 @@
 #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 --git a/arch/sh/include/asm/unaligned-sh4a.h b/arch/sh/include/asm/unaligned-sh4a.h
index 9f4dd25..c48a9c3 100644
--- a/arch/sh/include/asm/unaligned-sh4a.h
+++ b/arch/sh/include/asm/unaligned-sh4a.h
@@ -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 @@
 	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 --git a/arch/sh/include/mach-common/mach/romimage.h b/arch/sh/include/mach-common/mach/romimage.h
index 08fb422..3670455 100644
--- a/arch/sh/include/mach-common/mach/romimage.h
+++ b/arch/sh/include/mach-common/mach/romimage.h
@@ -4,7 +4,7 @@
 
 #else /* __ASSEMBLY__ */
 
-extern inline void mmcif_update_progress(int nr)
+static inline void mmcif_update_progress(int nr)
 {
 }
 
diff --git a/arch/sh/include/mach-ecovec24/mach/romimage.h b/arch/sh/include/mach-ecovec24/mach/romimage.h
index 1dcf5e6..d63ef51 100644
--- a/arch/sh/include/mach-ecovec24/mach/romimage.h
+++ b/arch/sh/include/mach-ecovec24/mach/romimage.h
@@ -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 --git a/arch/sh/include/mach-kfr2r09/mach/romimage.h b/arch/sh/include/mach-kfr2r09/mach/romimage.h
index 976256a..7a883167 100644
--- a/arch/sh/include/mach-kfr2r09/mach/romimage.h
+++ b/arch/sh/include/mach-kfr2r09/mach/romimage.h
@@ -23,7 +23,7 @@
 
 #else /* __ASSEMBLY__ */
 
-extern inline void mmcif_update_progress(int nr)
+static inline void mmcif_update_progress(int nr)
 {
 }
 
diff --git a/arch/sh/include/mach-sdk7786/mach/fpga.h b/arch/sh/include/mach-sdk7786/mach/fpga.h
index 40f0c2d..a9cdac4 100644
--- a/arch/sh/include/mach-sdk7786/mach/fpga.h
+++ b/arch/sh/include/mach-sdk7786/mach/fpga.h
@@ -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 --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 8eed6a4..77f7ae1 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -11,7 +11,7 @@
 
 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 @@
 	   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_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 --git a/arch/sh/kernel/clkdev.c b/arch/sh/kernel/clkdev.c
deleted file mode 100644
index 1f800ef..0000000
--- a/arch/sh/kernel/clkdev.c
+++ /dev/null
@@ -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 --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index 4edcb60..d49c213 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -20,4 +20,4 @@
 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 --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c
index e2f63d6..dd0e0f2 100644
--- a/arch/sh/kernel/cpu/clock-cpg.c
+++ b/arch/sh/kernel/cpu/clock-cpg.c
@@ -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 --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 50f887d..4187cf4 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -48,20 +48,4 @@
 	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 --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
new file mode 100644
index 0000000..e80a936
--- /dev/null
+++ b/arch/sh/kernel/cpu/proc.c
@@ -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_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 --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
index 0c9f24d..5b7f12e 100644
--- a/arch/sh/kernel/cpu/sh2/clock-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
@@ -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 @@
 
 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 --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
index b26264d..1174e2d 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
@@ -22,19 +22,12 @@
 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)
 {
-	return 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 @@
 
 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 --git a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
index 7e75d8f..95a008e 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
@@ -25,21 +25,11 @@
 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 @@
 
 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 --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
index b27a5e2..3c314d7 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
@@ -22,19 +22,11 @@
 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 @@
 
 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 --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index b601fa3..3f6f8e9 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -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>
 
@@ -81,8 +81,7 @@
 	for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
 		int divisor = frqcr3_divisors[i];
 
-		if (clk->ops->set_rate(clk, clk->parent->rate /
-						divisor, 0) == 0)
+		if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
 			break;
 	}
 
diff --git a/arch/sh/kernel/cpu/sh4/perf_event.c b/arch/sh/kernel/cpu/sh4/perf_event.c
index dbf3b4b..748955d 100644
--- a/arch/sh/kernel/cpu/sh4/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4/perf_event.c
@@ -250,4 +250,4 @@
 
 	return register_sh_pmu(&sh7750_pmu);
 }
-arch_initcall(sh7750_pmu_init);
+early_initcall(sh7750_pmu_init);
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
index 71291ae..93c6460 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
index 7ce5bbc..049dc062 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 2030f3d..9d23a36 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
index d3938f0..55493cd 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
index 271c0b32..d08fa95 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
index ce39a2a..e073e3e 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
index 1f1df48..599630f 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
index 62d7063..8894926 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
index c3e458a..2d96024 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
index 597c9fb..42e403b 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
index 4f70df6..1afdb93 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
@@ -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 --git a/arch/sh/kernel/cpu/sh4a/perf_event.c b/arch/sh/kernel/cpu/sh4a/perf_event.c
index 5802765..17e6beb 100644
--- a/arch/sh/kernel/cpu/sh4a/perf_event.c
+++ b/arch/sh/kernel/cpu/sh4a/perf_event.c
@@ -284,4 +284,4 @@
 
 	return register_sh_pmu(&sh4a_pmu);
 }
-arch_initcall(sh4a_pmu_init);
+early_initcall(sh4a_pmu_init);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index c016c00..0170dbd 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -522,10 +522,13 @@
 	},
 };
 
-static struct resource usb_ohci_resources[] = {
+#define USB_EHCI_START 0xffe70000
+#define USB_OHCI_START 0xffe70400
+
+static struct resource usb_ehci_resources[] = {
 	[0] = {
-		.start	= 0xffe70400,
-		.end	= 0xffe704ff,
+		.start	= USB_EHCI_START,
+		.end	= USB_EHCI_START + 0x3ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -535,12 +538,35 @@
 	},
 };
 
-static u64 usb_ohci_dma_mask = DMA_BIT_MASK(32);
+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	= USB_OHCI_START,
+		.end	= USB_OHCI_START + 0x3ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 77,
+		.end	= 77,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 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 +596,7 @@
 
 static struct platform_device *sh7786_devices[] __initdata = {
 	&dma0_device,
+	&usb_ehci_device,
 	&usb_ohci_device,
 };
 
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c
deleted file mode 100644
index 447d78f..0000000
--- a/arch/sh/kernel/io_generic.c
+++ /dev/null
@@ -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 --git a/arch/sh/kernel/iomap.c b/arch/sh/kernel/iomap.c
new file mode 100644
index 0000000..2e8e8b9
--- /dev/null
+++ b/arch/sh/kernel/iomap.c
@@ -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 --git a/arch/sh/kernel/ioport.c b/arch/sh/kernel/ioport.c
new file mode 100644
index 0000000..e3ad610
--- /dev/null
+++ b/arch/sh/kernel/ioport.c
@@ -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 --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c
index 9f9bb63..3d722e4 100644
--- a/arch/sh/kernel/machvec.c
+++ b/arch/sh/kernel/machvec.c
@@ -118,28 +118,6 @@
 		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 --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c
index 5a4b334..2ee21a4 100644
--- a/arch/sh/kernel/perf_event.c
+++ b/arch/sh/kernel/perf_event.c
@@ -389,7 +389,7 @@
 
 	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 --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index d6b018c..4f26716 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -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 @@
 {
 	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 --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index 97e3feb..a2c5898 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -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)/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 @@
 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)/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 @@
 	@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 --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c
new file mode 100644
index 0000000..c0a798f
--- /dev/null
+++ b/arch/sparc/boot/piggyback.c
@@ -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 --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c
deleted file mode 100644
index ac944ae..0000000
--- a/arch/sparc/boot/piggyback_32.c
+++ /dev/null
@@ -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 --git a/arch/sparc/boot/piggyback_64.c b/arch/sparc/boot/piggyback_64.c
deleted file mode 100644
index a26a686..0000000
--- a/arch/sparc/boot/piggyback_64.c
+++ /dev/null
@@ -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 --git a/arch/sparc/include/asm/ioctls.h b/arch/sparc/include/asm/ioctls.h
index 53f4ee0..ed3807b 100644
--- a/arch/sparc/include/asm/ioctls.h
+++ b/arch/sparc/include/asm/ioctls.h
@@ -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 --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
index 3ea5964..8580d17 100644
--- a/arch/sparc/include/asm/leon.h
+++ b/arch/sparc/include/asm/leon.h
@@ -224,6 +224,18 @@
 			  "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 --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h
index 618e888..263c719 100644
--- a/arch/sparc/include/asm/leon_amba.h
+++ b/arch/sparc/include/asm/leon_amba.h
@@ -100,9 +100,8 @@
 	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 @@
 	u32 force[16];
 	/* Extended IRQ registers */
 	u32 intid[16];	/* 0xc0 */
+	u32 unused[(0x1000-0x100)/4];
 };
 
 struct leon3_apbuart_regs_map {
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h
index 9e5c640..71e5e9a 100644
--- a/arch/sparc/include/asm/oplib_32.h
+++ b/arch/sparc/include/asm/oplib_32.h
@@ -48,18 +48,6 @@
 /* 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 @@
 /* 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 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_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 @@
 /* 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 @@
 /* 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_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 --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h
index 8cd0df3..97a9047 100644
--- a/arch/sparc/include/asm/oplib_64.h
+++ b/arch/sparc/include/asm/oplib_64.h
@@ -18,8 +18,8 @@
  */
 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 --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/perf_event.h
index 6e8bfa1..4d3dbe3 100644
--- a/arch/sparc/include/asm/perf_event.h
+++ b/arch/sparc/include/asm/perf_event.h
@@ -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 @@
 	(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 --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index 21bb259..5942349 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -73,12 +73,11 @@
 
 	/* 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 --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index f01c426..fdab7f8 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -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 @@
 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 @@
 			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 @@
 # 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 @@
 #endif
 
 	}
+	return;
+bad:
+	printk(KERN_ERR "No Timer/irqctrl found\n");
+	BUG();
+	return;
 }
 
 void leon_clear_clock_irq(void)
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index a4bd7ba..300f810 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -270,8 +270,6 @@
 			atomic_set(&nmi_active, -1);
 		}
 	}
-	if (!err)
-		init_hw_perf_events();
 
 	return err;
 }
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 0d6deb5..7605786 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1307,20 +1307,23 @@
 	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 --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c
index 0a37e8c..05fb253 100644
--- a/arch/sparc/kernel/prom_32.c
+++ b/arch/sparc/kernel/prom_32.c
@@ -136,18 +136,29 @@
 /* "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 @@
 
 	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 --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index b22ce61..648f216 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -185,7 +185,6 @@
 
 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 @@
 	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 --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index ddd0d86..b5137cc 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -435,16 +435,14 @@
 
 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 --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile
index 816c0fa..8287bbe 100644
--- a/arch/sparc/prom/Makefile
+++ b/arch/sparc/prom/Makefile
@@ -5,12 +5,10 @@
 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 --git a/arch/sparc/prom/bootstr_32.c b/arch/sparc/prom/bootstr_32.c
index 916831d..f5ec32e 100644
--- a/arch/sparc/prom/bootstr_32.c
+++ b/arch/sparc/prom/bootstr_32.c
@@ -29,7 +29,8 @@
 		/* 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 --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c
index 4886310..b05e3db 100644
--- a/arch/sparc/prom/console_32.c
+++ b/arch/sparc/prom/console_32.c
@@ -27,13 +27,14 @@
 	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 @@
 {
 	while (len) {
 		int n = prom_nbputchar(buf);
-		if (n)
+		if (n < 0)
 			continue;
 		len--;
 		buf++;
diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c
index ed39e75..9de6c8c 100644
--- a/arch/sparc/prom/console_64.c
+++ b/arch/sparc/prom/console_64.c
@@ -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 --git a/arch/sparc/prom/devmap.c b/arch/sparc/prom/devmap.c
deleted file mode 100644
index 46157d2..0000000
--- a/arch/sparc/prom/devmap.c
+++ /dev/null
@@ -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 --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c
index 3ff911e..9c6ac4b 100644
--- a/arch/sparc/prom/init_64.c
+++ b/arch/sparc/prom/init_64.c
@@ -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
@@ -38,7 +38,6 @@
 	if (!prom_chosen_node || 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");
diff --git a/arch/sparc/prom/misc_32.c b/arch/sparc/prom/misc_32.c
index 4d61c54..8c278c3 100644
--- a/arch/sparc/prom/misc_32.c
+++ b/arch/sparc/prom/misc_32.c
@@ -70,7 +70,7 @@
 /* Drop into the prom, but completely terminate the program.
  * No chance of continuing.
  */
-void
+void __noreturn
 prom_halt(void)
 {
 	unsigned long flags;
diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c
index 4c4dc79..97c44c9 100644
--- a/arch/sparc/prom/mp.c
+++ b/arch/sparc/prom/mp.c
@@ -41,81 +41,3 @@
 
 	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 --git a/arch/sparc/prom/palloc.c b/arch/sparc/prom/palloc.c
deleted file mode 100644
index 2e2a88b..0000000
--- a/arch/sparc/prom/palloc.c
+++ /dev/null
@@ -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 --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c
index 541fc82..0857aa9 100644
--- a/arch/sparc/prom/ranges.c
+++ b/arch/sparc/prom/ranges.c
@@ -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 @@
 	}
 }
 
-void
+static void
 prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
 		   struct linux_prom_ranges *ranges2, int nranges2)
 {
diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c
index 535e2e6..bc8e4cb 100644
--- a/arch/sparc/prom/tree_32.c
+++ b/arch/sparc/prom/tree_32.c
@@ -20,7 +20,7 @@
 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;
@@ -52,7 +52,7 @@
 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;
@@ -177,20 +177,6 @@
 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 @@
 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,17 +213,6 @@
 	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.
@@ -299,19 +274,6 @@
 }
 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 @@
 	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();
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e330da2..b6fccb0 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -377,6 +377,18 @@
 
 	  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 +397,10 @@
 	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 +482,19 @@
 	  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"
@@ -1141,16 +1170,16 @@
 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
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 2ac9069..15588a0 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -310,6 +310,9 @@
 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
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index b59ee76..45143bb 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -117,6 +117,17 @@
 	  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
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 52f85a1..35af09d 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -182,7 +182,7 @@
 	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 --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 76561d2..13009d1 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -66,6 +66,7 @@
 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 @@
  * 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 --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index c8517f8..6aee50d 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -3,36 +3,53 @@
 
 #include <linux/pci.h>
 
-extern struct pci_device_id k8_nb_ids[];
+extern struct pci_device_id amd_nb_misc_ids[];
 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_get_nodes(struct bootnode *nodes);
+extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn);
+extern int amd_scan_nodes(void);
 
-struct k8_northbridge_info {
-	u16 num;
-	u8 gart_supported;
-	struct pci_dev **nb_misc;
+struct amd_northbridge {
+	struct pci_dev *misc;
 };
-extern struct k8_northbridge_info k8_northbridges;
+
+struct amd_northbridge_info {
+	u16 num;
+	u64 flags;
+	struct amd_northbridge *nb;
+};
+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;
+}
+
+static inline int amd_nb_has_feature(int feature)
+{
+	return ((amd_northbridges.flags & feature) == feature);
+}
+
+static inline struct amd_northbridge *node_to_amd_nb(int node)
+{
+	return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] : NULL;
 }
 
 #else
 
-static inline struct pci_dev *node_to_k8_nb_misc(int node)
-{
-	return NULL;
-}
+#define amd_nb_num(x)		0
+#define amd_nb_has_feature(x)	false
+#define node_to_amd_nb(x)	NULL
+
 #endif
 
 
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index f6ce0bd..5e3969c 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -234,16 +234,17 @@
 extern void setup_local_APIC(void);
 extern void 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 --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index a859ca4..47a30ff 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -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 --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index 8e62185..c8bfe63 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -124,6 +124,7 @@
 	X86_SUBARCH_LGUEST,
 	X86_SUBARCH_XEN,
 	X86_SUBARCH_MRST,
+	X86_SUBARCH_CE4100,
 	X86_NR_SUBARCHS,
 };
 
diff --git a/arch/x86/include/asm/debugreg.h b/arch/x86/include/asm/debugreg.h
index b81002f..078ad0c 100644
--- a/arch/x86/include/asm/debugreg.h
+++ b/arch/x86/include/asm/debugreg.h
@@ -94,7 +94,7 @@
 
 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 --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 9479a03..0141b23 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -117,6 +117,10 @@
 	FIX_TEXT_POKE1,	/* reserve 2 pages for text_poke() */
 	FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
 	__end_of_permanent_fixed_addresses,
+
+#ifdef	CONFIG_X86_MRST
+	FIX_LNW_VRTC,
+#endif
 	/*
 	 * 256 temporary boot-time mappings, used by early_ioremap(),
 	 * before ioremap() is functional.
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index 4aa2bb3..ef32890 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -93,6 +93,17 @@
 	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 @@
 		     _ASM_EXTABLE(1b, 3b)
 		     : [err] "=r" (err)
 		     : [fx] "R" (fx), "m" (*fx), "0" (0));
+#endif
 	return err;
 }
 
@@ -119,6 +131,17 @@
 		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 @@
 		     _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 --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index a6b28d0..f327d38 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -159,7 +159,7 @@
 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 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 @@
 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 --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 13b0eba..ba870bb 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -15,10 +15,6 @@
 	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 --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h
index 5bdfca8..f23eb25 100644
--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -28,7 +28,7 @@
 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 --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index c62c13c..eb16e94 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -223,6 +223,9 @@
 
 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 --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index ef51b50..2421507 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -48,6 +48,12 @@
 
 #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 --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index c82868e..0c90dd9 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -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 @@
 				 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 @@
 	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 @@
 	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 --git a/arch/x86/include/asm/mpspec_def.h b/arch/x86/include/asm/mpspec_def.h
index 4a7f96d..c0a955a 100644
--- a/arch/x86/include/asm/mpspec_def.h
+++ b/arch/x86/include/asm/mpspec_def.h
@@ -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 --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/mrst-vrtc.h
new file mode 100644
index 0000000..73668ab
--- /dev/null
+++ b/arch/x86/include/asm/mrst-vrtc.h
@@ -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 --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index 4a711a6..719f00b 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -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 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 --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 6b89f5e..4d0dfa0 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -123,6 +123,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 +257,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 --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index 932f0f8..c4021b9 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -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,8 @@
 
 void arch_trigger_all_cpu_backtrace(void);
 #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
-
-static inline void localise_nmi_watchdog(void)
-{
-	if (nmi_watchdog == NMI_IO_APIC)
-		nmi_watchdog = NMI_LOCAL_APIC;
-}
-
-/* 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
 
-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 --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index ef99758..7709c12 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -112,7 +112,7 @@
 
 static inline void halt(void)
 {
-	PVOP_VCALL0(pv_irq_ops.safe_halt);
+	PVOP_VCALL0(pv_irq_ops.halt);
 }
 
 static inline void wbinvd(void)
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index ca0437c..6761292 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -65,6 +65,7 @@
 
 #define PCIBIOS_MIN_CARDBUS_IO	0x4000
 
+extern int pcibios_enabled;
 void pcibios_config_init(void);
 struct pci_bus *pcibios_scan_root(int bus);
 
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index f899e01..8ee4516 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -230,6 +230,125 @@
 })
 
 /*
+ * 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("\n1:mov "__percpu_arg(1)",%%al"			\
+		    "\n\tcmpxchgb %2, "__percpu_arg(1)			\
+		    "\n\tjnz 1b"					\
+			    : "=a" (pxo_ret__), "+m" (var)		\
+			    : "q" (pxo_new__)				\
+			    : "memory");				\
+		break;							\
+	case 2:								\
+		asm("\n1:mov "__percpu_arg(1)",%%ax"			\
+		    "\n\tcmpxchgw %2, "__percpu_arg(1)			\
+		    "\n\tjnz 1b"					\
+			    : "=a" (pxo_ret__), "+m" (var)		\
+			    : "r" (pxo_new__)				\
+			    : "memory");				\
+		break;							\
+	case 4:								\
+		asm("\n1:mov "__percpu_arg(1)",%%eax"			\
+		    "\n\tcmpxchgl %2, "__percpu_arg(1)			\
+		    "\n\tjnz 1b"					\
+			    : "=a" (pxo_ret__), "+m" (var)		\
+			    : "r" (pxo_new__)				\
+			    : "memory");				\
+		break;							\
+	case 8:								\
+		asm("\n1:mov "__percpu_arg(1)",%%rax"			\
+		    "\n\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 @@
 #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,11 @@
 #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 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_1(pcp, val)	percpu_add_op((pcp), val)
 #define irqsafe_cpu_add_2(pcp, val)	percpu_add_op((pcp), val)
@@ -299,6 +429,31 @@
 #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)
+#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)
+
+#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 +466,7 @@
 #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 +474,12 @@
 #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 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)
-
 #endif
 
 /* This is not atomic against other CPUs -- CPU preemption needs to be off */
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 550e26b1..d9d4dae 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -125,7 +125,6 @@
 #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 @@
 }
 
 #else
-static inline void init_hw_perf_events(void)		{ }
 static inline void perf_events_lapic_init(void)	{ }
 #endif
 
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
index a70cd21..295e2ff 100644
--- a/arch/x86/include/asm/perf_event_p4.h
+++ b/arch/x86/include/asm/perf_event_p4.h
@@ -744,14 +744,6 @@
 };
 
 /*
- * 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 +780,60 @@
 	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 --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index cae9c3c..c6efecf 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -141,10 +141,9 @@
 #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;
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index d6763b139a..db8aa19 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -53,6 +53,12 @@
 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 --git a/arch/x86/include/asm/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h
index 1def601..6c22bf3 100644
--- a/arch/x86/include/asm/smpboot_hooks.h
+++ b/arch/x86/include/asm/smpboot_hooks.h
@@ -48,7 +48,6 @@
 		setup_IO_APIC();
 	else {
 		nr_ioapics = 0;
-		localise_nmi_watchdog();
 	}
 #endif
 }
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index 2b16a2a..52b5c7e 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -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 @@
 };
 
 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 @@
 #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 --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
index 5469630..fa7b917 100644
--- a/arch/x86/include/asm/timer.h
+++ b/arch/x86/include/asm/timer.h
@@ -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 --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index 42d412f..ce1d54c 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -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
  */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 1e99475..34244b2 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -85,7 +85,6 @@
 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 --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 71232b9..ec881c6 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -198,6 +198,11 @@
 {
 	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;
@@ -847,18 +852,6 @@
  * 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 +873,7 @@
 		return count;
 	}
 
-	acpi_register_lapic_address(acpi_lapic_addr);
+	register_lapic_address(acpi_lapic_addr);
 
 	return count;
 }
@@ -907,16 +900,16 @@
 		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 +942,6 @@
 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 +972,7 @@
 	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 +1047,7 @@
 		mp_irq.srcbusirq = i; /* Identity mapped */
 		mp_irq.dstirq = pin;
 
-		save_mp_irq(&mp_irq);
+		mp_save_irq(&mp_irq);
 	}
 }
 
@@ -1117,7 +1084,7 @@
 	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 --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 5079f24..1236085 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -353,6 +353,7 @@
 	mutex_unlock(&smp_alt);
 }
 
+bool skip_smp_alternatives;
 void alternatives_smp_switch(int smp)
 {
 	struct smp_alt_module *mod;
@@ -368,7 +369,7 @@
 	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 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 @@
 		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 @@
 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 @@
 	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 --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 8f6463d..affacb5 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -12,95 +12,116 @@
 
 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);
+struct amd_northbridge_info amd_northbridges;
+EXPORT_SYMBOL(amd_northbridges);
 
-static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
+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++;
+
+	if (i == 0)
+		return 0;
+
+	nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
+	if (!nb)
+		return -ENOMEM;
+
+	amd_northbridges.nb = nb;
+	amd_northbridges.num = i;
+
+	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)
-		k8_northbridges.gart_supported = 1;
+		amd_northbridges.flags |= AMD_NB_GART;
 
-	k8_northbridges.nb_misc = kmalloc((k8_northbridges.num + 1) *
-					  sizeof(void *), GFP_KERNEL);
-	if (!k8_northbridges.nb_misc)
-		return -ENOMEM;
+	/*
+	 * 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;
 
-	if (!k8_northbridges.num) {
-		k8_northbridges.nb_misc[0] = NULL;
-		return 0;
-	}
-
-	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;
-		}
-	}
-
-	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 +130,16 @@
 	   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 +150,23 @@
 	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 --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 92543c7..7c9ab59 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -315,6 +315,7 @@
 
 	if (system_state == SYSTEM_BOOTING) {
 		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 (request_irq(adev->irq, apbt_interrupt_handler,
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index b3a16e8..dcd7c83 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -206,7 +206,7 @@
  * 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.
@@ -303,7 +303,7 @@
 		dev_limit = 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);
@@ -358,7 +358,7 @@
 		dev_limit = 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);
@@ -400,7 +400,7 @@
 		dev_limit = 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;
@@ -518,7 +518,7 @@
 		dev_base = bus_dev_ranges[i].dev_base;
 		dev_limit = 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 --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile
index 910f20b4..3966b56 100644
--- a/arch/x86/kernel/apic/Makefile
+++ b/arch/x86/kernel/apic/Makefile
@@ -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 --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 7821813..79e6baa 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -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>
 
@@ -432,17 +431,18 @@
 	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 @@
 {
 	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;
@@ -799,11 +799,7 @@
 	 * 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 @@
 			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 @@
 #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 @@
 	 * 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 @@
 		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,7 +1380,6 @@
 	}
 #endif
 
-	setup_apic_nmi_watchdog(NULL);
 	apic_pm_activate();
 
 	/*
@@ -1538,13 +1530,60 @@
 	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 +1613,12 @@
 				"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;
-		}
+		if (apic_force_enable())
+			return -1;
+	} else {
+		if (apic_verify())
+			return -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;
-	}
-	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 +1630,6 @@
 }
 #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 +1655,7 @@
 		 * 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 +1677,27 @@
 	}
 }
 
+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)
 {
@@ -1758,17 +1762,10 @@
 		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 --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c
index 62f6e1e..72ec29e 100644
--- a/arch/x86/kernel/apic/hw_nmi.c
+++ b/arch/x86/kernel/apic/hw_nmi.c
@@ -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 @@
 			break;
 		mdelay(1);
 	}
+
+	clear_bit(0, &backtrace_flag);
+	smp_mb__after_clear_bit();
 }
 
 static int __kprobes
@@ -50,7 +64,7 @@
 {
 	struct die_args *args = __args;
 	struct pt_regs *regs;
-	int cpu = smp_processor_id();
+	int cpu;
 
 	switch (cmd) {
 	case DIE_NMI:
@@ -62,6 +76,7 @@
 	}
 
 	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;
@@ -91,18 +106,3 @@
 }
 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 --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index fadcd74..697dc34 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -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 @@
 }
 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 @@
 	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 @@
  *
  * 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 @@
 	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 @@
 			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 @@
 						= 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 @@
 			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 @@
 		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 @@
 			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 @@
 				      "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 @@
 	 */
 	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 @@
 				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 @@
 		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 @@
 		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 @@
 	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 @@
 	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 @@
 		ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
 		ioapic_res++;
 	}
+
+	probe_nr_irqs_gsi();
 }
 
 void __init ioapic_insert_resources(void)
@@ -4103,7 +4087,8 @@
 
 	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 --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
deleted file mode 100644
index c90041c..0000000
--- a/arch/x86/kernel/apic/nmi.c
+++ /dev/null
@@ -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 --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index c1c52c3..ecca5f4 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -48,6 +48,16 @@
 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 @@
 	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 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 @@
 		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 @@
 	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 @@
 
 static __cpuinit void set_x2apic_extra_bits(int pnode)
 {
-	__get_cpu_var(x2apic_extra_bits) = (pnode << 6);
+	__this_cpu_write(x2apic_extra_bits, (pnode << 6));
 }
 
 /*
@@ -682,27 +684,32 @@
 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 @@
 		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 @@
 		/*
 		 * 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 @@
 		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 @@
 
 	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 --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 9e093f8..7c7bedb 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -668,7 +668,7 @@
 
 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 --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4b68bda..1d59834 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -894,7 +894,6 @@
 #else
 	vgetcpu_set_mode();
 #endif
-	init_hw_perf_events();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index 491977b..35c7e65 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -521,7 +521,7 @@
 
 	*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 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);
 }
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 17ad033..7283e98 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -149,8 +149,7 @@
 };
 
 struct amd_l3_cache {
-	struct	 pci_dev *dev;
-	bool	 can_disable;
+	struct	 amd_northbridge *nb;
 	unsigned indices;
 	u8	 subcaches[4];
 };
@@ -266,7 +265,7 @@
 		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 +287,7 @@
 	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 +310,12 @@
 /*
  * 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 +327,14 @@
 	l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
 }
 
-static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
+static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
+					int index)
 {
-	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 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 +342,7 @@
 	 * 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 +351,12 @@
 
 	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 +370,7 @@
 {
 	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 +384,8 @@
 {
 	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 +420,7 @@
 		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 +430,7 @@
 		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 +487,8 @@
 	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 +509,7 @@
 #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 +522,7 @@
 		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 +536,7 @@
 
 	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 +944,48 @@
 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 +1096,11 @@
 
 		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 --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 7a35b72..d916183 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -326,7 +326,7 @@
 
 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 @@
 {
 	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 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 @@
 
 	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_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 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 @@
 /* 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_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 @@
 	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 @@
 	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 --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 80c4823..5bf2fac 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -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 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 @@
 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);
 	}
 
-	tr->b->interrupt_enable ?
-	    (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
-	    (mci_misc_hi &= ~MASK_INT_TYPE_HI);
+	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;
+		}
+	}
 
-	mci_misc_hi |= MASK_COUNT_EN_HI;
-	wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+	tr->b->interrupt_enable ?
+	    (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
+	    (hi &= ~MASK_INT_TYPE_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 @@
 			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;
-			}
+			offset = setup_APIC_mce(offset,
+						(high & MASK_LVTOFF_HI) >> 20);
 
-			high &= ~MASK_LVTOFF_HI;
-			high |= lvt_off << 20;
-			wrmsr(address, low, high);
+			memset(&b, 0, sizeof(b));
+			b.cpu		= cpu;
+			b.bank		= bank;
+			b.block		= block;
+			b.address	= address;
 
-			threshold_defaults.address = address;
-			tr.b = &threshold_defaults;
-			tr.reset = 0;
-			tr.old_limit = 0;
-			threshold_restart_bank(&tr);
-
+			mce_threshold_block_init(&b, offset);
 			mce_threshold_vector = amd_threshold_interrupt;
 		}
 	}
@@ -298,9 +318,8 @@
 
 	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 @@
 	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 @@
 			continue;
 		err = threshold_create_bank(cpu, bank);
 		if (err)
-			goto out;
+			return err;
 	}
-out:
+
 	return err;
 }
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 6fcd093..8694ef56 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -130,7 +130,7 @@
 	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 --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 4b68326..e12246f 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -53,8 +53,13 @@
 	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);
+
 static DEFINE_PER_CPU(struct thermal_state, thermal_state);
 
 static atomic_t therm_throt_en	= ATOMIC_INIT(0);
@@ -200,6 +205,22 @@
 	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 +334,22 @@
 #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 +358,9 @@
 
 	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 --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 6d75b91..0492101 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -330,9 +330,6 @@
 {
 	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 @@
 	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 @@
 		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 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 @@
 	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 @@
 
 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);
 }
@@ -1243,7 +1271,7 @@
 		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 +1295,8 @@
 	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 +1307,8 @@
 		 * 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;
@@ -1362,7 +1390,7 @@
 	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 +1405,18 @@
 		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 +1464,12 @@
 	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 +1483,9 @@
  */
 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 +1495,12 @@
  */
 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 +1711,7 @@
 
 	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 --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index e421b8c..67e2202 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -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 @@
 	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 @@
 	if (!nb)
 		return NULL;
 
-	nb->nb_id = nb_id;
+	nb->nb_id = -1;
 
 	/*
 	 * initialize all possible NB constraints
@@ -306,7 +304,7 @@
 	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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 
 		cpuhw->amd_nb = NULL;
 	}
-
-	raw_spin_unlock(&amd_nb_lock);
 }
 
 static __initconst const struct x86_pmu amd_pmu = {
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index c8f5c08..008835c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -649,7 +649,7 @@
 	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 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 @@
 	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 --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index d9f4ff8..d5a2366 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -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 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 @@
 	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 --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 6e8752c..8474c99 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -175,21 +175,21 @@
 
 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, "");
 }
 
 /*
@@ -210,7 +210,7 @@
 		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);
 
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index 1bc7f75..74cc1ed 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -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 @@
 			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 @@
 
 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 @@
 		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 @@
 		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 --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 6a34048..6410133 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -139,8 +139,8 @@
  * 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,6 +149,7 @@
 	unsigned used = 0;
 	struct thread_info *tinfo;
 	int graph = 0;
+	unsigned long bp;
 
 	if (!task)
 		task = current;
@@ -160,18 +161,7 @@
 			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 @@
 
 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 @@
 	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 @@
 
 		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 --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 4572f25..cd28a35 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -240,7 +240,7 @@
 		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 @@
 			hsu_early_console_init();
 			early_console_register(&early_hsu_console, keep);
 		}
-
 #endif
 		buf++;
 	}
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 3afb33f..382eb29 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -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 @@
 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_post_process(void)
 {
 	modifying_code = 0;
+	set_all_modules_text_ro();
 	set_kernel_text_ro();
 	return 0;
 }
@@ -167,9 +170,9 @@
 
 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_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 --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 7633101..7f138b3 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -61,6 +61,9 @@
 	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 --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index c0dbd9a..9f54b20 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -139,39 +139,6 @@
 	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
@@ -181,7 +148,6 @@
  *
  * Note that the stack is not yet set up!
  */
-default_entry:
 #ifdef CONFIG_X86_PAE
 
 	/*
@@ -261,7 +227,42 @@
 	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
@@ -282,7 +283,7 @@
 	movl %eax,%fs
 	movl %eax,%gs
 #endif /* CONFIG_SMP */
-3:
+default_entry:
 
 /*
  *	New page tables may be in 4Mbyte page mode and may
@@ -316,6 +317,10 @@
 	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? */
@@ -611,6 +616,8 @@
 #endif
 	iret
 
+#include "verify_cpu.S"
+
 	__REFDATA
 .align 4
 ENTRY(initial_code)
@@ -622,13 +629,13 @@
 __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
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c
index 42c5942..02f0763 100644
--- a/arch/x86/kernel/hw_breakpoint.c
+++ b/arch/x86/kernel/hw_breakpoint.c
@@ -122,7 +122,7 @@
 		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 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 --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 83ec017..3a43caa 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -234,7 +234,7 @@
 	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();
@@ -350,12 +350,12 @@
 	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);
 			raw_spin_lock(&desc->lock);
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 96656f2..48ff6dc 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -79,7 +79,7 @@
 	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
@@ -166,7 +166,7 @@
 
 	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 --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 1cbd54c..d91c477 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -403,7 +403,7 @@
 
 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 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 @@
 		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 @@
 
 		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 @@
 {
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	}
 	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 --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index ce0cb47..0fe6d1a 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -155,12 +155,6 @@
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 	}
 
 	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 --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index dcb65cc..1a1b606 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -364,8 +364,7 @@
 
 		/* For performance reasons, reuse mc area when possible */
 		if (!mc || mc_size > curr_mc_size) {
-			if (mc)
-				vfree(mc);
+			vfree(mc);
 			mc = vmalloc(mc_size);
 			if (!mc)
 				break;
@@ -374,13 +373,11 @@
 
 		if (get_ucode_data(mc, ucode_ptr, mc_size) ||
 		    microcode_sanity_check(mc) < 0) {
-			vfree(mc);
 			break;
 		}
 
 		if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) {
-			if (new_mc)
-				vfree(new_mc);
+			vfree(new_mc);
 			new_rev = mc_header.rev;
 			new_mc  = mc;
 			mc = NULL;	/* trigger new vmalloc */
@@ -390,12 +387,10 @@
 		leftover  -= mc_size;
 	}
 
-	if (mc)
-		vfree(mc);
+	vfree(mc);
 
 	if (leftover) {
-		if (new_mc)
-			vfree(new_mc);
+		vfree(new_mc);
 		state = UCODE_ERROR;
 		goto out;
 	}
@@ -405,8 +400,7 @@
 		goto out;
 	}
 
-	if (uci->mc)
-		vfree(uci->mc);
+	vfree(uci->mc);
 	uci->mc = (struct microcode_intel *)new_mc;
 
 	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 9af64d9..01b0f6d 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -118,21 +118,8 @@
 
 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 @@
 		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 @@
 /*
  * Read/parse the MPC
  */
-
 static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
 {
 
@@ -275,18 +199,6 @@
 
 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 @@
 #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 @@
 			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 @@
 
 		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 @@
 	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 @@
 		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 --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index ba0f0ca..c01ffa5 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -143,7 +143,7 @@
 
 	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 @@
 {
 	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 @@
 	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 @@
  * 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 @@
 
 	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 @@
 	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 @@
 	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 @@
 	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 --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 57d1868..09c08a1 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -91,8 +91,7 @@
 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)
@@ -374,6 +373,7 @@
 {
 	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
@@ -444,8 +444,9 @@
 void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
 {
 	trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id());
+	trace_cpu_idle((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 +461,8 @@
 {
 	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);
@@ -481,10 +483,12 @@
 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());
 }
 
 /*
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 96586c3..4b9befa 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -113,8 +113,8 @@
 			stop_critical_timings();
 			pm_idle();
 			start_critical_timings();
-
 			trace_power_end(smp_processor_id());
+			trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
 		}
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index b3d7a3a..4c818a7 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -142,6 +142,8 @@
 			start_critical_timings();
 
 			trace_power_end(smp_processor_id());
+			trace_cpu_idle(PWR_EVENT_EXIT,
+				       smp_processor_id());
 
 			/* In many cases the interrupt that ended idle
 			   has already called exit_idle. But some idle
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c
index fda313e..c8e41e9 100644
--- a/arch/x86/kernel/reboot_fixups_32.c
+++ b/arch/x86/kernel/reboot_fixups_32.c
@@ -43,17 +43,33 @@
 	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 --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index a0f52af..d3cfe26c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -705,7 +705,7 @@
 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 @@
 	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 @@
 #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 --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 083e99d..c7149c9 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -281,6 +281,13 @@
 	 */
 	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 @@
 	 */
 	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 @@
 
 	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;
@@ -1061,8 +1058,6 @@
 		printk(KERN_INFO "SMP mode deactivated.\n");
 		smpboot_clear_io_apic();
 
-		localise_nmi_watchdog();
-
 		connect_bsp_APIC();
 		setup_local_APIC();
 		end_local_APIC_setup();
@@ -1094,7 +1089,7 @@
 
 	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();
 	/*
@@ -1166,6 +1161,20 @@
 	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 @@
 #ifdef CONFIG_X86_IO_APIC
 	setup_ioapic_dest();
 #endif
-	check_nmi_watchdog();
 	mtrr_aps_init();
 }
 
@@ -1341,8 +1349,6 @@
 	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 @@
 
 	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
@@ -1397,11 +1403,11 @@
 	int i;
 	void *mwait_ptr;
 
-	if (!cpu_has(&current_cpu_data, X86_FEATURE_MWAIT))
+	if (!cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_MWAIT))
 		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 +1458,7 @@
 
 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 --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index b53c525..938c8e1 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -73,22 +73,22 @@
  */
 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 --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c
index fb5cc5e1..25a28a2 100644
--- a/arch/x86/kernel/time.c
+++ b/arch/x86/kernel/time.c
@@ -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 @@
 	/* 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 --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
index 3af2dff..075d130 100644
--- a/arch/x86/kernel/trampoline_64.S
+++ b/arch/x86/kernel/trampoline_64.S
@@ -127,7 +127,7 @@
 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 --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index cb838ca..c76aaca 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -83,6 +83,8 @@
 
 static int ignore_nmis;
 
+int unknown_nmi_panic;
+
 static inline void conditional_sti(struct pt_regs *regs)
 {
 	if (regs->flags & X86_EFLAGS_IF)
@@ -300,6 +302,13 @@
 	die("general protection fault", regs, error_code);
 }
 
+static int __init setup_unknown_nmi_panic(char *str)
+{
+	unknown_nmi_panic = 1;
+	return 1;
+}
+__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
+
 static notrace __kprobes void
 mem_parity_error(unsigned char reason, struct pt_regs *regs)
 {
@@ -342,9 +351,11 @@
 	reason = (reason & 0xf) | 8;
 	outb(reason, 0x61);
 
-	i = 2000;
-	while (--i)
-		udelay(1000);
+	i = 20000;
+	while (--i) {
+		touch_nmi_watchdog();
+		udelay(100);
+	}
 
 	reason &= ~8;
 	outb(reason, 0x61);
@@ -371,7 +382,7 @@
 			reason, smp_processor_id());
 
 	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
-	if (panic_on_unrecovered_nmi)
+	if (unknown_nmi_panic || panic_on_unrecovered_nmi)
 		panic("NMI: Not continuing");
 
 	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
@@ -397,20 +408,8 @@
 		if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
 							== NOTIFY_STOP)
 			return;
-
-#ifndef CONFIG_LOCKUP_DETECTOR
-		/*
-		 * Ok, so this is none of the documented NMI sources,
-		 * so it must be the NMI watchdog.
-		 */
-		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);
 #endif
+		unknown_nmi_error(reason, regs);
 
 		return;
 	}
@@ -446,14 +445,12 @@
 
 void stop_nmi(void)
 {
-	acpi_nmi_disable();
 	ignore_nmis++;
 }
 
 void restart_nmi(void)
 {
 	ignore_nmis--;
-	acpi_nmi_enable();
 }
 
 /* May run on IST stack. */
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 0c40d8b..03d2ea8 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -659,7 +659,7 @@
 
 	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 @@
 
 	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 @@
 	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 (!hpet && !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)
+		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 @@
 		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 @@
 		mark_tsc_unstable("TSCs unsynchronized");
 
 	check_system_tsc_reliable();
-	init_tsc_clocksource();
 }
 
diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S
new file mode 100644
index 0000000..0edefc1
--- /dev/null
+++ b/arch/x86/kernel/verify_cpu.S
@@ -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 --git a/arch/x86/kernel/verify_cpu_64.S b/arch/x86/kernel/verify_cpu_64.S
deleted file mode 100644
index 56a8c2a..0000000
--- a/arch/x86/kernel/verify_cpu_64.S
+++ /dev/null
@@ -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 --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e03530a..bf47007 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -69,7 +69,7 @@
 
 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 @@
 
 	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 @@
 		__bss_start = .;
 		*(.bss..page_aligned)
 		*(.bss)
-		. = ALIGN(4);
+		. = ALIGN(PAGE_SIZE);
 		__bss_stop = .;
 	}
 
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index f628234..3cece05 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -575,6 +575,8 @@
 	s->pics[1].elcr_mask = 0xde;
 	s->pics[0].pics_state = s;
 	s->pics[1].pics_state = s;
+	s->pics[0].isr_ack = 0xff;
+	s->pics[1].isr_ack = 0xff;
 
 	/*
 	 * Initialize PIO device
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index fb8b376..fbb04ae 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2394,7 +2394,8 @@
 			ASSERT(!VALID_PAGE(root));
 			spin_lock(&vcpu->kvm->mmu_lock);
 			kvm_mmu_free_some_pages(vcpu);
-			sp = kvm_mmu_get_page(vcpu, i << 30, i << 30,
+			sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
+					      i << 30,
 					      PT32_ROOT_LEVEL, 1, ACC_ALL,
 					      NULL);
 			root = __pa(sp->spt);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b989e1f..46a368c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -976,7 +976,7 @@
 	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 +1061,7 @@
 	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);
@@ -4427,7 +4427,7 @@
 
 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 +4441,7 @@
 		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,
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S
index e7d5382..4f420c2f 100644
--- a/arch/x86/lguest/i386_head.S
+++ b/arch/x86/lguest/i386_head.S
@@ -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 @@
 	/* 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 --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c
index ff485d3..fc45ba8 100644
--- a/arch/x86/lib/delay.c
+++ b/arch/x86/lib/delay.c
@@ -121,7 +121,7 @@
 	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 --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 5554339..09df2f9 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -23,7 +23,7 @@
 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 --git a/arch/x86/mm/amdtopology_64.c b/arch/x86/mm/amdtopology_64.c
new file mode 100644
index 0000000..08a0069
--- /dev/null
+++ b/arch/x86/mm/amdtopology_64.c
@@ -0,0 +1,236 @@
+/*
+ * 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 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_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 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);
+
+		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 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 --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index c0e28a1..947f42ab 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -364,8 +364,9 @@
 	/*
 	 * 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 --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 0e969f9..f89b5bb 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -226,7 +226,7 @@
 
 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;
 }
@@ -912,6 +912,23 @@
 	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 +963,7 @@
 	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 --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
deleted file mode 100644
index 804a3b6..0000000
--- a/arch/x86/mm/k8topology_64.c
+++ /dev/null
@@ -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 --git a/arch/x86/mm/kmemcheck/error.c b/arch/x86/mm/kmemcheck/error.c
index af3b6c8..704a37c 100644
--- a/arch/x86/mm/kmemcheck/error.c
+++ b/arch/x86/mm/kmemcheck/error.c
@@ -185,7 +185,7 @@
 	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 --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 7ffc9b7..7762a51 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -264,7 +264,7 @@
 static char *cmdline __initdata;
 
 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;
@@ -274,13 +274,13 @@
 	if (acpi)
 		nr_nodes = acpi_get_nodes(physnodes);
 #endif
-#ifdef CONFIG_K8_NUMA
-	if (k8)
-		nr_nodes = k8_get_nodes(physnodes);
+#ifdef CONFIG_AMD_NUMA
+	if (amd)
+		nr_nodes = 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++) {
@@ -549,7 +549,7 @@
  * 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;
@@ -557,7 +557,7 @@
 	int num_nodes;
 	int i;
 
-	num_phys_nodes = setup_physnodes(addr, max_addr, acpi, k8);
+	num_phys_nodes = setup_physnodes(addr, max_addr, acpi, amd);
 	/*
 	 * 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,
@@ -602,7 +602,7 @@
 #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,7 +610,7 @@
 	nodes_clear(node_online_map);
 
 #ifdef CONFIG_NUMA_EMU
-	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, k8))
+	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd))
 		return;
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
@@ -624,8 +624,8 @@
 	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);
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 532e793..8b830ca 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -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>
@@ -255,13 +256,16 @@
 				   unsigned long pfn)
 {
 	pgprot_t forbidden = __pgprot(0);
+	pgprot_t required = __pgprot(0);
 
 	/*
 	 * 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
@@ -278,6 +282,12 @@
 	if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
 		   __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
 		pgprot_val(forbidden) |= _PAGE_RW;
+	/*
+	 * .data and .bss should always be writable.
+	 */
+	if (within(address, (unsigned long)_sdata, (unsigned long)_edata) ||
+	    within(address, (unsigned long)__bss_start, (unsigned long)__bss_stop))
+		pgprot_val(required) |= _PAGE_RW;
 
 #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
 	/*
@@ -317,6 +327,7 @@
 #endif
 
 	prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
+	prot = __pgprot(pgprot_val(prot) | pgprot_val(required));
 
 	return prot;
 }
@@ -393,7 +404,7 @@
 {
 	unsigned long nextpage_addr, numpages, pmask, psize, flags, 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;
 
@@ -438,10 +449,10 @@
 	 * 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 +461,17 @@
 	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 +494,7 @@
 	 * 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.
diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c
index a3250aa..410531d 100644
--- a/arch/x86/mm/setup_nx.c
+++ b/arch/x86/mm/setup_nx.c
@@ -41,7 +41,7 @@
 {
 	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 --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c
index a17dffd..f164345 100644
--- a/arch/x86/mm/srat_32.c
+++ b/arch/x86/mm/srat_32.c
@@ -92,6 +92,7 @@
 	/* 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 --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index a35cb9d..171a0aa 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -134,6 +134,10 @@
 	}
 
 	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 @@
 		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;
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index 2d49d4e..72cbec1 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -126,7 +126,7 @@
 	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 --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 4e8baad..f24a853 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -143,7 +143,7 @@
 
 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)
@@ -732,6 +732,9 @@
 		case 0x14:
 			cpu_type = "x86-64/family14h";
 			break;
+		case 0x15:
+			cpu_type = "x86-64/family15h";
+			break;
 		default:
 			return -ENODEV;
 		}
diff --git a/arch/x86/oprofile/nmi_timer_int.c b/arch/x86/oprofile/nmi_timer_int.c
index e3ecb71..0636dd9 100644
--- a/arch/x86/oprofile/nmi_timer_int.c
+++ b/arch/x86/oprofile/nmi_timer_int.c
@@ -58,9 +58,6 @@
 
 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 --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index a011bcc..c3b8e24 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -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 @@
 	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 @@
 {
 	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 @@
 {
 	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 @@
 			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 @@
 	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 @@
 	}
 
 	/* 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 @@
 	}
 
 	/* 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 @@
 	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 @@
 	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 @@
 	 * 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 @@
 		ret = setup_ibs_ctl(i);
 		if (ret)
 			return ret;
+		pr_err(FW_BUG "using offset %d for IBS interrupts\n", i);
 		return 0;
 	}
 
@@ -630,21 +638,29 @@
 	return 0;
 }
 
-/* initialize the APIC for the IBS interrupts if available */
+/*
+ * check and reserve APIC extended interrupt LVT offset for IBS if
+ * available
+ *
+ * init_ibs() preforms implicitly cpu-local operations, so pin this
+ * thread to its current CPU
+ */
+
 static void init_ibs(void)
 {
+	preempt_disable();
+
 	ibs_caps = get_ibs_caps();
-
 	if (!ibs_caps)
-		return;
+		goto out;
 
-	if (__init_ibs_nmi()) {
+	if (__init_ibs_nmi() < 0)
 		ibs_caps = 0;
-		return;
-	}
+	else
+		printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
 
-	printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n",
-	       (unsigned)ibs_caps);
+out:
+	preempt_enable();
 }
 
 static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
@@ -698,18 +714,29 @@
 	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 --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c
index 182558d..9fadec0 100644
--- a/arch/x86/oprofile/op_model_p4.c
+++ b/arch/x86/oprofile/op_model_p4.c
@@ -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 --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
index d769cda..94b7450 100644
--- a/arch/x86/oprofile/op_model_ppro.c
+++ b/arch/x86/oprofile/op_model_ppro.c
@@ -95,8 +95,8 @@
 		 * 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 @@
 	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 --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index effd96e..6b8759f 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -7,6 +7,7 @@
 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 --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
new file mode 100644
index 0000000..85b68ef
--- /dev/null
+++ b/arch/x86/pci/ce4100.c
@@ -0,0 +1,315 @@
+/*
+ *  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/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,
+};
+
+static int __init ce4100_pci_init(void)
+{
+	init_sim_regs();
+	raw_pci_ops = &ce4100_pci_conf;
+	return 0;
+}
+subsys_initcall(ce4100_pci_init);
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
index 2492d16..a5f7d0d 100644
--- a/arch/x86/pci/pcbios.c
+++ b/arch/x86/pci/pcbios.c
@@ -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 @@
 			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 --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 7bf70b8..021eee9 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -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 --git a/arch/x86/platform/ce4100/Makefile b/arch/x86/platform/ce4100/Makefile
new file mode 100644
index 0000000..91fc929
--- /dev/null
+++ b/arch/x86/platform/ce4100/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_X86_INTEL_CE)	+= ce4100.o
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
new file mode 100644
index 0000000..d2c0d51
--- /dev/null
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -0,0 +1,132 @@
+/*
+ * 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/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;
+}
diff --git a/arch/x86/platform/iris/Makefile b/arch/x86/platform/iris/Makefile
new file mode 100644
index 0000000..db92198
--- /dev/null
+++ b/arch/x86/platform/iris/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_X86_32_IRIS)		+= iris.o
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c
new file mode 100644
index 0000000..1ba7f5e
--- /dev/null
+++ b/arch/x86/platform/iris/iris.c
@@ -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 --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile
index efbbc55..f61ccdd 100644
--- a/arch/x86/platform/mrst/Makefile
+++ b/arch/x86/platform/mrst/Makefile
@@ -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 --git a/arch/x86/kernel/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c
similarity index 100%
rename from arch/x86/kernel/early_printk_mrst.c
rename to arch/x86/platform/mrst/early_printk_mrst.c
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index 79ae681..ea6529e 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -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 @@
 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 @@
 		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 @@
 			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 @@
 		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 @@
 
 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 @@
 		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 @@
 	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 @@
 
 	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 @@
 	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 --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
new file mode 100644
index 0000000..32cd7ed
--- /dev/null
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -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 --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index dd4c281..7785b72 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -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 @@
 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 --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index ba9caa8..df58e9c 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1341,7 +1341,7 @@
 
 	/*
 	 * 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);
@@ -1490,7 +1490,7 @@
 /*
  * 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 @@
 	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 @@
 		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 @@
 				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 @@
 		bcp->congested_reps = congested_reps;
 		bcp->congested_period = congested_period;
 	}
+	return 0;
 }
 
 /*
@@ -1625,7 +1636,10 @@
 	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 --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c
index 3371bd0..6320376 100644
--- a/arch/x86/platform/visws/visws_quirks.c
+++ b/arch/x86/platform/visws/visws_quirks.c
@@ -171,7 +171,7 @@
 	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 --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 44dcad4..aa8c89a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -574,8 +574,8 @@
 
 	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();
 
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h
index 9e565da..4ec8035 100644
--- a/arch/x86/xen/multicalls.h
+++ b/arch/x86/xen/multicalls.h
@@ -22,7 +22,7 @@
 	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 --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 23e061b..cc9b1e1 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -159,8 +159,8 @@
 {
 	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 @@
 	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 --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 5da5e53..067759e 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -135,24 +135,24 @@
 
 	/* 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 --git a/arch/xtensa/include/asm/ioctls.h b/arch/xtensa/include/asm/ioctls.h
index ab18000..ccf1800 100644
--- a/arch/xtensa/include/asm/ioctls.h
+++ b/arch/xtensa/include/asm/ioctls.h
@@ -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 --git a/drivers/Kconfig b/drivers/Kconfig
index a2b902f..3d93b3a 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -111,4 +111,6 @@
 source "drivers/staging/Kconfig"
 
 source "drivers/platform/Kconfig"
+
+source "drivers/clk/Kconfig"
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index f3ebb30..bf15ce7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,3 +115,5 @@
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
 obj-y				+= ieee802154/
+#common clk code
+obj-y				+= clk/
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c
index 2c7def9..4c8dea5 100644
--- a/drivers/acpi/acpica/evgpeinit.c
+++ b/drivers/acpi/acpica/evgpeinit.c
@@ -408,6 +408,9 @@
 		return_ACPI_STATUS(AE_OK);
 	}
 
+	/* Disable the GPE in case it's been enabled already. */
+	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
+
 	/*
 	 * Add the GPE information from above to the gpe_event_info block for
 	 * use during dispatch of this GPE.
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 660a272..0cac7ec 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -577,9 +577,7 @@
 	 * 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 --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 9fb9d5a..95649d3 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -130,8 +130,6 @@
 	unsigned long flags;
 };
 
-static int acpi_battery_update(struct acpi_battery *battery);
-
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -186,9 +184,6 @@
 	int ret = 0;
 	struct acpi_battery *battery = to_acpi_battery(psy);
 
-	if (acpi_battery_update(battery))
-		return -ENODEV;
-
 	if (acpi_battery_present(battery)) {
 		/* run battery update only if it is present */
 		acpi_battery_get_state(battery);
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 5718566..d9926af 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -275,13 +275,23 @@
 int __init acpi_numa_init(void)
 {
 	int ret = 0;
+	int nr_cpu_entries = nr_cpu_ids;
+
+#ifdef CONFIG_X86
+	/*
+	 * 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.
+	 */
+	nr_cpu_entries = MAX_LOCAL_APIC;
+#endif
 
 	/* 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, nr_cpu_entries);
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
-				     acpi_parse_processor_affinity, nr_cpu_ids);
+				     acpi_parse_processor_affinity, nr_cpu_entries);
 		ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index dcb38f8..a765b82 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -746,7 +746,7 @@
 	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 +787,7 @@
 	s64 idle_time_ns;
 	s64 idle_time;
 
-	pr = __get_cpu_var(processors);
+	pr = __this_cpu_read(processors);
 
 	if (unlikely(!pr))
 		return 0;
@@ -864,7 +864,7 @@
 	s64 idle_time;
 
 
-	pr = __get_cpu_var(processors);
+	pr = __this_cpu_read(processors);
 
 	if (unlikely(!pr))
 		return 0;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 2b6c21d..29ef505 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -705,54 +705,85 @@
 }
 
 static acpi_status
-acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
-					     union acpi_object *package)
+acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
+					     struct acpi_device_wakeup *wakeup)
 {
-	int i = 0;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *package = NULL;
 	union acpi_object *element = NULL;
+	acpi_status status;
+	int i = 0;
 
-	if (!device || !package || (package->package.count < 2))
+	if (!wakeup)
 		return AE_BAD_PARAMETER;
 
+	/* _PRW */
+	status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
+		return status;
+	}
+
+	package = (union acpi_object *)buffer.pointer;
+
+	if (!package || (package->package.count < 2)) {
+		status = AE_BAD_DATA;
+		goto out;
+	}
+
 	element = &(package->package.elements[0]);
-	if (!element)
-		return AE_BAD_PARAMETER;
+	if (!element) {
+		status = AE_BAD_DATA;
+		goto out;
+	}
 	if (element->type == ACPI_TYPE_PACKAGE) {
 		if ((element->package.count < 2) ||
 		    (element->package.elements[0].type !=
 		     ACPI_TYPE_LOCAL_REFERENCE)
-		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER))
-			return AE_BAD_DATA;
-		device->wakeup.gpe_device =
+		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) {
+			status = AE_BAD_DATA;
+			goto out;
+		}
+		wakeup->gpe_device =
 		    element->package.elements[0].reference.handle;
-		device->wakeup.gpe_number =
+		wakeup->gpe_number =
 		    (u32) element->package.elements[1].integer.value;
 	} else if (element->type == ACPI_TYPE_INTEGER) {
-		device->wakeup.gpe_number = element->integer.value;
-	} else
-		return AE_BAD_DATA;
+		wakeup->gpe_device = NULL;
+		wakeup->gpe_number = element->integer.value;
+	} else {
+		status = AE_BAD_DATA;
+		goto out;
+	}
 
 	element = &(package->package.elements[1]);
 	if (element->type != ACPI_TYPE_INTEGER) {
-		return AE_BAD_DATA;
+		status = AE_BAD_DATA;
+		goto out;
 	}
-	device->wakeup.sleep_state = element->integer.value;
+	wakeup->sleep_state = element->integer.value;
 
 	if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
-		return AE_NO_MEMORY;
+		status = AE_NO_MEMORY;
+		goto out;
 	}
-	device->wakeup.resources.count = package->package.count - 2;
-	for (i = 0; i < device->wakeup.resources.count; i++) {
+	wakeup->resources.count = package->package.count - 2;
+	for (i = 0; i < wakeup->resources.count; i++) {
 		element = &(package->package.elements[i + 2]);
-		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
-			return AE_BAD_DATA;
+		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
+			status = AE_BAD_DATA;
+			goto out;
+		}
 
-		device->wakeup.resources.handles[i] = element->reference.handle;
+		wakeup->resources.handles[i] = element->reference.handle;
 	}
 
-	acpi_gpe_can_wake(device->wakeup.gpe_device, device->wakeup.gpe_number);
+	acpi_gpe_can_wake(wakeup->gpe_device, wakeup->gpe_number);
 
-	return AE_OK;
+ out:
+	kfree(buffer.pointer);
+
+	return status;
 }
 
 static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
@@ -787,26 +818,15 @@
 static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 {
 	acpi_status status = 0;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *package = NULL;
 	int psw_error;
 
-	/* _PRW */
-	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
-		goto end;
-	}
-
-	package = (union acpi_object *)buffer.pointer;
-	status = acpi_bus_extract_wakeup_device_power_package(device, package);
+	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;
 	}
 
-	kfree(buffer.pointer);
-
 	device->wakeup.flags.valid = 1;
 	device->wakeup.prepare_count = 0;
 	acpi_bus_set_run_wake_flags(device);
@@ -1351,6 +1371,7 @@
 	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;
@@ -1360,8 +1381,10 @@
 		return AE_OK;
 
 	if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
-	    !(sta & ACPI_STA_DEVICE_FUNCTIONING))
+	    !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
+		acpi_bus_extract_wakeup_device_power_package(handle, &wakeup);
 		return AE_CTRL_DEPTH;
+	}
 
 	/*
 	 * We may already have an acpi_device from a previous enumeration.  If
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 2737b97..e7df019 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -147,6 +147,39 @@
 	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 @@
 	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 @@
 			break;
 
 		amba_put_disable_pclk(pcdev);
+		amba_put_disable_vcore(pcdev);
 	} while (0);
 
 	return ret;
@@ -180,6 +218,7 @@
 	int ret = drv->remove(pcdev);
 
 	amba_put_disable_pclk(pcdev);
+	amba_put_disable_vcore(pcdev);
 
 	return ret;
 }
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f23d6d4..0a6a943 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6128,7 +6128,7 @@
 	/* 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 --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 484697f..af6141b 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1320,7 +1320,7 @@
 {
 	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 --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index a6e6c96..628c8fa 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -44,6 +44,8 @@
 module_param_named(msr, use_msr, int, 0644);
 MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
 #else
+#undef rdmsr	/* avoid accidental MSR usage on, e.g. x86-64 */
+#undef wrmsr
 #define rdmsr(x, y, z) do { } while (0)
 #define wrmsr(x, y, z) do { } while (0)
 #define use_msr 0
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index ffe9b65..9f47e86 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -1926,8 +1926,9 @@
   const struct firmware *fw;
   unsigned long start_address;
   const struct ihex_binrec *rec;
+  const char *errmsg = 0;
   int res;
-  
+
   res = request_ihex_firmware(&fw, "atmsar11.fw", &dev->pci_dev->dev);
   if (res) {
     PRINTK (KERN_ERR, "Cannot load microcode data");
@@ -1937,8 +1938,8 @@
   /* 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 @@
     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 @@
     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 --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 3951020..25e4dff 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4352,7 +4352,7 @@
 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 +4422,7 @@
 	 * 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 --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 657873e..d7aa39e 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -547,7 +547,7 @@
 	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 @@
 	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 --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index de65915..64a2146 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -837,7 +837,7 @@
 
 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 --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 43d3395..d4a7776 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -682,6 +682,15 @@
        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
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index ba53ec9..fa0b824 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_HVC_ISERIES)	+= hvc_iseries.o
 obj-$(CONFIG_HVC_RTAS)		+= hvc_rtas.o
 obj-$(CONFIG_HVC_TILE)		+= hvc_tile.o
+obj-$(CONFIG_HVC_DCC)		+= hvc_dcc.o
 obj-$(CONFIG_HVC_BEAT)		+= hvc_beat.o
 obj-$(CONFIG_HVC_DRIVER)	+= hvc_console.o
 obj-$(CONFIG_HVC_IRQ)		+= hvc_irq.o
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 42396df..9252e85 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -38,7 +38,7 @@
 
 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 @@
 	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 @@
 	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 @@
 	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 @@
 {
 	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 @@
 	}
 
 	/* 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 @@
 	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 */
@@ -778,7 +777,7 @@
 		}
 
 		/* 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))
 			return -ENODEV;
 
 		/* Look for any AGP bridge */
diff --git a/drivers/char/hvc_dcc.c b/drivers/char/hvc_dcc.c
new file mode 100644
index 0000000..6470f63
--- /dev/null
+++ b/drivers/char/hvc_dcc.c
@@ -0,0 +1,133 @@
+/* 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/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#include <asm/processor.h>
+
+#include "hvc_console.h"
+
+/* DCC Status Bits */
+#define DCC_STATUS_RX		(1 << 30)
+#define DCC_STATUS_TX		(1 << 29)
+
+static inline u32 __dcc_getstatus(void)
+{
+	u32 __ret;
+
+	asm("mrc p14, 0, %0, c0, c1, 0	@ read comms ctrl reg"
+		: "=r" (__ret) : : "cc");
+
+	return __ret;
+}
+
+
+#if defined(CONFIG_CPU_V7)
+static inline char __dcc_getchar(void)
+{
+	char __c;
+
+	asm("get_wait:	mrc p14, 0, pc, c0, c1, 0                          \n\
+			bne get_wait                                       \n\
+			mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
+		: "=r" (__c) : : "cc");
+
+	return __c;
+}
+#else
+static inline char __dcc_getchar(void)
+{
+	char __c;
+
+	asm("mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
+		: "=r" (__c));
+
+	return __c;
+}
+#endif
+
+#if defined(CONFIG_CPU_V7)
+static inline void __dcc_putchar(char c)
+{
+	asm("put_wait:	mrc p14, 0, pc, c0, c1, 0                 \n\
+			bcs put_wait                              \n\
+			mcr p14, 0, %0, c0, c5, 0                   "
+	: : "r" (c) : "cc");
+}
+#else
+static inline void __dcc_putchar(char c)
+{
+	asm("mcr p14, 0, %0, c0, c5, 0	@ write a char"
+		: /* no output register */
+		: "r" (c));
+}
+#endif
+
+static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		while (__dcc_getstatus() & DCC_STATUS_TX)
+			cpu_relax();
+
+		__dcc_putchar((char)(buf[i] & 0xFF));
+	}
+
+	return count;
+}
+
+static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
+{
+	int i;
+
+	for (i = 0; i < count; ++i) {
+		int c = -1;
+
+		if (__dcc_getstatus() & DCC_STATUS_RX)
+			c = __dcc_getchar();
+		if (c < 0)
+			break;
+		buf[i] = c;
+	}
+
+	return i;
+}
+
+static const struct hv_ops hvc_dcc_get_put_ops = {
+	.get_chars = hvc_dcc_get_chars,
+	.put_chars = hvc_dcc_put_chars,
+};
+
+static int __init hvc_dcc_console_init(void)
+{
+	hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
+	return 0;
+}
+console_initcall(hvc_dcc_console_init);
+
+static int __init hvc_dcc_init(void)
+{
+	hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
+	return 0;
+}
+device_initcall(hvc_dcc_init);
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index a2bc885..67a75a5 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -850,8 +850,8 @@
 	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();
+	cancel_delayed_work_sync(&hp->writer);
+	flush_work_sync(&hp->handshaker);
 
 	/*
 	 * it's also possible that our timeout expired and hvsi_write_worker
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index fcd02ba..c3a0253 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -3224,7 +3224,7 @@
 
 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 --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c
index 99cffda..0aeb5a3 100644
--- a/drivers/char/pcmcia/ipwireless/hardware.c
+++ b/drivers/char/pcmcia/ipwireless/hardware.c
@@ -1729,7 +1729,7 @@
 
 	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 --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c
index 9fe5383..f7daeea 100644
--- a/drivers/char/pcmcia/ipwireless/network.c
+++ b/drivers/char/pcmcia/ipwireless/network.c
@@ -430,7 +430,8 @@
 	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 --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c
index 1a2c2c3..f5eb28b 100644
--- a/drivers/char/pcmcia/ipwireless/tty.c
+++ b/drivers/char/pcmcia/ipwireless/tty.c
@@ -577,7 +577,7 @@
 				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 --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
index 73dcb0e..d3d63be 100644
--- a/drivers/char/ramoops.c
+++ b/drivers/char/ramoops.c
@@ -29,7 +29,6 @@
 #include <linux/ramoops.h>
 
 #define RAMOOPS_KERNMSG_HDR "===="
-#define RAMOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))
 
 #define RECORD_SIZE 4096
 
@@ -65,8 +64,8 @@
 			struct ramoops_context, dump);
 	unsigned long s1_start, s2_start;
 	unsigned long l1_cpy, l2_cpy;
-	int res;
-	char *buf;
+	int res, hdr_size;
+	char *buf, *buf_orig;
 	struct timeval timestamp;
 
 	/* Only dump oopses if dump_oops is set */
@@ -74,6 +73,8 @@
 		return;
 
 	buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
+	buf_orig = buf;
+
 	memset(buf, '\0', RECORD_SIZE);
 	res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
 	buf += res;
@@ -81,8 +82,9 @@
 	res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
 	buf += res;
 
-	l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE));
-	l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy);
+	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);
 
 	s2_start = l2 - l2_cpy;
 	s1_start = l1 - l1_cpy;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 5a1aa64..72a4fcb 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -626,7 +626,7 @@
 	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 --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 86308830..3e4e73a 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1764,7 +1764,7 @@
 
 #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 --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 73f66d0..79e36c8 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1434,7 +1434,7 @@
 	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 --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index a7616d2..c2bca3f 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -2355,7 +2355,7 @@
 	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 --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..0b3af3f 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -986,7 +986,7 @@
 	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 +1038,7 @@
 	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 --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
new file mode 100644
index 0000000..4168c88
--- /dev/null
+++ b/drivers/clk/Kconfig
@@ -0,0 +1,4 @@
+
+config CLKDEV_LOOKUP
+	bool
+	select HAVE_CLK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
new file mode 100644
index 0000000..07613fa
--- /dev/null
+++ b/drivers/clk/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
new file mode 100644
index 0000000..0fc0a79
--- /dev/null
+++ b/drivers/clk/clkdev.c
@@ -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 --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index a7f046b..2b46a7e 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -43,9 +43,10 @@
 
 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 --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index c63a438..1109f68 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -355,6 +355,7 @@
 		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))
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index a507108..386888f 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -49,7 +49,7 @@
  */
 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;
 
@@ -107,6 +107,7 @@
 	if (cpuidle_curr_governor->reflect)
 		cpuidle_curr_governor->reflect(dev);
 	trace_power_end(smp_processor_id());
+	trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
 }
 
 /**
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0602dd..d5a5d4d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -273,50 +273,6 @@
 #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
 
 /**
@@ -1127,8 +1083,74 @@
 	 */
 }
 
-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, "sdma-%s-to%d.bin", cpu_name, to_version);
+	if (!fwname)
+		return -ENOMEM;
+
+	ret = request_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,
+			sdma->script_addrs->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 +1214,6 @@
 
 	__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,14 +1233,9 @@
 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;
@@ -1262,38 +1274,9 @@
 	if (ret)
 		goto err_request_irq;
 
-	fwname = kasprintf(GFP_KERNEL, "sdma-%s-to%d.bin",
-			pdata->cpu_name, pdata->to_version);
-	if (!fwname) {
-		ret = -ENOMEM;
-		goto err_cputype;
-	}
-
-	ret = request_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;
 
@@ -1316,10 +1299,15 @@
 		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;
@@ -1336,10 +1324,6 @@
 		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.
 	 */
@@ -1347,15 +1331,13 @@
 	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);
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 411d5bf..a25f5f6 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -449,7 +449,7 @@
 static void mv_xor_tasklet(unsigned long data)
 {
 	struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
-	__mv_xor_slot_cleanup(chan);
+	mv_xor_slot_cleanup(chan);
 }
 
 static struct mv_xor_desc_slot *
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 85ffd5e..28720d3 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -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 @@
 /* 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 @@
 	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 @@
 	/* 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;
 }
-#endif
+
+static irqreturn_t sh_dmae_err(int irq, void *data)
+{
+	return IRQ_RETVAL(sh_dmae_reset(data));
+}
 
 static void dmae_do_tasklet(unsigned long data)
 {
@@ -876,6 +895,60 @@
 	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 @@
 	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 @@
 	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 @@
 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 @@
 {
 	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 @@
 	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 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 @@
 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 --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 4021275..52e4fb1 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -43,6 +43,7 @@
 	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 --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index f436a2f..fe70a34 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -75,11 +75,11 @@
 	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 --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index eca9ba1..4a5ecc5 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -15,10 +15,14 @@
 
 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 @@
 			   [5 ... 6]	= 1024,
 			   [7 ... 8]	= 2048,
 			   [9 ... 10]	= 4096,
-			   [11]	= 8192,
+			   [11]		= 8192,
 };
 
 /*
@@ -73,7 +77,11 @@
  *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 @@
  * 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 @@
 		 * 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 @@
 	}
 
 	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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 	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.
@@ -893,8 +857,7 @@
 		return;
 	}
 
-	amd64_printk(KERN_INFO, "using %s syndromes.\n",
-		     ((pvt->syn_type == 8) ? "x8" : "x4"));
+	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))
@@ -915,10 +878,10 @@
 /* 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 +928,8 @@
 		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 +944,14 @@
 
 	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 +962,14 @@
 
 	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 +979,7 @@
 	}
 }
 
-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 +992,7 @@
 		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 +1010,16 @@
 {
 	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 +1046,14 @@
 	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 +1083,8 @@
 			 * 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 +1106,7 @@
 	 */
 	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 +1174,7 @@
 	 * 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 +1188,7 @@
 	if (channels > 2)
 		channels = 2;
 
-	debugf0("MCT channel count: %d\n", channels);
+	amd64_info("MCT channel count: %d\n", channels);
 
 	return channels;
 
@@ -1255,31 +1209,6 @@
 	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 +1230,8 @@
 	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 +1248,8 @@
 	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 +1266,7 @@
 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 +1292,7 @@
 			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 +1421,7 @@
 	int cs_found = -EINVAL;
 	int csrow;
 
-	mci = mci_lookup[nid];
+	mci = mcis[nid];
 	if (!mci)
 		return cs_found;
 
@@ -1738,28 +1663,17 @@
 		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 +1683,9 @@
 		}
 	},
 	[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 +1871,7 @@
 					  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 +1889,15 @@
 	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 +1914,8 @@
 
 	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 +1928,8 @@
 	 */
 	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 +1938,8 @@
 
 	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 +1950,8 @@
 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 +1970,7 @@
 
 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 +1994,50 @@
 }
 
 /*
- * 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 +2058,7 @@
 	} 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 +2095,20 @@
 
 	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 +2188,22 @@
  * 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 +2227,7 @@
 		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 +2272,7 @@
 	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 +2298,17 @@
 	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 +2318,14 @@
 
 		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 +2336,92 @@
 	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);
+
+	/* turn on UECCEn and CECCEn bits */
+	s->old_nbctl   = value & mask;
+	s->nbctl_valid = true;
 
 	value |= mask;
-	pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value);
+	pci_write_config_dword(F3, K8_NBCTL, value);
 
-	if (amd64_toggle_ecc_err_reporting(pvt, ON))
-		amd64_printk(KERN_WARNING, "Error enabling ECC reporting over "
-					   "MCGCTL!\n");
+	amd64_read_pci_cfg(F3, K8_NBCFG, &value);
 
-	amd64_read_pci_cfg(pvt->misc_f3_ctl, 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 +2429,28 @@
 	"'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 +2459,23 @@
 
 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 +2491,8 @@
 	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 +2501,94 @@
 }
 
 /*
- * 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,54 +2596,77 @@
 		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);
+err_siblings:
+	free_mc_sibling_devs(pvt);
 
-	amd64_restore_ecc_error_reporting(pvt);
+err_free:
+	kfree(pvt);
 
-	if (boot_cpu_data.x86 > 0xf)
-		amd64_teardown(pvt);
-
-	amd64_free_mc_sibling_devices(pvt);
-
-	kfree(pvt_lookup[pvt->mc_node_id]);
-	pvt_lookup[node_id] = NULL;
-
+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;
 }
 
@@ -2811,6 +2674,9 @@
 {
 	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 +2685,20 @@
 
 	pvt = mci->pvt_info;
 
-	amd64_restore_ecc_error_reporting(pvt);
+	restore_ecc_error_reporting(s, nid, F3);
 
-	if (boot_cpu_data.x86 > 0xf)
-		amd64_teardown(pvt);
-
-	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 +2717,6 @@
 		.subdevice	= PCI_ANY_ID,
 		.class		= 0,
 		.class_mask	= 0,
-		.driver_data	= K8_CPUS
 	},
 	{
 		.vendor		= PCI_VENDOR_ID_AMD,
@@ -2860,16 +2725,6 @@
 		.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 +2732,12 @@
 
 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 +2745,12 @@
 	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 +2764,50 @@
 
 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;
+	if (!atomic_read(&drv_instances))
+		goto err_no_instances;
 
-		err = amd64_init_2nd_stage(pvt_lookup[nb]);
-		if (err)
-			goto err_2nd_stage;
+	setup_pci_device();
+	return 0;
 
-		load_ok = true;
-	}
-
-	if (load_ok) {
-		amd64_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 +2819,12 @@
 
 	pci_unregister_driver(&amd64_pci_driver);
 
+	kfree(ecc_stngs);
+	ecc_stngs = NULL;
+
+	kfree(mcis);
+	mcis = NULL;
+
 	msrs_free(msrs);
 	msrs = NULL;
 }
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 044aee4..613ec72 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -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 @@
 enum amd64_chipset_families {
 	K8_CPUS = 0,
 	F10_CPUS,
-	F11_CPUS,
 };
 
 /* Error injection control structure */
@@ -384,16 +393,13 @@
 };
 
 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 @@
 	/* 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 */
+	/* DCT per-family scrubrate setting */
+	u32 min_scrubrate;
+
+	/* 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;
 
-	/* MC Type Index value: socket F vs Family 10h */
-	u32 mc_type_index;
-
-	/* 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 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 @@
 
 	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 @@
  */
 #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 --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c
index 29f1f7a..688478d 100644
--- a/drivers/edac/amd64_edac_inj.c
+++ b/drivers/edac/amd64_edac_inj.c
@@ -23,9 +23,7 @@
 	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 @@
 	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 @@
 	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 @@
 		/* 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 @@
 		/* 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 --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c
index 1609a19..b9a781c 100644
--- a/drivers/edac/cpc925_edac.c
+++ b/drivers/edac/cpc925_edac.c
@@ -818,9 +818,10 @@
 }
 
 /* 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 @@
 	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 --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 073f5a0..ec302d4 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -983,11 +983,11 @@
 
 	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 @@
 			"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 --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 251440c..ff1eb7b 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -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 {                                                            \
@@ -386,7 +387,7 @@
 	   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 --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 795ea69c..a4e9db2 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -76,6 +76,8 @@
 	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 @@
 };
 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 --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index dce61f7..39d97cf 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -436,56 +436,55 @@
 	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;
+
+	bandwidth = mci->get_sdram_scrub_rate(mci);
+	if (bandwidth < 0) {
+		edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
+		return bandwidth;
 	}
 
-	err = mci->get_sdram_scrub_rate(mci, &bandwidth);
-	if (err) {
-		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);
-	}
+	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 --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index f459a6c..0448da0 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -611,20 +611,17 @@
 
 	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 --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index c018109..f6cf73d 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -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 @@
 	"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 @@
 		}
 	} 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		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_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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 
 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 @@
 
 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 @@
 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("\n");
+	pr_cont("]: 0x%016llx\n", m->status);
+
 
 	switch (m->bank) {
 	case 0:
@@ -576,7 +800,10 @@
 		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 @@
 		amd_decode_fr_mce(m);
 		break;
 
+	case 6:
+		amd_decode_fp_mce(m);
+		break;
+
 	default:
 		break;
 	}
@@ -608,18 +839,21 @@
 
 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 @@
 		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 --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index 35f6e0e3..45dda47 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -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 @@
  * 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 --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index 39faded..733a7e7a 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -88,10 +88,11 @@
 		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 --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3143ac7..082495b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -230,11 +230,11 @@
 	  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
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index bdf3dde..39bfd7a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -24,7 +24,7 @@
 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
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c
deleted file mode 100644
index 7e10c93..0000000
--- a/drivers/gpio/tc35892-gpio.c
+++ /dev/null
@@ -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 --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c
new file mode 100644
index 0000000..180d584
--- /dev/null
+++ b/drivers/gpio/tc3589x-gpio.c
@@ -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(unsigned int irq, unsigned int type)
+{
+	struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+	int offset = 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(unsigned int irq)
+{
+	struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+
+	mutex_lock(&tc3589x_gpio->irq_lock);
+}
+
+static void tc3589x_gpio_irq_sync_unlock(unsigned int irq)
+{
+	struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+	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(unsigned int irq)
+{
+	struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+	int offset = 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(unsigned int irq)
+{
+	struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq);
+	int offset = 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",
+	.bus_lock		= tc3589x_gpio_irq_lock,
+	.bus_sync_unlock	= tc3589x_gpio_irq_sync_unlock,
+	.mask			= tc3589x_gpio_irq_mask,
+	.unmask			= tc3589x_gpio_irq_unmask,
+	.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 --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index af70337..d3e8c54 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -242,7 +242,7 @@
 
 static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
 {
-	return connector_status_unknown;
+	return connector_status_connected;
 }
 
 static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index e680081..cb900dc 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -34,6 +34,7 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "i915_trace.h"
+#include "../../../platform/x86/intel_ips.h"
 #include <linux/pci.h>
 #include <linux/vgaarb.h>
 #include <linux/acpi.h>
@@ -1871,6 +1872,26 @@
 EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
 
 /**
+ * Tells the intel_ips driver that the i915 driver is now loaded, if
+ * IPS got loaded first.
+ *
+ * This awkward dance is so that neither module has to depend on the
+ * other in order for IPS to do the appropriate communication of
+ * GPU turbo limits to i915.
+ */
+static void
+ips_ping_for_i915_load(void)
+{
+	void (*link)(void);
+
+	link = symbol_get(ips_link_to_i915_driver);
+	if (link) {
+		link();
+		symbol_put(ips_link_to_i915_driver);
+	}
+}
+
+/**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
  * @flags: startup flags
@@ -2075,6 +2096,8 @@
 	dev_priv->mchdev_lock = &mchdev_lock;
 	spin_unlock(&mchdev_lock);
 
+	ips_ping_for_i915_load();
+
 	return 0;
 
 out_workqueue_free:
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 878fc76..cb8f434 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2471,6 +2471,9 @@
 # define MARIUNIT_CLOCK_GATE_DISABLE		(1 << 18)
 # define SVSMUNIT_CLOCK_GATE_DISABLE		(1 << 1)
 
+#define PCH_3DCGDIS1		0x46024
+# define VFMUNIT_CLOCK_GATE_DISABLE		(1 << 11)
+
 #define FDI_PLL_FREQ_CTL        0x46030
 #define  FDI_PLL_FREQ_CHANGE_REQUEST    (1<<24)
 #define  FDI_PLL_FREQ_LOCK_LIMIT_MASK   0xfff00
@@ -2588,6 +2591,13 @@
 #define ILK_DISPLAY_CHICKEN2	0x42004
 #define  ILK_DPARB_GATE	(1<<22)
 #define  ILK_VSDPFD_FULL	(1<<21)
+#define ILK_DISPLAY_CHICKEN_FUSES	0x42014
+#define  ILK_INTERNAL_GRAPHICS_DISABLE	(1<<31)
+#define  ILK_INTERNAL_DISPLAY_DISABLE	(1<<30)
+#define  ILK_DISPLAY_DEBUG_DISABLE	(1<<29)
+#define  ILK_HDCP_DISABLE		(1<<25)
+#define  ILK_eDP_A_DISABLE		(1<<24)
+#define  ILK_DESKTOP			(1<<23)
 #define ILK_DSPCLK_GATE		0x42020
 #define  ILK_DPARB_CLK_GATE	(1<<5)
 /* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 2b20786..b0b1200 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -270,7 +270,7 @@
 					general->ssc_freq ? 66 : 48;
 			else if (IS_GEN5(dev) || IS_GEN6(dev))
 				dev_priv->lvds_ssc_freq =
-					general->ssc_freq ? 120 : 100;
+					general->ssc_freq ? 100 : 120;
 			else
 				dev_priv->lvds_ssc_freq =
 					general->ssc_freq ? 100 : 96;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d9b7092..fca5232 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5379,6 +5379,23 @@
 	return index_mask;
 }
 
+static bool has_edp_a(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!IS_MOBILE(dev))
+		return false;
+
+	if ((I915_READ(DP_A) & DP_DETECTED) == 0)
+		return false;
+
+	if (IS_GEN5(dev) &&
+	    (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
+		return false;
+
+	return true;
+}
+
 static void intel_setup_outputs(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5396,7 +5413,7 @@
 	if (HAS_PCH_SPLIT(dev)) {
 		dpd_is_edp = intel_dpd_is_edp(dev);
 
-		if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
+		if (has_edp_a(dev))
 			intel_dp_init(dev, DP_A);
 
 		if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
@@ -5825,6 +5842,8 @@
 			I915_WRITE(PCH_3DCGDIS0,
 				   MARIUNIT_CLOCK_GATE_DISABLE |
 				   SVSMUNIT_CLOCK_GATE_DISABLE);
+			I915_WRITE(PCH_3DCGDIS1,
+				   VFMUNIT_CLOCK_GATE_DISABLE);
 		}
 
 		I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 27e63ab..6bc42fa 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2040,13 +2040,14 @@
 					   SDVO_COLORIMETRY_RGB256);
 		connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
 
-		intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
 		intel_sdvo->is_hdmi = true;
 	}
 	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
 				       (1 << INTEL_ANALOG_CLONE_BIT));
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+	if (intel_sdvo->is_hdmi)
+		intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
 
 	return true;
 }
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 148a322..934a96a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1472,8 +1472,7 @@
 	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))
 		;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 41d9a5b..fe096a7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -659,7 +659,7 @@
 	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 --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 3052e29..401acec 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -154,7 +154,8 @@
 	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"
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
index 02d8cd3..4fb7c75 100644
--- a/drivers/hid/hid-3m-pct.c
+++ b/drivers/hid/hid-3m-pct.c
@@ -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 @@
 #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 @@
 
 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 @@
 					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 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 @@
 			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 @@
 			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);
 }
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 88cb04e..3f9673d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1300,6 +1300,9 @@
 	{ 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_EZKEY, USB_DEVICE_ID_BTC_8193) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
@@ -1604,6 +1607,7 @@
 	{ 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) },
diff --git a/drivers/hid/hid-egalax.c b/drivers/hid/hid-egalax.c
index 5a1b52e..8fbff23 100644
--- a/drivers/hid/hid-egalax.c
+++ b/drivers/hid/hid-egalax.c
@@ -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 @@
 
 #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 @@
 		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 @@
 		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 @@
 		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 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 @@
 	 * 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 @@
 		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:
@@ -261,6 +238,12 @@
 			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 --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 3341baa..8e11af8 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -196,10 +196,15 @@
 #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
 
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index 05248f2..92b42db 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -234,7 +234,6 @@
 	attr->index = channel;
 	attr->dev_attr.attr.name  = attrs->in_name;
 	attr->dev_attr.attr.mode  = S_IRUGO;
-	attr->dev_attr.attr.owner = THIS_MODULE;
 	attr->dev_attr.show = s3c_hwmon_ch_show;
 
 	ret =  device_create_file(dev, &attr->dev_attr);
@@ -252,7 +251,6 @@
 		attr->index = channel;
 		attr->dev_attr.attr.name  = attrs->label_name;
 		attr->dev_attr.attr.mode  = S_IRUGO;
-		attr->dev_attr.attr.owner = THIS_MODULE;
 		attr->dev_attr.show = s3c_hwmon_label_show;
 
 		ret = device_create_file(dev, &attr->dev_attr);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index b33c785..9d09083 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -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 @@
 	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 @@
 				(i2c_dev->regs[reg] << i2c_dev->reg_shift));
 }
 
-static int __init omap_i2c_get_clocks(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;
-	}
-
-	return 0;
-}
-
-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;
-}
-
 static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 {
+	struct platform_device *pdev;
+	struct omap_i2c_bus_platform_data *pdata;
+
 	WARN_ON(!dev->idle);
 
-	clk_enable(dev->iclk);
-	clk_enable(dev->fclk);
+	pdev = to_platform_device(dev->dev);
+	pdata = pdev->dev.platform_data;
+
+	pm_runtime_get_sync(&pdev->dev);
+
 	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_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 @@
 		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 @@
 	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 */
@@ -414,7 +392,9 @@
 		 * 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 +423,9 @@
 			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;
@@ -1048,14 +1030,12 @@
 	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 +1107,6 @@
 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 +1128,6 @@
 	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);
@@ -1162,7 +1139,7 @@
 	.probe		= omap_i2c_probe,
 	.remove		= omap_i2c_remove,
 	.driver		= {
-		.name	= "i2c_omap",
+		.name	= "omap_i2c",
 		.owner	= THIS_MODULE,
 	},
 };
@@ -1184,4 +1161,4 @@
 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 --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index c131d58..56ac09d 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -220,9 +220,8 @@
 	kt_before = ktime_get_real();
 
 	stop_critical_timings();
-#ifndef MODULE
 	trace_power_start(POWER_CSTATE, (eax >> 4) + 1, cpu);
-#endif
+	trace_cpu_idle((eax >> 4) + 1, cpu);
 	if (!need_resched()) {
 
 		__monitor((void *)&current_thread_info()->flags, 0, 0);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 8c8afc7..31ae1b1 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -277,18 +277,14 @@
 		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 --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index f99bddc..df7fa25 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -453,17 +453,14 @@
 		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 --git a/drivers/input/Makefile b/drivers/input/Makefile
index 7ad212d..09614ce 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -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 --git a/drivers/input/apm-power.c b/drivers/input/apm-power.c
index 7d61a96..e90ee3d 100644
--- a/drivers/input/apm-power.c
+++ b/drivers/input/apm-power.c
@@ -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 @@
 	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 @@
 
 	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 --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index f7c5c14..cd4e667 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -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 @@
 
 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 @@
 	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 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 --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 68f09a8..c8471a2 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -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 @@
 	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 @@
 #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 @@
 			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 --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 03078c0..3367f76 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -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 @@
 
 	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 @@
 	    (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 @@
 	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 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 --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index 1d881c9..117a59a 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -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 @@
 	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 @@
 	}
 
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 46239e4..23cf8fc 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -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 @@
 	}
 
 	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 @@
 
 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;
-		}
+	if (!list_empty(&gameport_event_list)) {
+		event = list_first_entry(&gameport_event_list,
+					 struct gameport_event, node);
+		list_del_init(&event->node);
 	}
 
-	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);
-	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 @@
 	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 @@
 	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);
+	schedule_work(&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 @@
 	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 @@
 		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 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 --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
new file mode 100644
index 0000000..c48c81f
--- /dev/null
+++ b/drivers/input/input-mt.c
@@ -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 --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index 10c9b0a..0559e30 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -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 @@
 	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 --git a/drivers/input/input.c b/drivers/input/input.c
index db409d6..7985114 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -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>
@@ -958,10 +960,8 @@
 
 	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 +1109,8 @@
 		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 +1334,26 @@
 }
 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 +1487,7 @@
 {
 	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 +1553,8 @@
 	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 +1744,6 @@
 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 +1792,8 @@
 		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 +1875,9 @@
 		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 +2159,7 @@
 
 	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 +2169,7 @@
 
 	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 --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 9d424ceb..3182c9c 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -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 @@
 			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 --git a/drivers/input/joystick/iforce/Makefile b/drivers/input/joystick/iforce/Makefile
index 74daff4..bc5bda2 100644
--- a/drivers/input/joystick/iforce/Makefile
+++ b/drivers/input/joystick/iforce/Makefile
@@ -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 --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f9fb7fa..56abf3d 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -543,21 +543,25 @@
 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 @@
 
 	if (xpad_led) {
 		led_classdev_unregister(&xpad_led->led_cdev);
-		kfree(xpad_led->name);
+		kfree(xpad_led);
 	}
 }
 #else
@@ -756,8 +760,9 @@
 {
 	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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 		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 @@
 {
 	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 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 --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 3a87f3b..f829998 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -196,20 +196,22 @@
 	  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"
@@ -459,6 +461,25 @@
 	  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 --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 622de73..8933e9c 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -38,9 +38,11 @@
 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_TNETV107X)	+= tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index a72e61d..0e2a19c 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -65,7 +65,6 @@
 
 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 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 @@
 			       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 @@
 	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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 			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 --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
new file mode 100644
index 0000000..bee03d6
--- /dev/null
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -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 --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
new file mode 100644
index 0000000..dbbe761
--- /dev/null
+++ b/drivers/input/keyboard/tc3589x-keypad.c
@@ -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 --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index 00137be..800fbcc 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -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 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 @@
 {
 	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 @@
 {
 	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 @@
 
 	chip->client = client;
 	chip->input = input;
+	chip->io_size = id->driver_data;
 	chip->pinmask = pdata->pinmask;
 	chip->use_polling = pdata->use_polling;
 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index b99b8cb..b0c6772 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -294,24 +294,6 @@
 	  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 @@
 	  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 --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 1fe1f6c..9b47971 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -18,6 +18,8 @@
 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_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 --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c
new file mode 100644
index 0000000..1633b63
--- /dev/null
+++ b/drivers/input/misc/cma3000_d0x.c
@@ -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 --git a/drivers/input/misc/cma3000_d0x.h b/drivers/input/misc/cma3000_d0x.h
new file mode 100644
index 0000000..2304ce3
--- /dev/null
+++ b/drivers/input/misc/cma3000_d0x.h
@@ -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 --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
new file mode 100644
index 0000000..d100cc5
--- /dev/null
+++ b/drivers/input/misc/cma3000_d0x_i2c.c
@@ -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 --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index d1583ae..08be1a3 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -169,19 +169,29 @@
 }
 
 #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 @@
 	.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 --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index b941078..82542a1 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -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 @@
 			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 @@
 			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 --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c
deleted file mode 100644
index 64f1de7..0000000
--- a/drivers/input/misc/winbond-cir.c
+++ /dev/null
@@ -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 --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index 1d2205b..95577c1 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -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 @@
 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 @@
 	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 @@
  * 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 @@
 {
 	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 @@
 	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);
+	err = hgpk_reset_device(psmouse, true);
+	if (err)
+		return err;
 
-	/* 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);
-
-	/* 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 @@
 
 	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 @@
 		 * 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 @@
 			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_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 @@
 		 * 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 @@
 __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 @@
 
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 
 	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 --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h
index d61cfd3..311c0e8 100644
--- a/drivers/input/mouse/hgpk.h
+++ b/drivers/input/mouse/hgpk.h
@@ -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 @@
 	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 @@
 	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 --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index cd9d0c9..3f74bae 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -1711,6 +1711,7 @@
 
 	lifebook_module_init();
 	synaptics_module_init();
+	hgpk_module_init();
 
 	kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
 	if (!kpsmoused_wq) {
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 2e300a4..da392c2 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -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 @@
 	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 @@
  *	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 @@
 			 ((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 @@
 		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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 {
 	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 @@
 			     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 @@
 	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);
@@ -702,6 +777,11 @@
 		return -1;
 	}
 
+	if (synaptics_set_advanced_gesture_mode(psmouse)) {
+		printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -744,15 +824,45 @@
 #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 +879,11 @@
 		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 +917,8 @@
 
 	/*
 	 * 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 --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 0aefaa8..25e5d04 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -54,6 +54,7 @@
 #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 +114,8 @@
 	int scroll;
 
 	struct serio *pt_port;			/* Pass-through serio port */
+
+	struct synaptics_hw_state mt;		/* current gesture packet */
 };
 
 void synaptics_module_init(void);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 2a00ddf..7630273 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -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 @@
 			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 @@
 #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 --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 6256233..bcb1fde 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -214,7 +214,6 @@
 	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.
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index 8f1770e..ebe9553 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -172,6 +172,5 @@
 	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 --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 4a30846..448c772 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -191,6 +191,9 @@
 
 	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 +240,6 @@
 	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 --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index e5624d8..bfd3865 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -932,6 +932,11 @@
 		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 --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index 7d2b820..d50f067 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -305,6 +305,7 @@
 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 @@
 	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 --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index a5475b5..5ae0fc4 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -553,6 +553,13 @@
  */
 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 +759,7 @@
 #endif
 
 	if (i8042_nopnp) {
-		printk(KERN_INFO "i8042: PNP detection disabled\n");
+		pr_info("PNP detection disabled\n");
 		return 0;
 	}
 
@@ -769,7 +776,7 @@
 #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 +788,7 @@
 		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 +805,7 @@
 	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 +814,27 @@
 	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;
 		}
 	}
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 18db5a8..c04ff00 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -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>
@@ -225,8 +227,8 @@
 		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 +255,32 @@
 	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 +311,7 @@
 	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 +357,14 @@
 
 	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 +455,8 @@
 	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 +469,8 @@
 
 		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
@@ -512,7 +513,7 @@
 	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 +541,7 @@
 	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 +560,7 @@
 	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 +642,7 @@
 	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 +652,7 @@
 	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 +677,8 @@
 	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 +771,8 @@
  */
 
 	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 +820,7 @@
  * 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 +846,7 @@
 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 +865,15 @@
 	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 +884,7 @@
 	 * 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 +909,7 @@
 
 	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 +917,7 @@
 			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 +941,7 @@
 		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 +968,7 @@
  */
 
 	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 +998,7 @@
 	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 +1019,7 @@
  */
 
 	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 +1043,14 @@
 	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 +1066,7 @@
 
 	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 +1101,10 @@
 	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 +1117,7 @@
 
 	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 --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index cbc1beb..ac1d759 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -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 --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c
index 6bce22e..15aa81c 100644
--- a/drivers/input/serio/ps2mult.c
+++ b/drivers/input/serio/ps2mult.c
@@ -207,7 +207,7 @@
 err_out:
 	while (--i >= 0)
 		kfree(psm->ports[i].serio);
-	kfree(serio);
+	kfree(psm);
 	return error;
 }
 
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 405bf21..db5b0bc 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -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 @@
 
 /*
  * 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,8 +164,95 @@
 
 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 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_free_event(struct serio_event *event)
+{
+	module_put(event->owner);
+	kfree(event);
+}
+
+static void serio_remove_duplicate_events(struct serio_event *event)
+{
+	struct serio_event *e, *next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	list_for_each_entry_safe(e, next, &serio_event_list, node) {
+		if (event->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)
+				break;
+
+			list_del_init(&e->node);
+			serio_free_event(e);
+		}
+	}
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+}
+
+static void serio_handle_event(struct work_struct *work)
+{
+	struct serio_event *event;
+
+	mutex_lock(&serio_mutex);
+
+	while ((event = serio_get_event())) {
+
+		switch (event->type) {
+
+		case SERIO_REGISTER_PORT:
+			serio_add_port(event->object);
+			break;
+
+		case SERIO_RECONNECT_PORT:
+			serio_reconnect_port(event->object);
+			break;
+
+		case SERIO_RESCAN_PORT:
+			serio_disconnect_port(event->object);
+			serio_find_driver(event->object);
+			break;
+
+		case SERIO_RECONNECT_SUBTREE:
+			serio_reconnect_subtree(event->object);
+			break;
+
+		case SERIO_ATTACH_DRIVER:
+			serio_attach_driver(event->object);
+			break;
+		}
+
+		serio_remove_duplicate_events(event);
+		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)
@@ -212,101 +298,13 @@
 	event->owner = owner;
 
 	list_add_tail(&event->node, &serio_event_list);
-	wake_up(&serio_wait);
+	schedule_work(&serio_event_work);
 
 out:
 	spin_unlock_irqrestore(&serio_event_lock, flags);
 	return retval;
 }
 
-static void serio_free_event(struct serio_event *event)
-{
-	module_put(event->owner);
-	kfree(event);
-}
-
-static void serio_remove_duplicate_events(struct serio_event *event)
-{
-	struct serio_event *e, *next;
-	unsigned long flags;
-
-	spin_lock_irqsave(&serio_event_lock, flags);
-
-	list_for_each_entry_safe(e, next, &serio_event_list, node) {
-		if (event->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)
-				break;
-
-			list_del_init(&e->node);
-			serio_free_event(e);
-		}
-	}
-
-	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)
-{
-	struct serio_event *event;
-
-	mutex_lock(&serio_mutex);
-
-	while ((event = serio_get_event())) {
-
-		switch (event->type) {
-
-		case SERIO_REGISTER_PORT:
-			serio_add_port(event->object);
-			break;
-
-		case SERIO_RECONNECT_PORT:
-			serio_reconnect_port(event->object);
-			break;
-
-		case SERIO_RESCAN_PORT:
-			serio_disconnect_port(event->object);
-			serio_find_driver(event->object);
-			break;
-
-		case SERIO_RECONNECT_SUBTREE:
-			serio_reconnect_subtree(event->object);
-			break;
-
-		case SERIO_ATTACH_DRIVER:
-			serio_attach_driver(event->object);
-			break;
-		}
-
-		serio_remove_duplicate_events(event);
-		serio_free_event(event);
-	}
-
-	mutex_unlock(&serio_mutex);
-}
-
 /*
  * Remove all events that have been submitted for a given
  * object, be it serio port or driver.
@@ -356,18 +354,6 @@
 	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
  */
@@ -1040,21 +1026,18 @@
 		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 --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index de5adb1..23317bd 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -103,6 +103,7 @@
 MODULE_LICENSE(DRIVER_LICENSE);
 
 #define USB_VENDOR_ID_WACOM	0x056a
+#define USB_VENDOR_ID_LENOVO	0x17ef
 
 struct wacom {
 	dma_addr_t data_dma;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 435b0af..5187829 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -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 @@
 	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 @@
 			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);
@@ -1272,7 +1262,7 @@
 			__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 +1272,6 @@
 			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);
 		} else if (features->device_type == BTN_TOOL_PEN) {
 			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
 			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
@@ -1444,11 +1432,17 @@
 	{ "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) },
@@ -1525,6 +1519,7 @@
 	{ USB_DEVICE_WACOM(0xE2) },
 	{ USB_DEVICE_WACOM(0xE3) },
 	{ USB_DEVICE_WACOM(0x47) },
+	{ USB_DEVICE_LENOVO(0x6004) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, wacom_ids);
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 00ca015..b1310ec 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -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 @@
 	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 --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 06ea8da..07ac77d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -659,6 +659,28 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called pcap_ts.
 
+config TOUCHSCREEN_ST1232
+	tristate "Sitronix ST1232 touchscreen controllers"
+	depends on I2C
+	help
+	  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 st1232_ts.
+
+config TOUCHSCREEN_STMPE
+	tristate "STMicroelectronics STMPE touchscreens"
+	depends on MFD_STMPE
+	help
+	  Say Y here if you want support for STMicroelectronics
+	  STMPE touchscreen controllers.
+
+	  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
@@ -671,14 +693,4 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called tps6507x_ts.
 
-config TOUCHSCREEN_STMPE
-	tristate "STMicroelectronics STMPE touchscreens"
-	depends on MFD_STMPE
-	help
-	  Say Y here if you want support for STMicroelectronics
-	  STMPE touchscreen controllers.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called stmpe-ts.
-
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 7cc1b4f..718bcc8 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -39,6 +39,7 @@
 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 --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
index 2ca9e5d..f7fa9ef 100644
--- a/drivers/input/touchscreen/bu21013_ts.c
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -365,7 +365,7 @@
 	}
 
 	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;
diff --git a/drivers/input/touchscreen/qt602240_ts.c b/drivers/input/touchscreen/qt602240_ts.c
index 66b26ad..4dcb0e8 100644
--- a/drivers/input/touchscreen/qt602240_ts.c
+++ b/drivers/input/touchscreen/qt602240_ts.c
@@ -969,7 +969,7 @@
 		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 @@
 }
 
 #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 @@
 	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 @@
 
 	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 @@
 	.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 --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
new file mode 100644
index 0000000..4ab3713
--- /dev/null
+++ b/drivers/input/touchscreen/st1232.c
@@ -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 --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 9ae4c7b..8ed53ad 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -15,10 +15,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 +38,7 @@
 
 #define W8001_QUERY_PACKET	0x20
 
+#define W8001_CMD_STOP		'0'
 #define W8001_CMD_START		'1'
 #define W8001_CMD_QUERY		'*'
 #define W8001_CMD_TOUCHQUERY	'%'
@@ -48,8 +50,6 @@
 #define W8001_PKTLEN_TPCCTL	11	/* control packet */
 #define W8001_PKTLEN_TOUCH2FG	13
 
-#define MAX_TRACKING_ID		0xFF	/* arbitrarily chosen */
-
 struct w8001_coord {
 	u8 rdy;
 	u8 tsw;
@@ -87,7 +87,6 @@
 	char phys[32];
 	int type;
 	unsigned int pktlen;
-	int trkid[2];
 };
 
 static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -116,28 +115,23 @@
 
 static void parse_touch(struct w8001 *w8001)
 {
-	static int trkid;
 	struct input_dev *dev = w8001->dev;
 	unsigned char *data = w8001->data;
 	int i;
 
 	for (i = 0; i < 2; i++) {
-		input_mt_slot(dev, i);
+		bool touch = data[0] & (1 << i);
 
-		if (data[0] & (1 << i)) {
+		input_mt_slot(dev, i);
+		input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch);
+		if (touch) {
 			int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
 			int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
 			/* data[5,6] and [11,12] is finger capacity */
 
 			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;
 		}
-		input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
 	}
 
 	input_sync(dev);
@@ -287,24 +281,46 @@
 	struct w8001_coord coord;
 	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);
-
-	error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
+	/* penabled? */
+	error = w8001_command(w8001, W8001_CMD_QUERY, true);
 	if (!error) {
+		__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_data(w8001->response, &coord);
+
+		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);
+		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);
+		}
+	}
+
+	/* 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]) {
 		struct w8001_touch_query touch;
 
 		parse_touchquery(w8001->response, &touch);
 
+		input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0);
+		input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0);
+		__set_bit(BTN_TOOL_FINGER, dev->keybit);
+
 		switch (touch.sensor_id) {
 		case 0:
 		case 2:
@@ -318,15 +334,13 @@
 		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);
 			break;
 		}
 	}
@@ -372,7 +386,6 @@
 	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);
 
@@ -385,11 +398,7 @@
 	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);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
 
 	serio_set_drvdata(serio, w8001);
 	err = serio_open(serio, drv);
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
index e0c024d..7f85a86 100644
--- a/drivers/input/xen-kbdfront.c
+++ b/drivers/input/xen-kbdfront.c
@@ -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 @@
 				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 @@
 			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 --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index e54e79d..92607ed 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -2297,6 +2297,7 @@
 
 	errcode = capi20_get_profile(0, &profile);
 	if (errcode != CAPI_NOERROR) {
+		unregister_capictr_notifier(&capictr_nb);
 		capi20_release(&global.ap);
 		return -EIO;
 	}
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 3acf94c..2b33b26 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -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 @@
 	event->type = event_type;
 	event->controller = controller;
 
-	schedule_work(&event->work);
+	queue_work(kcapi_wq, &event->work);
 	return 0;
 }
 
@@ -408,7 +409,7 @@
 		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 @@
 
 	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 @@
 {
 	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 --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 307bd6e..199f374 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -110,7 +110,7 @@
 	}
 	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_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 --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index 5b59796..bd526f6 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -1269,6 +1269,8 @@
 	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 --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 5aab32c..a045232 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -276,7 +276,7 @@
 	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 --git a/drivers/macintosh/ams/ams-core.c b/drivers/macintosh/ams/ams-core.c
index 2ad62c3..399beb16 100644
--- a/drivers/macintosh/ams/ams-core.c
+++ b/drivers/macintosh/ams/ams-core.c
@@ -226,7 +226,7 @@
 	 * 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 --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 067f996..6a82388 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -23,6 +23,8 @@
 
 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 @@
 	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 @@
 	if (rc)
 		*valp = old_val;
 
+	mutex_unlock(&mac_hid_emumouse_mutex);
+
 	return rc;
 }
 
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index 53cce3a..39f660b 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -285,8 +285,8 @@
 
 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 --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
deleted file mode 100644
index aa4163e..0000000
--- a/drivers/media/IR/Kconfig
+++ /dev/null
@@ -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 --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
deleted file mode 100644
index f9574ad..0000000
--- a/drivers/media/IR/Makefile
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c
deleted file mode 100644
index 7637bab..0000000
--- a/drivers/media/IR/ene_ir.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ene_ir.h b/drivers/media/IR/ene_ir.h
deleted file mode 100644
index f587066..0000000
--- a/drivers/media/IR/ene_ir.h
+++ /dev/null
@@ -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 --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
deleted file mode 100644
index bc11806..0000000
--- a/drivers/media/IR/imon.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
deleted file mode 100644
index 81c936b..0000000
--- a/drivers/media/IR/ir-core-priv.h
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c
deleted file mode 100644
index db591e4..0000000
--- a/drivers/media/IR/ir-functions.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c
deleted file mode 100644
index 63dca6e..0000000
--- a/drivers/media/IR/ir-jvc-decoder.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
deleted file mode 100644
index f60107c..0000000
--- a/drivers/media/IR/ir-keytable.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
deleted file mode 100644
index 9fc0db9..0000000
--- a/drivers/media/IR/ir-lirc-codec.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
deleted file mode 100644
index 70993f7..0000000
--- a/drivers/media/IR/ir-nec-decoder.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
deleted file mode 100644
index a06a07e..0000000
--- a/drivers/media/IR/ir-raw-event.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c
deleted file mode 100644
index 572ed4c..0000000
--- a/drivers/media/IR/ir-rc5-decoder.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-rc5-sz-decoder.c b/drivers/media/IR/ir-rc5-sz-decoder.c
deleted file mode 100644
index 7c41350..0000000
--- a/drivers/media/IR/ir-rc5-sz-decoder.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
deleted file mode 100644
index d25da91..0000000
--- a/drivers/media/IR/ir-rc6-decoder.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c
deleted file mode 100644
index 2d15730..0000000
--- a/drivers/media/IR/ir-sony-decoder.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
deleted file mode 100644
index 38423a8..0000000
--- a/drivers/media/IR/ir-sysfs.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/Kconfig b/drivers/media/IR/keymaps/Kconfig
deleted file mode 100644
index 14b22f5..0000000
--- a/drivers/media/IR/keymaps/Kconfig
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile
deleted file mode 100644
index 3194d39..0000000
--- a/drivers/media/IR/keymaps/Makefile
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c
deleted file mode 100644
index b172831..0000000
--- a/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-alink-dtu-m.c b/drivers/media/IR/keymaps/rc-alink-dtu-m.c
deleted file mode 100644
index ddfee7f..0000000
--- a/drivers/media/IR/keymaps/rc-alink-dtu-m.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-anysee.c b/drivers/media/IR/keymaps/rc-anysee.c
deleted file mode 100644
index 30d7049..0000000
--- a/drivers/media/IR/keymaps/rc-anysee.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-apac-viewcomp.c b/drivers/media/IR/keymaps/rc-apac-viewcomp.c
deleted file mode 100644
index 0ef2b56..0000000
--- a/drivers/media/IR/keymaps/rc-apac-viewcomp.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-asus-pc39.c b/drivers/media/IR/keymaps/rc-asus-pc39.c
deleted file mode 100644
index 2996e0a..0000000
--- a/drivers/media/IR/keymaps/rc-asus-pc39.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c
deleted file mode 100644
index 8edfd29..0000000
--- a/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avermedia-a16d.c b/drivers/media/IR/keymaps/rc-avermedia-a16d.c
deleted file mode 100644
index 12f0435..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia-a16d.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avermedia-cardbus.c b/drivers/media/IR/keymaps/rc-avermedia-cardbus.c
deleted file mode 100644
index 2a945b0..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia-cardbus.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avermedia-dvbt.c b/drivers/media/IR/keymaps/rc-avermedia-dvbt.c
deleted file mode 100644
index 39dde62..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia-dvbt.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avermedia-m135a.c b/drivers/media/IR/keymaps/rc-avermedia-m135a.c
deleted file mode 100644
index e4471fb..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia-m135a.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c
deleted file mode 100644
index cf8d457..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c b/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c
deleted file mode 100644
index 9ee6090..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avermedia.c b/drivers/media/IR/keymaps/rc-avermedia.c
deleted file mode 100644
index 21effd5..0000000
--- a/drivers/media/IR/keymaps/rc-avermedia.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-avertv-303.c b/drivers/media/IR/keymaps/rc-avertv-303.c
deleted file mode 100644
index 971c59d..0000000
--- a/drivers/media/IR/keymaps/rc-avertv-303.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c
deleted file mode 100644
index e087614..0000000
--- a/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-behold-columbus.c b/drivers/media/IR/keymaps/rc-behold-columbus.c
deleted file mode 100644
index 9f56c98..0000000
--- a/drivers/media/IR/keymaps/rc-behold-columbus.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-behold.c b/drivers/media/IR/keymaps/rc-behold.c
deleted file mode 100644
index abc140b..0000000
--- a/drivers/media/IR/keymaps/rc-behold.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-budget-ci-old.c b/drivers/media/IR/keymaps/rc-budget-ci-old.c
deleted file mode 100644
index 64c2ac9..0000000
--- a/drivers/media/IR/keymaps/rc-budget-ci-old.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-cinergy-1400.c b/drivers/media/IR/keymaps/rc-cinergy-1400.c
deleted file mode 100644
index 074f2c2..0000000
--- a/drivers/media/IR/keymaps/rc-cinergy-1400.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-cinergy.c b/drivers/media/IR/keymaps/rc-cinergy.c
deleted file mode 100644
index cf84c3d..0000000
--- a/drivers/media/IR/keymaps/rc-cinergy.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-dib0700-nec.c b/drivers/media/IR/keymaps/rc-dib0700-nec.c
deleted file mode 100644
index ae18320..0000000
--- a/drivers/media/IR/keymaps/rc-dib0700-nec.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-dib0700-rc5.c b/drivers/media/IR/keymaps/rc-dib0700-rc5.c
deleted file mode 100644
index 4a4797c..0000000
--- a/drivers/media/IR/keymaps/rc-dib0700-rc5.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c
deleted file mode 100644
index 63e469e..0000000
--- a/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-digittrade.c b/drivers/media/IR/keymaps/rc-digittrade.c
deleted file mode 100644
index 5dece78..0000000
--- a/drivers/media/IR/keymaps/rc-digittrade.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-dm1105-nec.c b/drivers/media/IR/keymaps/rc-dm1105-nec.c
deleted file mode 100644
index 90684d0..0000000
--- a/drivers/media/IR/keymaps/rc-dm1105-nec.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c
deleted file mode 100644
index 8a4027a..0000000
--- a/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c
deleted file mode 100644
index 6f4d607..0000000
--- a/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-em-terratec.c b/drivers/media/IR/keymaps/rc-em-terratec.c
deleted file mode 100644
index 3130c9c..0000000
--- a/drivers/media/IR/keymaps/rc-em-terratec.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c b/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c
deleted file mode 100644
index 4b81696..0000000
--- a/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-encore-enltv.c b/drivers/media/IR/keymaps/rc-encore-enltv.c
deleted file mode 100644
index 9fabffd..0000000
--- a/drivers/media/IR/keymaps/rc-encore-enltv.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-encore-enltv2.c b/drivers/media/IR/keymaps/rc-encore-enltv2.c
deleted file mode 100644
index efefd51..0000000
--- a/drivers/media/IR/keymaps/rc-encore-enltv2.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-evga-indtube.c b/drivers/media/IR/keymaps/rc-evga-indtube.c
deleted file mode 100644
index 3f3fb13..0000000
--- a/drivers/media/IR/keymaps/rc-evga-indtube.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-eztv.c b/drivers/media/IR/keymaps/rc-eztv.c
deleted file mode 100644
index 660907a..0000000
--- a/drivers/media/IR/keymaps/rc-eztv.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-flydvb.c b/drivers/media/IR/keymaps/rc-flydvb.c
deleted file mode 100644
index a173c81..0000000
--- a/drivers/media/IR/keymaps/rc-flydvb.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-flyvideo.c b/drivers/media/IR/keymaps/rc-flyvideo.c
deleted file mode 100644
index 9c73043..0000000
--- a/drivers/media/IR/keymaps/rc-flyvideo.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c b/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c
deleted file mode 100644
index cdb1038..0000000
--- a/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-gadmei-rm008z.c b/drivers/media/IR/keymaps/rc-gadmei-rm008z.c
deleted file mode 100644
index c16c0d1..0000000
--- a/drivers/media/IR/keymaps/rc-gadmei-rm008z.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c
deleted file mode 100644
index 89f8e38..0000000
--- a/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-gotview7135.c b/drivers/media/IR/keymaps/rc-gotview7135.c
deleted file mode 100644
index 52f025b..0000000
--- a/drivers/media/IR/keymaps/rc-gotview7135.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-hauppauge-new.c b/drivers/media/IR/keymaps/rc-hauppauge-new.c
deleted file mode 100644
index c6f8cd7..0000000
--- a/drivers/media/IR/keymaps/rc-hauppauge-new.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-imon-mce.c b/drivers/media/IR/keymaps/rc-imon-mce.c
deleted file mode 100644
index e49f350..0000000
--- a/drivers/media/IR/keymaps/rc-imon-mce.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-imon-pad.c b/drivers/media/IR/keymaps/rc-imon-pad.c
deleted file mode 100644
index bc4db72..0000000
--- a/drivers/media/IR/keymaps/rc-imon-pad.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-iodata-bctv7e.c b/drivers/media/IR/keymaps/rc-iodata-bctv7e.c
deleted file mode 100644
index ef66002..0000000
--- a/drivers/media/IR/keymaps/rc-iodata-bctv7e.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-kaiomy.c b/drivers/media/IR/keymaps/rc-kaiomy.c
deleted file mode 100644
index 4c7883b..0000000
--- a/drivers/media/IR/keymaps/rc-kaiomy.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-kworld-315u.c b/drivers/media/IR/keymaps/rc-kworld-315u.c
deleted file mode 100644
index 618c817..0000000
--- a/drivers/media/IR/keymaps/rc-kworld-315u.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c
deleted file mode 100644
index 366732f..0000000
--- a/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c b/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c
deleted file mode 100644
index 7521315..0000000
--- a/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-lirc.c b/drivers/media/IR/keymaps/rc-lirc.c
deleted file mode 100644
index 43fcf90..0000000
--- a/drivers/media/IR/keymaps/rc-lirc.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-lme2510.c b/drivers/media/IR/keymaps/rc-lme2510.c
deleted file mode 100644
index 40dcf0b..0000000
--- a/drivers/media/IR/keymaps/rc-lme2510.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-manli.c b/drivers/media/IR/keymaps/rc-manli.c
deleted file mode 100644
index 0f590b3..0000000
--- a/drivers/media/IR/keymaps/rc-manli.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-msi-digivox-ii.c b/drivers/media/IR/keymaps/rc-msi-digivox-ii.c
deleted file mode 100644
index 67237fb..0000000
--- a/drivers/media/IR/keymaps/rc-msi-digivox-ii.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-msi-digivox-iii.c b/drivers/media/IR/keymaps/rc-msi-digivox-iii.c
deleted file mode 100644
index 882056e..0000000
--- a/drivers/media/IR/keymaps/rc-msi-digivox-iii.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c
deleted file mode 100644
index eb8e42c..0000000
--- a/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere.c
deleted file mode 100644
index ef41185..0000000
--- a/drivers/media/IR/keymaps/rc-msi-tvanywhere.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-nebula.c b/drivers/media/IR/keymaps/rc-nebula.c
deleted file mode 100644
index ccc50eb..0000000
--- a/drivers/media/IR/keymaps/rc-nebula.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c
deleted file mode 100644
index e1b54d2..0000000
--- a/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-norwood.c b/drivers/media/IR/keymaps/rc-norwood.c
deleted file mode 100644
index e5849a6..0000000
--- a/drivers/media/IR/keymaps/rc-norwood.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-npgtech.c b/drivers/media/IR/keymaps/rc-npgtech.c
deleted file mode 100644
index b9ece1e..0000000
--- a/drivers/media/IR/keymaps/rc-npgtech.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pctv-sedna.c b/drivers/media/IR/keymaps/rc-pctv-sedna.c
deleted file mode 100644
index 4129bb4..0000000
--- a/drivers/media/IR/keymaps/rc-pctv-sedna.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pinnacle-color.c b/drivers/media/IR/keymaps/rc-pinnacle-color.c
deleted file mode 100644
index 326e023..0000000
--- a/drivers/media/IR/keymaps/rc-pinnacle-color.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pinnacle-grey.c b/drivers/media/IR/keymaps/rc-pinnacle-grey.c
deleted file mode 100644
index 14cb772..0000000
--- a/drivers/media/IR/keymaps/rc-pinnacle-grey.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c
deleted file mode 100644
index 835bf4e..0000000
--- a/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pixelview-mk12.c b/drivers/media/IR/keymaps/rc-pixelview-mk12.c
deleted file mode 100644
index 5a735d5..0000000
--- a/drivers/media/IR/keymaps/rc-pixelview-mk12.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pixelview-new.c b/drivers/media/IR/keymaps/rc-pixelview-new.c
deleted file mode 100644
index 7bbbbf5..0000000
--- a/drivers/media/IR/keymaps/rc-pixelview-new.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pixelview.c b/drivers/media/IR/keymaps/rc-pixelview.c
deleted file mode 100644
index 82ff12e..0000000
--- a/drivers/media/IR/keymaps/rc-pixelview.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-powercolor-real-angel.c b/drivers/media/IR/keymaps/rc-powercolor-real-angel.c
deleted file mode 100644
index 7cef819..0000000
--- a/drivers/media/IR/keymaps/rc-powercolor-real-angel.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-proteus-2309.c b/drivers/media/IR/keymaps/rc-proteus-2309.c
deleted file mode 100644
index 22e92d3..0000000
--- a/drivers/media/IR/keymaps/rc-proteus-2309.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-purpletv.c b/drivers/media/IR/keymaps/rc-purpletv.c
deleted file mode 100644
index 4e20fc2..0000000
--- a/drivers/media/IR/keymaps/rc-purpletv.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-pv951.c b/drivers/media/IR/keymaps/rc-pv951.c
deleted file mode 100644
index 36679e7..0000000
--- a/drivers/media/IR/keymaps/rc-pv951.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c
deleted file mode 100644
index cc6b8f5..0000000
--- a/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-rc5-tv.c b/drivers/media/IR/keymaps/rc-rc5-tv.c
deleted file mode 100644
index 73cce2f..0000000
--- a/drivers/media/IR/keymaps/rc-rc5-tv.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c
deleted file mode 100644
index 6da955d..0000000
--- a/drivers/media/IR/keymaps/rc-rc6-mce.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c
deleted file mode 100644
index ab1a6d2..0000000
--- a/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-streamzap.c b/drivers/media/IR/keymaps/rc-streamzap.c
deleted file mode 100644
index df32013..0000000
--- a/drivers/media/IR/keymaps/rc-streamzap.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-tbs-nec.c b/drivers/media/IR/keymaps/rc-tbs-nec.c
deleted file mode 100644
index 3309631..0000000
--- a/drivers/media/IR/keymaps/rc-tbs-nec.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c
deleted file mode 100644
index 5326a0b..0000000
--- a/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-terratec-slim.c b/drivers/media/IR/keymaps/rc-terratec-slim.c
deleted file mode 100644
index 10dee4c..0000000
--- a/drivers/media/IR/keymaps/rc-terratec-slim.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-tevii-nec.c b/drivers/media/IR/keymaps/rc-tevii-nec.c
deleted file mode 100644
index e30d411..0000000
--- a/drivers/media/IR/keymaps/rc-tevii-nec.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-total-media-in-hand.c b/drivers/media/IR/keymaps/rc-total-media-in-hand.c
deleted file mode 100644
index fd19857..0000000
--- a/drivers/media/IR/keymaps/rc-total-media-in-hand.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-trekstor.c b/drivers/media/IR/keymaps/rc-trekstor.c
deleted file mode 100644
index 91092ca..0000000
--- a/drivers/media/IR/keymaps/rc-trekstor.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-tt-1500.c b/drivers/media/IR/keymaps/rc-tt-1500.c
deleted file mode 100644
index bc88de0..0000000
--- a/drivers/media/IR/keymaps/rc-tt-1500.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-twinhan1027.c b/drivers/media/IR/keymaps/rc-twinhan1027.c
deleted file mode 100644
index 0b5d356..0000000
--- a/drivers/media/IR/keymaps/rc-twinhan1027.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-videomate-s350.c b/drivers/media/IR/keymaps/rc-videomate-s350.c
deleted file mode 100644
index 4df7fcd..0000000
--- a/drivers/media/IR/keymaps/rc-videomate-s350.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c b/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c
deleted file mode 100644
index 776b0a6..0000000
--- a/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c
deleted file mode 100644
index 9d2d550..0000000
--- a/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/keymaps/rc-winfast.c b/drivers/media/IR/keymaps/rc-winfast.c
deleted file mode 100644
index 0e90a3b..0000000
--- a/drivers/media/IR/keymaps/rc-winfast.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c
deleted file mode 100644
index 756656e..0000000
--- a/drivers/media/IR/lirc_dev.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
deleted file mode 100644
index 392ca24..0000000
--- a/drivers/media/IR/mceusb.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c
deleted file mode 100644
index acc729c..0000000
--- a/drivers/media/IR/nuvoton-cir.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/nuvoton-cir.h b/drivers/media/IR/nuvoton-cir.h
deleted file mode 100644
index 62dc530..0000000
--- a/drivers/media/IR/nuvoton-cir.h
+++ /dev/null
@@ -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 --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c
deleted file mode 100644
index 689143f..0000000
--- a/drivers/media/IR/rc-map.c
+++ /dev/null
@@ -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 --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c
deleted file mode 100644
index 3a20aef..0000000
--- a/drivers/media/IR/streamzap.c
+++ /dev/null
@@ -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 --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index a28541b..81b3ba8 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -40,35 +40,6 @@
 	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 @@
 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/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 --git a/drivers/media/Makefile b/drivers/media/Makefile
index 499b081..b603ea6 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -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 --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index d246910..0ac5c61 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -1129,35 +1129,6 @@
 			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 +1157,6 @@
 	.vidioc_streamon             = vidioc_streamon,
 	.vidioc_streamoff            = vidioc_streamoff,
 	.vidioc_g_parm 		     = vidioc_g_parm,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf                 = vidiocgmbuf,
-#endif
 };
 
 /*********************************************************************************/
diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/common/tuners/max2165.c
index 937e4b0..9883617 100644
--- a/drivers/media/common/tuners/max2165.c
+++ b/drivers/media/common/tuners/max2165.c
@@ -52,13 +52,12 @@
 	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 @@
 
 	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 --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c
index 8da1fde..aacfe23 100644
--- a/drivers/media/common/tuners/tda18218.c
+++ b/drivers/media/common/tuners/tda18218.c
@@ -28,7 +28,7 @@
 /* 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 --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
index a6ceb08..f3de0a4 100644
--- a/drivers/media/dvb/dm1105/Kconfig
+++ b/drivers/media/dvb/dm1105/Kconfig
@@ -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 @@
 	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 --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 5d404f1..2d8b404 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -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 @@
 
 /* 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 @@
 
 	data = (ircom >> 8) & 0x7f;
 
-	ir_keydown(ir->input_dev, data, 0);
+	rc_keydown(ir->dev, data, 0);
 }
 
 /* work handler */
@@ -593,46 +592,47 @@
 
 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 --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index ad1f61d..e4b5c03 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -572,13 +572,13 @@
 	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 --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 4df42aa..51752a9 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1329,7 +1329,8 @@
 		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 --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 2525d3b..3d48ba0 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -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 --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index a5c3637..53b93a4 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -37,7 +37,7 @@
 	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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c
index 696207f..c3bc64e 100644
--- a/drivers/media/dvb/dvb-usb/af9005-remote.c
+++ b/drivers/media/dvb/dvb-usb/af9005-remote.c
@@ -33,7 +33,7 @@
 
 #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 @@
 	{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 @@
 				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 @@
 	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 --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
index 8ecba88..51f6439 100644
--- a/drivers/media/dvb/dvb-usb/af9005.c
+++ b/drivers/media/dvb/dvb-usb/af9005.c
@@ -1027,8 +1027,8 @@
 
 	.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 @@
 		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 @@
 	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 --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/dvb/dvb-usb/af9005.h
index 3c1fbd1..c71c77b 100644
--- a/drivers/media/dvb/dvb-usb/af9005.h
+++ b/drivers/media/dvb/dvb-usb/af9005.h
@@ -3490,7 +3490,7 @@
 /* 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 --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 31c0a0e..8671ca3 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -1041,13 +1041,13 @@
 				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 @@
 		.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 @@
 		.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 @@
 		.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 --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index 1759d26..6b402e9 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -394,7 +394,7 @@
 
 	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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c
index 62c5828..57e2444 100644
--- a/drivers/media/dvb/dvb-usb/az6027.c
+++ b/drivers/media/dvb/dvb-usb/az6027.c
@@ -386,7 +386,7 @@
 }
 
 /* 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 @@
 	{ 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 @@
 	.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 @@
 			.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 --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
index 4f5aa83f..16f2ce2 100644
--- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c
+++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
@@ -84,7 +84,7 @@
 	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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index cd9f362..acb5fb2 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -385,7 +385,7 @@
 
 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 @@
 	*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_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 @@
 	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_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 @@
 	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 @@
 	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 @@
 	{ 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 @@
 	{ 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 @@
 		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 @@
 			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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index c2c9d23..3537d65 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -60,7 +60,7 @@
 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 --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 48397f1..8ca48f7 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -471,19 +471,19 @@
 	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 @@
 		return ret;
 	}
 
-	d->props.rc.core.protocol = ir_type;
+	d->props.rc.core.protocol = rc_type;
 
 	return ret;
 }
@@ -535,7 +535,7 @@
 	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 @@
 		 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 */
@@ -600,7 +600,7 @@
 		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 --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index e06acd1..defd839 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -510,7 +510,7 @@
 
 	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 @@
 			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;
 	}
@@ -1924,12 +1924,10 @@
 			.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 +1958,10 @@
 			.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 +2017,10 @@
 			.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 +2059,10 @@
 			.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 +2135,10 @@
 			.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 +2179,10 @@
 			.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 +2247,10 @@
 			.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 +2294,10 @@
 			.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 +2363,10 @@
 			.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 +2399,10 @@
 			.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 +2467,10 @@
 			.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 +2511,10 @@
 			.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 +2560,10 @@
 			.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 +2597,10 @@
 			.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 --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index ba991aa..956f7ae 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -327,7 +327,7 @@
 /*
  * 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 @@
 	{ 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 --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 8e3c0d2..04d91bd 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -213,8 +213,8 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index 1cbc41c..c1d9094 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -83,8 +83,8 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
index 61a6bf3..e47c321 100644
--- a/drivers/media/dvb/dvb-usb/dibusb.h
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -124,7 +124,7 @@
 #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 --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 13d006b..f2dbce7 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -161,7 +161,7 @@
 	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 @@
 	/* 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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index ca495e0..ecd86ec 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -57,7 +57,7 @@
 
 /* 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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 192a40c..1a6310b 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -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 --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index b579fed..23005b3 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -13,11 +13,11 @@
 {
 	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 @@
 	 * 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 @@
 {
 	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 @@
 			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_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 @@
 			      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 @@
 
 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 @@
 	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_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 @@
 		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 @@
 				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 --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 34f7b3b..65fa926 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -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 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_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 @@
 #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 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 @@
  *
  * @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_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 --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 774df88..2c307ba 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -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 @@
 	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 @@
 	{ 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 @@
 	{ 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 @@
 	{ 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 @@
 		/* 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 @@
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 @@
 	/* fill only different fields */
 	p7500->firmware = "dvb-usb-p7500.fw";
 	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 --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index c821293..1cb3d9a 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -24,6 +24,33 @@
 
 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 @@
 				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 --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
index e83a575..831749a 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.h
+++ b/drivers/media/dvb/dvb-usb/gp8psk.h
@@ -25,7 +25,6 @@
 #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 @@
 #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 @@
 #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 --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c
index d939fbb..9eea418 100644
--- a/drivers/media/dvb/dvb-usb/lmedm04.c
+++ b/drivers/media/dvb/dvb-usb/lmedm04.c
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 	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 @@
 			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 @@
 					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 @@
 					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 @@
 				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 @@
 				break;
 			case 0x24:
 				rbuf[0] = 0x55;
-				rbuf[1] = (st->signal_level & 0x80)
-						? 0 : st->signal_lock;
+				rbuf[1] = 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);
-				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_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_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_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
+	strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
-	usb_to_input_id(d->udev, &input_dev->id);
+	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 |= ir_input_register(input_dev, ir_codes, NULL, "LME 2510");
-
+	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 @@
 		ret |= (data[0] == 0x88) ? 0 : -1;
 		}
 	}
+
 	usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
 
@@ -701,10 +671,11 @@
 	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[] = "dvb-usb-lme2510c-s7395.fw";
@@ -712,8 +683,10 @@
 	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 @@
 		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 @@
 					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 @@
 		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);
 		}
-		kfree(adap->fe);
-		adap->fe = NULL;
+	} else {
+		info("DM04 Not Supported");
+		return -ENODEV;
 	}
 
-	info("DM04 Not Supported");
-	return -ENODEV;
+end:	if (ret) {
+		kfree(adap->fe);
+		adap->fe = NULL;
+		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 @@
 		{
 			.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 @@
 	.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 },
 			},
 
@@ -989,6 +1013,7 @@
 		{
 			.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 @@
 	.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 @@
 		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 @@
 }
 
 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_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.74");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index bdef1a1..da9dc91 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -142,9 +142,9 @@
 	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 @@
 };
 
 /* 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 @@
 	{ 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 @@
 	{ 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 @@
 
 	.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 @@
 
 	.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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index 181f36a..9d3cd2d 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -21,7 +21,7 @@
 #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 @@
 
 			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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index f896337..1f1b7d6 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -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 @@
 	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 @@
 
 		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 @@
 	.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 --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index a6de489..0d4709f 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -43,6 +43,7 @@
 
 struct ttusb2_state {
 	u8 id;
+	u16 last_rc_key;
 };
 
 static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
@@ -128,6 +129,33 @@
 	.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 @@
 
 	.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 --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index 5c9f327..7890e75 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -174,7 +174,7 @@
 }
 
 /* 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 @@
 		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 @@
 	.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 --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index f13791c..ab0ab3c 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -99,7 +99,7 @@
 
 /* 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 @@
 		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 @@
 
 	.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 --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 96b2701..ef3e43a 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -497,7 +497,7 @@
 	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 @@
 	  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 --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 9a31985..b1d9525 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -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_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 --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c
index e2a95c0..ce22205 100644
--- a/drivers/media/dvb/frontends/af9013.c
+++ b/drivers/media/dvb/frontends/af9013.c
@@ -964,7 +964,7 @@
 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 --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c
index 43aac2f..1539ea1 100644
--- a/drivers/media/dvb/frontends/atbm8830.c
+++ b/drivers/media/dvb/frontends/atbm8830.c
@@ -50,8 +50,7 @@
 	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 @@
 
 	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 @@
 
 	*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 --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
index 6d9c594..b537891 100644
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -278,10 +278,18 @@
 			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 @@
 	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 @@
 	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 @@
 	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 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 @@
 		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 --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h
index 609cf04..751e17d 100644
--- a/drivers/media/dvb/frontends/au8522_priv.h
+++ b/drivers/media/dvb/frontends/au8522_priv.h
@@ -397,7 +397,9 @@
 #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 --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
index 0f09fd3..c7f5ccf 100644
--- a/drivers/media/dvb/frontends/dib7000m.c
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -805,7 +805,7 @@
 	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 @@
 	/* 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 @@
 	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 @@
 	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 @@
 	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;
 	}
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 3aed0d4..6aa02cb 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -717,7 +717,7 @@
 	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 @@
 	/* 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 @@
 	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 @@
 	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 @@
 	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 --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
index 55f2eba..6360c68 100644
--- a/drivers/media/dvb/frontends/ix2505v.c
+++ b/drivers/media/dvb/frontends/ix2505v.c
@@ -72,7 +72,7 @@
 	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)
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c
index 0fcddc4..1172b54 100644
--- a/drivers/media/dvb/frontends/lgs8gxx.c
+++ b/drivers/media/dvb/frontends/lgs8gxx.c
@@ -60,13 +60,12 @@
 		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 @@
 
 	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 --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c
new file mode 100644
index 0000000..d3ad3e7
--- /dev/null
+++ b/drivers/media/dvb/frontends/mb86a20s.c
@@ -0,0 +1,615 @@
+/*
+ *   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;
+};
+
+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 rcor(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 (rcor=%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)
+		return rc;
+
+	if (!state->config->is_serial) {
+		regD5 &= ~1;
+
+		rc = mb86a20s_writereg(state, 0x50, 0xd5);
+		if (rc < 0)
+			return rc;
+		rc = mb86a20s_writereg(state, 0x51, regD5);
+		if (rc < 0)
+			return rc;
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	return 0;
+}
+
+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);
+	fe->ops.tuner_ops.set_params(fe, p);
+
+	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 --git a/drivers/media/dvb/frontends/mb86a20s.h b/drivers/media/dvb/frontends/mb86a20s.h
new file mode 100644
index 0000000..bf22e77
--- /dev/null
+++ b/drivers/media/dvb/frontends/mb86a20s.h
@@ -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 --git a/drivers/media/dvb/frontends/s921.c b/drivers/media/dvb/frontends/s921.c
new file mode 100644
index 0000000..ca0103d
--- /dev/null
+++ b/drivers/media/dvb/frontends/s921.c
@@ -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 --git a/drivers/media/dvb/frontends/s921.h b/drivers/media/dvb/frontends/s921.h
new file mode 100644
index 0000000..f220d82
--- /dev/null
+++ b/drivers/media/dvb/frontends/s921.h
@@ -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 --git a/drivers/media/dvb/frontends/s921_core.c b/drivers/media/dvb/frontends/s921_core.c
deleted file mode 100644
index 974b52b..0000000
--- a/drivers/media/dvb/frontends/s921_core.c
+++ /dev/null
@@ -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 --git a/drivers/media/dvb/frontends/s921_core.h b/drivers/media/dvb/frontends/s921_core.h
deleted file mode 100644
index de2f10a..0000000
--- a/drivers/media/dvb/frontends/s921_core.h
+++ /dev/null
@@ -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 --git a/drivers/media/dvb/frontends/s921_module.c b/drivers/media/dvb/frontends/s921_module.c
deleted file mode 100644
index 0eefff6..0000000
--- a/drivers/media/dvb/frontends/s921_module.c
+++ /dev/null
@@ -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 --git a/drivers/media/dvb/frontends/s921_module.h b/drivers/media/dvb/frontends/s921_module.h
deleted file mode 100644
index 7866042..0000000
--- a/drivers/media/dvb/frontends/s921_module.h
+++ /dev/null
@@ -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 --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
index 8e38fce..37a222d 100644
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/drivers/media/dvb/frontends/stb0899_drv.c
@@ -714,7 +714,7 @@
 	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 --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c
index 80a9e4c..64673b8 100644
--- a/drivers/media/dvb/frontends/stb6100.c
+++ b/drivers/media/dvb/frontends/stb6100.c
@@ -51,7 +51,7 @@
 		if (x > y)								\
 			printk(format, ##arg);						\
 	}										\
-} while(0)
+} while (0)
 
 struct stb6100_lkup {
 	u32 val_low;
@@ -117,7 +117,10 @@
 	[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 @@
 	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 @@
 	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 @@
 	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 @@
 	/* 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 @@
 	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 @@
 	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 @@
 	}
 	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;
+
+	/* 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);
-	regs[STB6100_LPEN] |= STB6100_LPEN_LPEN;	/* PLL loop enabled		*/
-	if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0)
-		return rc;
 
+	/* 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 @@
 	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 --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index 425e7a4..4e0fc2c 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -1483,8 +1483,8 @@
 		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 @@
 		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 --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig
index fd0830e..a13a505 100644
--- a/drivers/media/dvb/mantis/Kconfig
+++ b/drivers/media/dvb/mantis/Kconfig
@@ -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 --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c
index 09e9fc7..70e73af 100644
--- a/drivers/media/dvb/mantis/hopper_cards.c
+++ b/drivers/media/dvb/mantis/hopper_cards.c
@@ -251,6 +251,8 @@
 	{ }
 };
 
+MODULE_DEVICE_TABLE(pci, hopper_pci_table);
+
 static struct pci_driver hopper_pci_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= hopper_pci_table,
diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c
index 96674c7..68a29f8 100644
--- a/drivers/media/dvb/mantis/hopper_vp3028.c
+++ b/drivers/media/dvb/mantis/hopper_vp3028.c
@@ -47,17 +47,17 @@
 	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 --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c
index cf4b39f..40da225 100644
--- a/drivers/media/dvb/mantis/mantis_cards.c
+++ b/drivers/media/dvb/mantis/mantis_cards.c
@@ -281,6 +281,8 @@
 	{ }
 };
 
+MODULE_DEVICE_TABLE(pci, mantis_pci_table);
+
 static struct pci_driver mantis_pci_driver = {
 	.name		= DRIVER_NAME,
 	.id_table	= mantis_pci_table,
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
index d0b645a..bd400d2 100644
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -171,7 +171,9 @@
 	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 --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c
index 99d82ee..e5180e4 100644
--- a/drivers/media/dvb/mantis/mantis_dvb.c
+++ b/drivers/media/dvb/mantis/mantis_dvb.c
@@ -47,15 +47,15 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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 --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
index a7b369a..9f73c2c 100644
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -111,7 +111,7 @@
 	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 --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c
index a99489b..db6d54d 100644
--- a/drivers/media/dvb/mantis/mantis_input.c
+++ b/drivers/media/dvb/mantis/mantis_input.c
@@ -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 @@
 	{ 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;
+
+	dev = rc_allocate_device();
+	if (!dev) {
+		dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
+		err = -ENOMEM;
+		goto out_map;
 	}
 
-	sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
-	sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev));
+	sprintf(mantis->input_name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
+	sprintf(mantis->input_phys, "pci-%s/ir0", pci_name(mantis->pdev));
 
-	rc->name = name;
-	rc->phys = 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;
 
-	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;
-
-	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 --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c
index fe31cfb..479086d 100644
--- a/drivers/media/dvb/mantis/mantis_ioc.c
+++ b/drivers/media/dvb/mantis/mantis_ioc.c
@@ -75,7 +75,7 @@
 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 @@
 	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 --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h
index 188fe5a..d56e002 100644
--- a/drivers/media/dvb/mantis/mantis_ioc.h
+++ b/drivers/media/dvb/mantis/mantis_ioc.h
@@ -44,7 +44,7 @@
 };
 
 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 --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c
index 7d2f239..97b889e 100644
--- a/drivers/media/dvb/mantis/mantis_uart.c
+++ b/drivers/media/dvb/mantis/mantis_uart.c
@@ -182,5 +182,6 @@
 {
 	/* disable interrupt */
 	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
+	flush_work_sync(&mantis->uart_work);
 }
 EXPORT_SYMBOL_GPL(mantis_uart_exit);
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c
index 4a723bd..deec927 100644
--- a/drivers/media/dvb/mantis/mantis_vp1033.c
+++ b/drivers/media/dvb/mantis/mantis_vp1033.c
@@ -173,7 +173,7 @@
 		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 --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c
index 8e6ae55..26bc0cb 100644
--- a/drivers/media/dvb/mantis/mantis_vp1034.c
+++ b/drivers/media/dvb/mantis/mantis_vp1034.c
@@ -50,13 +50,13 @@
 	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 @@
 		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 --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c
index d1aa2bc..38a436c 100644
--- a/drivers/media/dvb/mantis/mantis_vp1041.c
+++ b/drivers/media/dvb/mantis/mantis_vp1041.c
@@ -316,14 +316,14 @@
 	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 --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c
index 10ce817..06da0dd 100644
--- a/drivers/media/dvb/mantis/mantis_vp2033.c
+++ b/drivers/media/dvb/mantis/mantis_vp2033.c
@@ -132,7 +132,7 @@
 		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 @@
 				"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 --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c
index a7ca233e8..f72b137 100644
--- a/drivers/media/dvb/mantis/mantis_vp2040.c
+++ b/drivers/media/dvb/mantis/mantis_vp2040.c
@@ -132,7 +132,7 @@
 		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 @@
 				"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 --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c
index 1f43342..c09308cd 100644
--- a/drivers/media/dvb/mantis/mantis_vp3030.c
+++ b/drivers/media/dvb/mantis/mantis_vp3030.c
@@ -59,21 +59,21 @@
 	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 --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
index 3a7ef71..dc073bd 100644
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -1304,7 +1304,6 @@
 static int ngene_start(struct ngene *dev)
 {
 	int stat;
-	unsigned long flags;
 	int i;
 
 	pci_set_master(dev->pci_dev);
@@ -1337,6 +1336,8 @@
 #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 @@
 
 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 @@
 	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 --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig
index e520bce..bc6456e 100644
--- a/drivers/media/dvb/siano/Kconfig
+++ b/drivers/media/dvb/siano/Kconfig
@@ -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 --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index 135e45b..78765ed 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -438,7 +438,7 @@
 	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 --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c
index a27c44a..37bc5c4 100644
--- a/drivers/media/dvb/siano/smsir.c
+++ b/drivers/media/dvb/siano/smsir.c
@@ -45,25 +45,24 @@
 		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 @@
 	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 --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/dvb/siano/smsir.h
index 926e247..ae92b3a 100644
--- a/drivers/media/dvb/siano/smsir.h
+++ b/drivers/media/dvb/siano/smsir.h
@@ -28,20 +28,19 @@
 #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 --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index 50d4338..0b8da57 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -288,8 +288,7 @@
 
 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 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_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 --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index debea8d..44afab2 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -89,7 +89,6 @@
 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 @@
 	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 --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index ac20c5b..cdd31ca 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -100,6 +100,7 @@
 		.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 @@
 		.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 @@
 		.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 @@
 		.tuner		= 0,
 		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
 		.status		= 0,
+		.capabilities	= V4L2_IN_CAP_STD,
 	}
 };
 
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 97afc01..e957d76 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1406,8 +1406,10 @@
 
 #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 --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index a9c2c32..b82756d 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -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 @@
 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 @@
 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 @@
 	    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 @@
 	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 @@
 	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 @@
 	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 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 --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 83567b8..3c5a473 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -452,4 +452,20 @@
 	  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 --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f615583..d297074 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -26,5 +26,6 @@
 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 --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 05e832f..6cc5d13 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -31,7 +31,6 @@
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
-#include <linux/delay.h>	/* udelay			*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
 #include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
 #include <linux/io.h>		/* outb, outb_p			*/
@@ -71,27 +70,17 @@
 
 /* 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 +109,7 @@
 
 	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 +144,7 @@
 		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 +158,7 @@
 		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 +409,7 @@
 
 	/* 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 --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
new file mode 100644
index 0000000..dd6bd36
--- /dev/null
+++ b/drivers/media/radio/radio-wl1273.c
@@ -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 = "radio-wl1273-fw.bin";
+	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 (request_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,
+	.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 --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h
index b9914d7..4a4e908 100644
--- a/drivers/media/radio/si470x/radio-si470x.h
+++ b/drivers/media/radio/si470x/radio-si470x.h
@@ -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 --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c
index a6e6f19..0fab6f8 100644
--- a/drivers/media/radio/si4713-i2c.c
+++ b/drivers/media/radio/si4713-i2c.c
@@ -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_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 @@
 	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 @@
 		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 @@
 		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 @@
 					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 @@
 		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 @@
 			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 @@
 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 @@
 		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 --git a/drivers/media/radio/si4713-i2c.h b/drivers/media/radio/si4713-i2c.h
index faf8cff..c6dfa7f 100644
--- a/drivers/media/radio/si4713-i2c.h
+++ b/drivers/media/radio/si4713-i2c.h
@@ -211,6 +211,8 @@
 	u32 enabled;
 };
 
+#define SI4713_NUM_SUPPLIES		2
+
 /*
  * si4713_device - private data
  */
@@ -220,11 +222,12 @@
 	/* 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 --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
new file mode 100644
index 0000000..3785162
--- /dev/null
+++ b/drivers/media/rc/Kconfig
@@ -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 --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
new file mode 100644
index 0000000..67b4f7f
--- /dev/null
+++ b/drivers/media/rc/Makefile
@@ -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 --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
new file mode 100644
index 0000000..80b3c31
--- /dev/null
+++ b/drivers/media/rc/ene_ir.c
@@ -0,0 +1,1208 @@
+/*
+ * 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 = MS_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 =
+			MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
+				ENE_FW_SAMPLE_PERIOD_FAN);
+	} else {
+		dev->rdev->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->rdev->min_timeout = MS_TO_NS(127 * sample_period);
+		dev->rdev->max_timeout = MS_TO_NS(200000);
+	}
+
+	if (dev->hw_learning_and_tx_capable)
+		dev->rdev->tx_resolution = MS_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 = MS_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 = 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(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;
+
+	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";
+	}
+
+	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;
+
+	dev->rdev = rdev;
+	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 --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h
new file mode 100644
index 0000000..c179baf
--- /dev/null
+++ b/drivers/media/rc/ene_ir.h
@@ -0,0 +1,261 @@
+/*
+ * 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 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 --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
new file mode 100644
index 0000000..6811512
--- /dev/null
+++ b/drivers/media/rc/imon.c
@@ -0,0 +1,2457 @@
+/*
+ *   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;
+	bool pad_mouse;
+	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;
+		pad_mouse = false;
+		break;
+	case RC_TYPE_UNKNOWN:
+	case RC_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 */
+		rc_type = RC_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 */
+		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 = 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 = 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 = 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)
+			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->rdev->allowed_protos = allowed_protos;
+	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;
+	if (ictx->rc_type == RC_TYPE_RC6)
+		rdev->map_name = RC_MAP_IMON_MCE;
+	else
+		rdev->map_name = RC_MAP_IMON_PAD;
+
+	/* 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);
+
+	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;
+	}
+
+	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:
+	rc_unregister_device(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 = 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 --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
new file mode 100644
index 0000000..624449a
--- /dev/null
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -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 --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
new file mode 100644
index 0000000..f011c5d
--- /dev/null
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -0,0 +1,402 @@
+/* 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/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);
+
+	/* 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(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(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 --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
new file mode 100644
index 0000000..7b58b4a
--- /dev/null
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -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 --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
new file mode 100644
index 0000000..185badd
--- /dev/null
+++ b/drivers/media/rc/ir-raw.c
@@ -0,0 +1,371 @@
+/* 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 */
+	struct 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.
+	 */
+	ev.duration = 0;
+	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()
+{
+	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 --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
new file mode 100644
index 0000000..ebdba55
--- /dev/null
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -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 --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
new file mode 100644
index 0000000..90aa886
--- /dev/null
+++ b/drivers/media/rc/ir-rc5-sz-decoder.c
@@ -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 --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
new file mode 100644
index 0000000..755dafa
--- /dev/null
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -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 --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
new file mode 100644
index 0000000..a92de80
--- /dev/null
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -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 --git a/drivers/media/rc/keymaps/Kconfig b/drivers/media/rc/keymaps/Kconfig
new file mode 100644
index 0000000..8e615fd
--- /dev/null
+++ b/drivers/media/rc/keymaps/Kconfig
@@ -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 --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
new file mode 100644
index 0000000..0659e9f
--- /dev/null
+++ b/drivers/media/rc/keymaps/Makefile
@@ -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 --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
new file mode 100644
index 0000000..136d395
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-alink-dtu-m.c b/drivers/media/rc/keymaps/rc-alink-dtu-m.c
new file mode 100644
index 0000000..fe652e9
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-alink-dtu-m.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-anysee.c b/drivers/media/rc/keymaps/rc-anysee.c
new file mode 100644
index 0000000..884f1b5
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-anysee.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-apac-viewcomp.c b/drivers/media/rc/keymaps/rc-apac-viewcomp.c
new file mode 100644
index 0000000..7af1882
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-apac-viewcomp.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-asus-pc39.c b/drivers/media/rc/keymaps/rc-asus-pc39.c
new file mode 100644
index 0000000..b248115
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-asus-pc39.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c
new file mode 100644
index 0000000..f766b24
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avermedia-a16d.c b/drivers/media/rc/keymaps/rc-avermedia-a16d.c
new file mode 100644
index 0000000..ec9beee
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-a16d.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c
new file mode 100644
index 0000000..bdf97b7
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
new file mode 100644
index 0000000..3ddb41b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c
new file mode 100644
index 0000000..357fea58
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
new file mode 100644
index 0000000..e694e6e
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
new file mode 100644
index 0000000..f4ca1ff
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avermedia.c b/drivers/media/rc/keymaps/rc-avermedia.c
new file mode 100644
index 0000000..edfa715
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avermedia.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-avertv-303.c b/drivers/media/rc/keymaps/rc-avertv-303.c
new file mode 100644
index 0000000..32e9498
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-avertv-303.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c
new file mode 100644
index 0000000..c3f6d62
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c
new file mode 100644
index 0000000..4b787fa
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-behold-columbus.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c
new file mode 100644
index 0000000..0ee1f14
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c
new file mode 100644
index 0000000..97fc386
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-cinergy-1400.c b/drivers/media/rc/keymaps/rc-cinergy-1400.c
new file mode 100644
index 0000000..284534b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-cinergy-1400.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c
new file mode 100644
index 0000000..99520ff
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-cinergy.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-dib0700-nec.c b/drivers/media/rc/keymaps/rc-dib0700-nec.c
new file mode 100644
index 0000000..c59851b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dib0700-nec.c
@@ -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 */
+	{ 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_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 --git a/drivers/media/rc/keymaps/rc-dib0700-rc5.c b/drivers/media/rc/keymaps/rc-dib0700-rc5.c
new file mode 100644
index 0000000..4af12e4
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dib0700-rc5.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c
new file mode 100644
index 0000000..f68b450
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-digittrade.c b/drivers/media/rc/keymaps/rc-digittrade.c
new file mode 100644
index 0000000..21d4987
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-digittrade.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-dm1105-nec.c b/drivers/media/rc/keymaps/rc-dm1105-nec.c
new file mode 100644
index 0000000..d024fbf
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dm1105-nec.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
new file mode 100644
index 0000000..43912bd
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c
new file mode 100644
index 0000000..015e99d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-em-terratec.c b/drivers/media/rc/keymaps/rc-em-terratec.c
new file mode 100644
index 0000000..269d429
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-em-terratec.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c
new file mode 100644
index 0000000..e388698
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c
new file mode 100644
index 0000000..afa4e92
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-encore-enltv.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c
new file mode 100644
index 0000000..7d5b00e
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-evga-indtube.c b/drivers/media/rc/keymaps/rc-evga-indtube.c
new file mode 100644
index 0000000..a2bf24f
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-evga-indtube.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-eztv.c b/drivers/media/rc/keymaps/rc-eztv.c
new file mode 100644
index 0000000..1e8e5b2
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-eztv.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c
new file mode 100644
index 0000000..aea2f4a
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-flydvb.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-flyvideo.c b/drivers/media/rc/keymaps/rc-flyvideo.c
new file mode 100644
index 0000000..5bbe683
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-flyvideo.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c
new file mode 100644
index 0000000..c80b25c
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c
new file mode 100644
index 0000000..068c9ea
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c
new file mode 100644
index 0000000..cdbbed4
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-gotview7135.c b/drivers/media/rc/keymaps/rc-gotview7135.c
new file mode 100644
index 0000000..a38bdde
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-gotview7135.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c
new file mode 100644
index 0000000..bd11da4
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-hauppauge-new.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c
new file mode 100644
index 0000000..cb67184
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-imon-mce.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c
new file mode 100644
index 0000000..eef46b7
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-imon-pad.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c
new file mode 100644
index 0000000..1f59e16
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-kaiomy.c b/drivers/media/rc/keymaps/rc-kaiomy.c
new file mode 100644
index 0000000..f31dc5c
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-kaiomy.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c
new file mode 100644
index 0000000..3ce6ef7
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-kworld-315u.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
new file mode 100644
index 0000000..e45f0b8
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c
new file mode 100644
index 0000000..8faa54f
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-lirc.c b/drivers/media/rc/keymaps/rc-lirc.c
new file mode 100644
index 0000000..e8e23e2
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-lirc.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c
new file mode 100644
index 0000000..875cd81
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-lme2510.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-manli.c b/drivers/media/rc/keymaps/rc-manli.c
new file mode 100644
index 0000000..23b2d04
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-manli.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c
new file mode 100644
index 0000000..7b9a01b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
new file mode 100644
index 0000000..ae9d06b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
new file mode 100644
index 0000000..fa8fd0a
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
new file mode 100644
index 0000000..18b37fa
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c
new file mode 100644
index 0000000..3e6f077
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-nebula.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c
new file mode 100644
index 0000000..26f114c
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c
new file mode 100644
index 0000000..629ee9d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-norwood.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-npgtech.c b/drivers/media/rc/keymaps/rc-npgtech.c
new file mode 100644
index 0000000..4aa588b
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-npgtech.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c
new file mode 100644
index 0000000..fa5ae59
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pinnacle-color.c b/drivers/media/rc/keymaps/rc-pinnacle-color.c
new file mode 100644
index 0000000..23b8c50
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pinnacle-color.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pinnacle-grey.c b/drivers/media/rc/keymaps/rc-pinnacle-grey.c
new file mode 100644
index 0000000..6ba8c36
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pinnacle-grey.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
new file mode 100644
index 0000000..bb10ffe
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pixelview-002t.c b/drivers/media/rc/keymaps/rc-pixelview-002t.c
new file mode 100644
index 0000000..e5ab071
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pixelview-002t.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
new file mode 100644
index 0000000..8d9f664
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c
new file mode 100644
index 0000000..777a700
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pixelview-new.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c
new file mode 100644
index 0000000..0ec5988
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pixelview.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c
new file mode 100644
index 0000000..5f9d546
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-proteus-2309.c b/drivers/media/rc/keymaps/rc-proteus-2309.c
new file mode 100644
index 0000000..8a3a643
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-proteus-2309.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-purpletv.c b/drivers/media/rc/keymaps/rc-purpletv.c
new file mode 100644
index 0000000..ef90296
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-purpletv.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c
new file mode 100644
index 0000000..83a418d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-pv951.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
new file mode 100644
index 0000000..dfc9b15
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c
new file mode 100644
index 0000000..4fcef9f
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-rc5-tv.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c
new file mode 100644
index 0000000..3bf3337
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-rc6-mce.c
@@ -0,0 +1,113 @@
+/* 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 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 */
+
+	{ 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 --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
new file mode 100644
index 0000000..2d14598
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c
new file mode 100644
index 0000000..92cc10d
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-streamzap.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c
new file mode 100644
index 0000000..7242ee6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-tbs-nec.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c
new file mode 100644
index 0000000..bc38e34
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c
new file mode 100644
index 0000000..1abafa5
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-terratec-slim.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-tevii-nec.c b/drivers/media/rc/keymaps/rc-tevii-nec.c
new file mode 100644
index 0000000..ef5ba3f
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-tevii-nec.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c
new file mode 100644
index 0000000..20ac4e1
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-trekstor.c b/drivers/media/rc/keymaps/rc-trekstor.c
new file mode 100644
index 0000000..f8190ea
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-trekstor.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c
new file mode 100644
index 0000000..295f373
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-tt-1500.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c
new file mode 100644
index 0000000..8bf8df6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-twinhan1027.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-videomate-m1f.c b/drivers/media/rc/keymaps/rc-videomate-m1f.c
new file mode 100644
index 0000000..4994d40
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-videomate-m1f.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-videomate-s350.c b/drivers/media/rc/keymaps/rc-videomate-s350.c
new file mode 100644
index 0000000..9e474a6
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-videomate-s350.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c
new file mode 100644
index 0000000..5f2a46e
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c
new file mode 100644
index 0000000..bd8d021
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c
@@ -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 --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c
new file mode 100644
index 0000000..2747db4
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-winfast.c
@@ -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 --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
new file mode 100644
index 0000000..fd237ab
--- /dev/null
+++ b/drivers/media/rc/lirc_dev.c
@@ -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 --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
new file mode 100644
index 0000000..0fef6ef
--- /dev/null
+++ b/drivers/media/rc/mceusb.c
@@ -0,0 +1,1313 @@
+/*
+ * 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 */
+#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 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 = 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->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;
+			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 = MS_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;
+	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->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 --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
new file mode 100644
index 0000000..dd4caf8
--- /dev/null
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -0,0 +1,1244 @@
+/*
+ * 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 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(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 = (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(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 --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
new file mode 100644
index 0000000..1df8235
--- /dev/null
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -0,0 +1,407 @@
+/*
+ * 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
+
+/* 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 --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
new file mode 100644
index 0000000..873b387
--- /dev/null
+++ b/drivers/media/rc/rc-core-priv.h
@@ -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 --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
new file mode 100644
index 0000000..49cee61
--- /dev/null
+++ b/drivers/media/rc/rc-loopback.c
@@ -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 --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
new file mode 100644
index 0000000..72be8a0
--- /dev/null
+++ b/drivers/media/rc/rc-main.c
@@ -0,0 +1,1135 @@
+/* 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) {
+		if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
+			IR_dprintk(1, "unknown key for scancode 0x%04x\n",
+				   scancode);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	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));
+
+	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 (!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 (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 --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
new file mode 100644
index 0000000..6e2911c
--- /dev/null
+++ b/drivers/media/rc/streamzap.c
@@ -0,0 +1,557 @@
+/*
+ * 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 *= 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->rdev->timeout;
+				sz->idle = true;
+				if (sz->timeout_enabled)
+					sz_push(sz, rawir);
+				ir_raw_event_handle(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;
+		}
+	}
+
+	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 = (((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;
+
+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 --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
new file mode 100644
index 0000000..186de55
--- /dev/null
+++ b/drivers/media/rc/winbond-cir.c
@@ -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 --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 6830d28..eb875af 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -7,11 +7,6 @@
 	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
 
@@ -96,7 +91,7 @@
 
 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,
@@ -666,6 +661,16 @@
 	  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 +794,12 @@
 	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 +916,8 @@
 
 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 --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index af79d47..81e38cb 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -22,10 +22,6 @@
 
 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
@@ -79,6 +75,7 @@
 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 +103,7 @@
 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 +122,6 @@
 
 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 +132,6 @@
 
 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 --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index 162fd5f..e41e4ad 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -122,6 +122,7 @@
 {
 	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 @@
 	}
 
 	/* 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 @@
 			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 @@
 					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 @@
 	}
 }
 
+/* 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 @@
 				    V4L2_FIELD_SEQ_TB,
 				    sizeof(struct au0828_buffer), fh, NULL);
 
-
 	return ret;
 }
 
@@ -987,11 +1047,19 @@
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 		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);
 	}
@@ -1723,15 +1809,6 @@
 	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;
-
-	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
-}
-#endif
-
 static struct v4l2_file_operations au0828_v4l_fops = {
 	.owner      = THIS_MODULE,
 	.open       = au0828_v4l2_open,
@@ -1775,9 +1852,6 @@
 	.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 +1914,14 @@
 	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 --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
index 9905bc4..9cde353 100644
--- a/drivers/media/video/au0828/au0828.h
+++ b/drivers/media/video/au0828/au0828.h
@@ -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 @@
 	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 --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
index 1a4a89f..7da5c2e 100644
--- a/drivers/media/video/bt8xx/Kconfig
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -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 --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 0902ec0..91399c9 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -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 @@
 	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 @@
 	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 @@
 	.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 @@
 {
 	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 @@
 
 	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 @@
 {
 	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 @@
 {
 	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 @@
 
 	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 @@
 			btv->field_count++;
 
 		if ((astat & BT848_INT_GPINT) && btv->remote) {
-			wake_up(&btv->gpioq);
 			bttv_input_irq(btv);
 		}
 
@@ -4284,7 +4258,6 @@
 	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 @@
 	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 @@
 
 	/* tell gpio modules we are leaving ... */
 	btv->shutdown=1;
-	wake_up(&btv->gpioq);
 	bttv_input_fini(btv);
 	bttv_sub_del_devices(&btv->c);
 
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 6bf05a7d..e8b64bc 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -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 @@
 
 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 @@
 		(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 @@
 			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 @@
 			(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 @@
 	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 @@
 	/* 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 @@
 		    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 @@
 		}
 		/* 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 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 @@
 		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 @@
 		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 @@
 		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 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 @@
 		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 @@
 	}
 
 	/* 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 @@
 		return;
 
 	bttv_ir_stop(btv);
-	ir_input_unregister(btv->remote->dev);
+	rc_unregister_device(btv->remote->dev);
 	kfree(btv->remote);
 	btv->remote = NULL;
 }
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index 6fd2a8e..fd62bf1 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -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>
 
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index d1e26a4..9b776fa 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -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 @@
 	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 @@
 /* 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_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 @@
 
 	/* infrared remote */
 	int has_remote;
-	struct card_ir *remote;
+	struct bttv_ir *remote;
 
 	/* I2C remote data */
 	struct IR_i2c_init_data    init_data;
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 0dfff50..789087c 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -859,8 +859,6 @@
 	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)
@@ -2196,12 +2194,13 @@
 		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 --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 46b433b..7edf80b 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -419,28 +419,6 @@
 
 /******************************************************************************
  *
- *  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
  *
  *****************************************************************************/
@@ -1380,17 +1358,6 @@
 		}
 		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 +1367,6 @@
 	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;
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
index 76c054d..d9d2f6a 100644
--- a/drivers/media/video/cx18/Kconfig
+++ b/drivers/media/video/cx18/Kconfig
@@ -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 --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index fe10909..8717773 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -39,7 +39,7 @@
 	.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. */
@@ -251,6 +251,66 @@
 
 /* ------------------------------------------------------------------------- */
 
+/* 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 +523,7 @@
 	&cx18_card_toshiba_qosmio_dvbt,
 	&cx18_card_leadtek_pvr2100,
 	&cx18_card_leadtek_dvr3100h,
+	&cx18_card_gotview_dvd3
 };
 
 const struct cx18_card *cx18_get_card(u16 index)
@@ -485,7 +546,6 @@
 		"Component 1"
 	};
 
-	memset(input, 0, sizeof(*input));
 	if (index >= cx->nof_inputs)
 		return -EINVAL;
 	input->index = index;
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 67043c7..97d7b7e 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -108,7 +108,7 @@
 					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 --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index df60f27..133ec2b 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -156,6 +156,7 @@
 		 "\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 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 +267,14 @@
 	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 */
@@ -333,6 +340,7 @@
 		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",
@@ -923,8 +931,13 @@
 	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;
 	}
@@ -1226,6 +1239,8 @@
 
 	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)
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 77be58c..f6f3e50 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -84,7 +84,8 @@
 #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_LAST		      8
 
 #define CX18_ENC_STREAM_TYPE_MPG  0
 #define CX18_ENC_STREAM_TYPE_TS   1
@@ -106,6 +107,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 +325,10 @@
 	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 +368,10 @@
 #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 +401,6 @@
 	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 {
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index 6d19f04..f0381d6 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -137,7 +137,7 @@
 {
 	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 +203,14 @@
 	.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.
@@ -247,6 +255,7 @@
 
 	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 +266,22 @@
 	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 +299,15 @@
 		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 +316,7 @@
 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 +325,9 @@
 	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 +381,7 @@
 
 	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 +408,16 @@
 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 +438,7 @@
  */
 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;
 
@@ -495,6 +510,29 @@
 				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,
+				.ctrl = NULL,
+			};
+			static struct xc2028_ctrl ctrl = {
+				.fname   = XC2028_DEFAULT_FIRMWARE,
+				.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;
 	default:
 		/* No Digital Tv Support */
 		break;
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index e71a026..c330fb9 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -98,7 +98,7 @@
 	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 --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 956aa19..c545f3b 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -136,7 +136,7 @@
 {
 	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 @@
 		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 @@
 	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 --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index ab461e2..94f5d79 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -107,6 +107,7 @@
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 	/* 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 --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
index 77412be..51765eb 100644
--- a/drivers/media/video/cx18/cx18-streams.h
+++ b/drivers/media/video/cx18/cx18-streams.h
@@ -33,7 +33,8 @@
 
 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);
 }
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig
index bb04914..ae85a7a 100644
--- a/drivers/media/video/cx231xx/Kconfig
+++ b/drivers/media/video/cx231xx/Kconfig
@@ -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 @@
 	  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 @@
 	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 --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile
index a6bc4cc..2c24843 100644
--- a/drivers/media/video/cx231xx/Makefile
+++ b/drivers/media/video/cx231xx/Makefile
@@ -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 --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/video/cx231xx/cx231xx-417.c
index 4c7cac3..fc9526a 100644
--- a/drivers/media/video/cx231xx/cx231xx-417.c
+++ b/drivers/media/video/cx231xx/cx231xx-417.c
@@ -940,14 +940,14 @@
 	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 --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c
index cf50faf..c53e972 100644
--- a/drivers/media/video/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/video/cx231xx/cx231xx-avcore.c
@@ -274,7 +274,7 @@
 
 	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 @@
 
 	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 @@
 	   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 @@
 	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 --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 2c78d18..588f3e8 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -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 @@
 			.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 @@
 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 @@
 	 .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 @@
 					       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 @@
 
 	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 @@
 	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 @@
 	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 @@
 	if (!dev->udev)
 		return;
 
+	flush_request_modules(dev);
+
 	/* delete v4l2 device */
 	v4l2_device_unregister(&dev->v4l2_dev);
 
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c
index 4af46fc..7d62d58 100644
--- a/drivers/media/video/cx231xx/cx231xx-core.c
+++ b/drivers/media/video/cx231xx/cx231xx-core.c
@@ -740,6 +740,7 @@
 		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 @@
 	/* 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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	if (saddr_len == 0)
 		saddr = 0;
-	else if (saddr_len == 0)
+	else if (saddr_len == 1)
 		saddr &= 0xff;
 
 	/* prepare xfer_data struct */
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c
index 5feb3ee..fe59a1c 100644
--- a/drivers/media/video/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/video/cx231xx/cx231xx-dvb.c
@@ -33,6 +33,7 @@
 #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 +89,11 @@
 		      .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 +141,17 @@
 	.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";
@@ -687,6 +704,29 @@
 			   &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 --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
new file mode 100644
index 0000000..45e14cac
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-input.c
@@ -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 --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index b13b69f..7e3e8c4 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -2044,15 +2044,6 @@
 	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 @@
 	.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 --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
index d067df9..72bbea2 100644
--- a/drivers/media/video/cx231xx/cx231xx.h
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -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 @@
 	/* 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_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_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 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 @@
 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 --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index e5c3c8d..103ef6b 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -853,9 +853,9 @@
 }
 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 @@
 	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 @@
 
 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 --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index e1367b3..6b4a516 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -5,7 +5,7 @@
 	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 --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c
index c95e7bc..209b971 100644
--- a/drivers/media/video/cx23885/cimax2.c
+++ b/drivers/media/video/cx23885/cimax2.c
@@ -368,7 +368,7 @@
 				DVB_CA_EN50221_POLL_CAM_READY;
 		else
 			state->status = 0;
-	};
+	}
 }
 
 /* CI irq handler */
@@ -377,16 +377,24 @@
 	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 --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 8861309..b298b73 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -309,6 +309,26 @@
 				  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 @@
 		.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 @@
 		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 @@
 		/* 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 @@
 	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 @@
 	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 --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index bb61870..199b996 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -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 @@
 		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 @@
 	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 @@
 		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 @@
 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 @@
 	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 @@
 				    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 @@
 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 @@
 
 	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 --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 8b2fb8a..644fcb8 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -1024,35 +1024,6 @@
 	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 @@
 	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 @@
 	.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 --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index ed94b17..62e41ab 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -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 @@
 	char			*name;
 	char			*phys;
 
-	struct input_dev	*inp_dev;
-	struct ir_dev_props	props;
+	struct rc_dev		*rc;
 };
 
 struct cx23885_dev {
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index e78e3e4..e37be6f 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -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 --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index dfb198d..f164618 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1989,8 +1989,23 @@
 	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
 			V4L2_CID_HUE, -128, 127, 1, 0);
 	if (!is_cx2583x(state)) {
-		default_volume = 228 - cx25840_read(client, 0x8d4);
-		default_volume = ((default_volume / 2) + 23) << 9;
+		default_volume = cx25840_read(client, 0x8d4);
+		/*
+		 * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume
+		 * scale mapping limits to avoid -ERANGE errors when
+		 * initializing the volume control
+		 */
+		if (default_volume > 228) {
+			/* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
+			default_volume = 228;
+			cx25840_write(client, 0x8d4, 228);
+		}
+		else if (default_volume < 20) {
+			/* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
+			default_volume = 20;
+			cx25840_write(client, 0x8d4, 20);
+		}
+		default_volume = (((228 - default_volume) >> 1) + 23) << 9;
 
 		state->volume = v4l2_ctrl_new_std(&state->hdl,
 			&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c
index 97a4e9b..627926f 100644
--- a/drivers/media/video/cx25840/cx25840-ir.c
+++ b/drivers/media/video/cx25840/cx25840-ir.c
@@ -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"
 
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 0fa85cb..5c42abd 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -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 --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 4aaa47c..54b7fcd 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -40,7 +40,6 @@
 #include <sound/control.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
-#include <media/wm8775.h>
 
 #include "cx88.h"
 #include "cx88-reg.h"
@@ -587,47 +586,26 @@
 	int left, right, v, b;
 	int changed = 0;
 	u32 old;
-	struct v4l2_control client_ctl;
-
-	/* Pass volume & balance onto any WM8775 */
-	if (value->value.integer.value[0] >= value->value.integer.value[1]) {
-		v = value->value.integer.value[0] << 10;
-		b = value->value.integer.value[0] ?
-			(0x8000 * value->value.integer.value[1]) / value->value.integer.value[0] :
-			0x8000;
-	} else {
-		v = value->value.integer.value[1] << 10;
-		b = value->value.integer.value[1] ?
-		0xffff - (0x8000 * value->value.integer.value[0]) / value->value.integer.value[1] :
-		0x8000;
-	}
-	client_ctl.value = v;
-	client_ctl.id = V4L2_CID_AUDIO_VOLUME;
-	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
-	client_ctl.value = b;
-	client_ctl.id = V4L2_CID_AUDIO_BALANCE;
-	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
 
 	left = value->value.integer.value[0] & 0x3f;
 	right = value->value.integer.value[1] & 0x3f;
 	b = right - left;
 	if (b < 0) {
-		v = 0x3f - left;
-		b = (-b) | 0x40;
+	    v = 0x3f - left;
+	    b = (-b) | 0x40;
 	} else {
-		v = 0x3f - right;
+	    v = 0x3f - right;
 	}
 	/* Do we really know this will always be called with IRQs on? */
 	spin_lock_irq(&chip->reg_lock);
 	old = cx_read(AUD_VOL_CTL);
 	if (v != (old & 0x3f)) {
-		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
-		changed = 1;
+	    cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
+	    changed = 1;
 	}
-	if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
-		cx_write(AUD_BAL_CTL, b);
-		changed = 1;
+	if (cx_read(AUD_BAL_CTL) != b) {
+	    cx_write(AUD_BAL_CTL, b);
+	    changed = 1;
 	}
 	spin_unlock_irq(&chip->reg_lock);
 
@@ -640,7 +618,7 @@
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-	.name = "Analog-TV Volume",
+	.name = "Playback Volume",
 	.info = snd_cx88_volume_info,
 	.get = snd_cx88_volume_get,
 	.put = snd_cx88_volume_put,
@@ -671,14 +649,7 @@
 	vol = cx_read(AUD_VOL_CTL);
 	if (value->value.integer.value[0] != !(vol & bit)) {
 		vol ^= bit;
-		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
-		/* Pass mute onto any WM8775 */
-		if ((1<<6) == bit) {
-			struct v4l2_control client_ctl;
-			client_ctl.value = 0 != (vol & bit);
-			client_ctl.id = V4L2_CID_AUDIO_MUTE;
-			call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-		}
+		cx_write(AUD_VOL_CTL, vol);
 		ret = 1;
 	}
 	spin_unlock_irq(&chip->reg_lock);
@@ -687,7 +658,7 @@
 
 static const struct snd_kcontrol_new snd_cx88_dac_switch = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Audio-Out Switch",
+	.name = "Playback Switch",
 	.info = snd_ctl_boolean_mono_info,
 	.get = snd_cx88_switch_get,
 	.put = snd_cx88_switch_put,
@@ -696,49 +667,13 @@
 
 static const struct snd_kcontrol_new snd_cx88_source_switch = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Analog-TV Switch",
+	.name = "Capture Switch",
 	.info = snd_ctl_boolean_mono_info,
 	.get = snd_cx88_switch_get,
 	.put = snd_cx88_switch_put,
 	.private_value = (1<<6),
 };
 
-static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *value)
-{
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-	struct cx88_core *core = chip->core;
-	struct v4l2_control client_ctl;
-
-	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
-	call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
-	value->value.integer.value[0] = client_ctl.value ? 1 : 0;
-
-	return 0;
-}
-
-static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *value)
-{
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-	struct cx88_core *core = chip->core;
-	struct v4l2_control client_ctl;
-
-	client_ctl.value = 0 != value->value.integer.value[0];
-	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
-	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
-	return 0;
-}
-
-static struct snd_kcontrol_new snd_cx88_alc_switch = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Line-In ALC Switch",
-	.info = snd_ctl_boolean_mono_info,
-	.get = snd_cx88_alc_get,
-	.put = snd_cx88_alc_put,
-};
-
 /****************************************************************************
 			Basic Flow for Sound Devices
  ****************************************************************************/
@@ -860,7 +795,6 @@
 {
 	struct snd_card  *card;
 	snd_cx88_card_t  *chip;
-	struct v4l2_subdev *sd;
 	int              err;
 
 	if (devno >= SNDRV_CARDS)
@@ -896,15 +830,6 @@
 	if (err < 0)
 		goto error;
 
-	/* If there's a wm8775 then add a Line-In ALC switch */
-	list_for_each_entry(sd, &chip->core->v4l2_dev.subdevs, list) {
-		if (WM8775_GID == sd->grp_id) {
-			snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch,
-						       chip));
-			break;
-		}
-	}
-
 	strcpy (card->driver, "CX88x");
 	sprintf(card->shortname, "Conexant CX%x", pci->device);
 	sprintf(card->longname, "%s at %#llx",
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index d7c9484..bca307e 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1064,7 +1064,7 @@
 		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 --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 9b9e169..4e6ee55 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -47,7 +47,7 @@
 
 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)
@@ -1007,15 +1007,22 @@
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.audio_chip = V4L2_IDENT_WM8775,
 		.input		= {{
 			.type	= CX88_VMUX_DVB,
 			.vmux	= 0,
+			/* 2: Line-In */
+			.audioroute = 2,
 		},{
 			.type	= CX88_VMUX_COMPOSITE1,
 			.vmux	= 1,
+			/* 2: Line-In */
+			.audioroute = 2,
 		},{
 			.type	= CX88_VMUX_SVIDEO,
 			.vmux	= 2,
+			/* 2: Line-In */
+			.audioroute = 2,
 		}},
 		.mpeg           = CX88_MPEG_DVB,
 	},
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 367a653f..90717ee 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -67,6 +67,10 @@
 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 @@
 	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 --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index f53836b..a1fe0ab 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -146,7 +146,6 @@
 	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 --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index fc777bc..06f7d1d 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -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 @@
 
 	/* sample from gpio pin 16 */
 	u32 sampling;
-	u32 samples[16];
-	int scount;
 
 	/* poll external decoder */
 	int polling;
@@ -63,6 +57,10 @@
 	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 @@
 #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 @@
 
 		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 @@
 	}
 	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 @@
 		__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 @@
 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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 		return 0;
 
 	cx88_ir_stop(core);
-	ir_input_unregister(ir->input);
+	rc_unregister_device(ir->dev);
 	kfree(ir);
 
 	/* done */
@@ -494,135 +502,75 @@
 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;
+
+	if (samples == 0xff && ir->dev->idle)
 		return;
+
+	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;
 	}
-	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 (ircode == 0) { /* key still pressed */
-			ir_dprintk("pulse distance decoded repeat code\n");
-			ir_repeat(ir->input);
-			break;
-		}
-
-		if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */
-			ir_dprintk("pulse distance decoded wrong address\n");
-			break;
-		}
-
-		if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */
-			ir_dprintk("pulse distance decoded wrong check sum\n");
-			break;
-		}
-
-		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;
-	}
-
-	ir->scount = 0;
-	return;
+	ir_raw_event_handle(ir->dev);
 }
 
+static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	int flags, code;
+
+	/* 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;
+
+	/* read actual key code */
+	code = i2c_smbus_read_byte_data(ir->c, 0x00);
+	if (code < 0) {
+		dprintk("read error\n");
+		return 0;
+	}
+
+	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 @@
 	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 @@
 			/* 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 --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index f7d71ac..addf954 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -66,8 +66,14 @@
 	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 @@
 
 	dprintk( 1, "%s\n", __func__);
 
+	flush_request_modules(dev);
+
 	if (!list_empty(&dev->drvlist)) {
 		struct cx8802_driver *drv, *tmp;
 		int err;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 62cea95..508dabbe 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -40,7 +40,6 @@
 #include "cx88.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
-#include <media/wm8775.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -977,7 +976,6 @@
 	const struct cx88_ctrl *c = NULL;
 	u32 value,mask;
 	int i;
-	struct v4l2_control client_ctl;
 
 	for (i = 0; i < CX8800_CTLS; i++) {
 		if (cx8800_ctls[i].v.id == ctl->id) {
@@ -991,27 +989,6 @@
 		ctl->value = c->v.minimum;
 	if (ctl->value > c->v.maximum)
 		ctl->value = c->v.maximum;
-
-	/* Pass changes onto any WM8775 */
-	client_ctl.id = ctl->id;
-	switch (ctl->id) {
-	case V4L2_CID_AUDIO_MUTE:
-		client_ctl.value = ctl->value;
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-		client_ctl.value = (ctl->value) ?
-			(0x90 + ctl->value) << 8 : 0;
-		break;
-	case V4L2_CID_AUDIO_BALANCE:
-		client_ctl.value = ctl->value << 9;
-		break;
-	default:
-		client_ctl.id = 0;
-		break;
-	}
-	if (client_ctl.id)
-		call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
 	mask=c->mask;
 	switch (ctl->id) {
 	case V4L2_CID_AUDIO_BALANCE:
@@ -1179,15 +1156,6 @@
 	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;
@@ -1558,9 +1526,7 @@
 	if (c->id <  V4L2_CID_BASE ||
 		c->id >= V4L2_CID_LASTP1)
 		return -EINVAL;
-	if (c->id == V4L2_CID_AUDIO_MUTE ||
-		c->id == V4L2_CID_AUDIO_VOLUME ||
-		c->id == V4L2_CID_AUDIO_BALANCE) {
+	if (c->id == V4L2_CID_AUDIO_MUTE) {
 		for (i = 0; i < CX8800_CTLS; i++) {
 			if (cx8800_ctls[i].v.id == c->id)
 				break;
@@ -1731,9 +1697,6 @@
 	.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 --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index ec5476d..d77f8ec 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -125,7 +125,6 @@
 	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 --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index e8c732e..c9981e7 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -398,19 +398,17 @@
 	return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
 }
 
-#define call_hw(core, grpid, o, f, args...) \
+#define call_all(core, o, f, args...) 				\
 	do {							\
 		if (!core->i2c_rc) {				\
 			if (core->gate_ctrl)			\
 				core->gate_ctrl(core, 1);	\
-			v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
+			v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
 			if (core->gate_ctrl)			\
 				core->gate_ctrl(core, 0);	\
 		}						\
 	} while (0)
 
-#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
-
 struct cx8800_dev;
 struct cx8802_dev;
 
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
index 7333a9b..353eada 100644
--- a/drivers/media/video/davinci/vpfe_capture.c
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -1276,7 +1276,7 @@
 		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 --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 66aefd6..985100e 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -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 @@
 	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 --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index f7e9168..099d5df 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -268,6 +268,20 @@
 };
 
 
+/* 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 +1238,19 @@
 			.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 +1496,7 @@
 		} },
 	},
 	[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 +1660,11 @@
 		.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 +1781,8 @@
 			.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 +1820,7 @@
 	{ 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 +1902,7 @@
 	{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 */
@@ -2408,7 +2438,7 @@
 		dev->init_data.get_key = em28xx_get_key_em_haup;
 		dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
 	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 +2460,36 @@
 			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);
@@ -2632,8 +2690,14 @@
 	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 +2813,8 @@
 	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 +3124,8 @@
 
 	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 --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 3ac8d30..c7c04bf 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -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 @@
 	.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 @@
 
 	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 @@
 	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 --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 6759cd5..ba1ba86 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -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 {
 	struct em28xx *dev;
-	struct input_dev *input;
+	struct rc_dev *rc;
 	char name[32];
 	char phys[32];
 
@@ -75,10 +74,6 @@
 	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 @@
 			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 @@
 	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 @@
 	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_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 @@
 	}
 
 	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 @@
 	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 @@
 	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 @@
 {
 	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 --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c
index 7f1c4a2..2b4c9cb 100644
--- a/drivers/media/video/em28xx/em28xx-vbi.c
+++ b/drivers/media/video/em28xx/em28xx-vbi.c
@@ -23,6 +23,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/hardirq.h>
 #include <linux/init.h>
 
 #include "em28xx.h"
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 908e3bc..f34d524 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1434,7 +1434,7 @@
 
 	/* 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 @@
 			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 @@
 				      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 @@
 	.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 = {
@@ -2377,7 +2365,7 @@
 	.owner         = THIS_MODULE,
 	.open          = em28xx_v4l2_open,
 	.release       = em28xx_v4l2_close,
-	.ioctl	       = video_ioctl2,
+	.unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 6a75e6a..6f2795a 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -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 --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index bb16409..a982750 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -1610,6 +1610,7 @@
 	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 --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c
index b8faff2..e4bba88 100644
--- a/drivers/media/video/fsl-viu.c
+++ b/drivers/media/video/fsl-viu.c
@@ -194,6 +194,8 @@
 
 	/* decoder */
 	struct v4l2_subdev	*decoder;
+
+	v4l2_std_id		std;
 };
 
 struct viu_fh {
@@ -915,6 +917,8 @@
 	if (fh->type != i)
 		return -EINVAL;
 
+	viu_start_dma(fh->dev);
+
 	return videobuf_streamon(&fh->vb_vidq);
 }
 
@@ -927,20 +931,39 @@
 	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 @@
 
 	viu_stop_dma(dev);
 	videobuf_stop(&fh->vb_vidq);
+	videobuf_mmap_free(&fh->vb_vidq);
 
 	kfree(fh);
 
@@ -1397,7 +1421,9 @@
 	.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 --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c
index 9b12168..c1ae05f 100644
--- a/drivers/media/video/gspca/cpia1.c
+++ b/drivers/media/video/gspca/cpia1.c
@@ -37,7 +37,7 @@
 /* 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 @@
 		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 @@
 	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 @@
 	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)
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 8fe8fb4..4429700 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -55,7 +55,7 @@
 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, 11, 0)
 
 #ifdef GSPCA_DEBUG
 int gspca_debug = D_ERR | D_PROBE;
@@ -224,12 +224,12 @@
 		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 @@
 	}
 	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 @@
 			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",
@@ -652,16 +652,12 @@
 				   : 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 +672,11 @@
 			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 +753,7 @@
 			}
 		} 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 +775,7 @@
 
 	if (!gspca_dev->present) {
 		ret = -ENODEV;
-		goto out;
+		goto unlock;
 	}
 
 	/* reset the streaming variables */
@@ -802,8 +796,10 @@
 	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 +869,8 @@
 		}
 	}
 out:
+	gspca_input_create_urb(gspca_dev);
+unlock:
 	mutex_unlock(&gspca_dev->usb_lock);
 	return ret;
 }
@@ -1299,17 +1297,19 @@
 		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
@@ -1710,12 +1710,13 @@
 
 		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 +1741,13 @@
 
 		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;
 	}
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index d4d210b..97b77a2 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -62,7 +62,7 @@
 /* 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 @@
 				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 *);
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
index 8ded8b1..703d486 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -624,7 +624,7 @@
 
 	/* 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 --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 6cf6855..e1c3b93 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -75,14 +75,14 @@
 
 	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 @@
 	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 @@
 	    },
 	    .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 @@
 		.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 @@
 	},
 };
 
+/* 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 @@
 		.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 @@
 	#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,13 @@
 #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_UV_EN			0x1e
+#define R511_SNAP_OPTS			0x1f
 
 #define R511_DRAM_FLOW_CTL		0x20
 #define R511_FIFO_OPTS			0x31
@@ -466,13 +514,14 @@
 #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 +575,81 @@
 #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 +667,6 @@
 	 * "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 +699,7 @@
 	 *    COMI[0] "Exposure control"
 	 *                  =   0 (0x00) .......0 "Manual"
 	 */
-	{ 0x13, 0xC0 },
+	{ 0x13, 0xc0 },
 
 	/*
 	 * 09 COMC "Common Control C"
@@ -706,7 +755,7 @@
 	 *    COME[0] "Auto zero circuit select"
 	 *                  =   1 (0x01) .......1 "On"
 	 */
-	{ 0x0d, 0xA1 },
+	{ 0x0d, 0xa1 },
 
 	/*
 	 * 0E COMF "Common Control F"
@@ -770,7 +819,7 @@
 	 *    COMJ[0] "Reserved"
 	 *                  =   0 (0x00) .......0
 	 */
-	{ 0x14, 0xC6 },
+	{ 0x14, 0xc6 },
 
 	/*
 	 * 15 COMK "Common Control K"
@@ -876,7 +925,7 @@
 	 *    FVOPT[7:0] "Range"
 	 *                  =  31 (0x1F) 00011111
 	 */
-	{ 0x3c, 0x1F },
+	{ 0x3c, 0x1f },
 
 	/*
 	 * 44 Undocumented  =   0 (0x00) 00000000
@@ -925,7 +974,7 @@
 	 *    48[7:0] "It's a secret"
 	 *                  = 192 (0xC0) 11000000
 	 */
-	{ 0x48, 0xC0 },
+	{ 0x48, 0xc0 },
 
 	/*
 	 * 49 Undocumented  =  25 (0x19) 00011001
@@ -939,18 +988,18 @@
 	 *    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 +1007,21 @@
 	 *    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 +1061,7 @@
 	 *    VBLM[3:0] "Sensor current control"
 	 *                  =  10 (0x0A) ....1010
 	 */
-	{ 0x34, 0x5A },
+	{ 0x34, 0x5a },
 
 	/*
 	 * 3B FREFB "Internal Reference Adjustment"
@@ -1078,7 +1127,7 @@
 	 *    HREFST[7:0] "Horizontal window start, 8 MSBs"
 	 *                  =  31 (0x1F) 00011111
 	 */
-	{ 0x17, 0x1F },
+	{ 0x17, 0x1f },
 
 	/*
 	 * 18 HREFEND "Horizontal window end"
@@ -1086,7 +1135,7 @@
 	 *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
 	 *                  =  95 (0x5F) 01011111
 	 */
-	{ 0x18, 0x5F },
+	{ 0x18, 0x5f },
 
 	/*
 	 * 19 VSTRT "Vertical window start"
@@ -1126,7 +1175,7 @@
 	 *    COMA[1:0] "Vertical window start line control 2 LSBs"
 	 *                  =   2 (0x02) ......10
 	 */
-	{ 0x03, 0x4A },
+	{ 0x03, 0x4a },
 
 	/*
 	 * 11 CLKRC "Clock Rate Control"
@@ -1183,7 +1232,7 @@
 	 *    HREFST[7:0] "Horizontal window start, 8 MSBs"
 	 *                  =  31 (0x1F) 00011111
 	 */
-	{ 0x17, 0x1F },
+	{ 0x17, 0x1f },
 
 	/*
 	 * 18 HREFEND "Horizontal window end"
@@ -1191,7 +1240,7 @@
 	 *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
 	 *                  =  95 (0x5F) 01011111
 	 */
-	{ 0x18, 0x5F },
+	{ 0x18, 0x5f },
 
 	/*
 	 * 19 VSTRT "Vertical window start"
@@ -1231,7 +1280,7 @@
 	 *    COMA[1:0] "Vertical window start line control 2 LSBs"
 	 *                  =   2 (0x02) ......10
 	 */
-	{ 0x03, 0x4A },
+	{ 0x03, 0x4a },
 
 	/*
 	 * 02 RED "Red Gain Control"
@@ -1241,7 +1290,7 @@
 	 *    RED[6:0] "Value"
 	 *                  =  47 (0x2F) .0101111
 	 */
-	{ 0x02, 0xAF },
+	{ 0x02, 0xaf },
 
 	/*
 	 * 2D ADDVSL "VSYNC Pulse Width"
@@ -1249,7 +1298,7 @@
 	 *    ADDVSL[7:0] "VSYNC pulse width, LSB"
 	 *                  = 210 (0xD2) 11010010
 	 */
-	{ 0x2d, 0xD2 },
+	{ 0x2d, 0xd2 },
 
 	/*
 	 * 00 GAIN          =  24 (0x18) 00011000
@@ -1272,7 +1321,7 @@
 	 *    BLUE[6:0] "Value"
 	 *                  = 112 (0x70) .1110000
 	 */
-	{ 0x01, 0xF0 },
+	{ 0x01, 0xf0 },
 
 	/*
 	 * 10 AEC "Automatic Exposure Control"
@@ -1280,14 +1329,14 @@
 	 *    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 +1345,7 @@
 	{ 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 +1513,7 @@
 	{ 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 +1581,177 @@
 	{ 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 +1773,37 @@
 
 /* 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 +1812,10 @@
 	{ 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 },
@@ -1657,9 +1850,9 @@
 	{ 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 +1868,22 @@
 	{ 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 +2018,13 @@
 }
 
 /* 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 +2034,8 @@
 		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 +2046,8 @@
 		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 +2057,22 @@
 			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 +2093,37 @@
 
 	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 +2134,37 @@
  * 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 +2174,55 @@
 			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 +2246,7 @@
 	/* 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 +2259,7 @@
 			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 +2269,10 @@
 
 	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 +2282,24 @@
  * 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 +2309,102 @@
  * 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 +2440,99 @@
  * 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 +2545,16 @@
 		}
 
 		/* 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 +2562,40 @@
  * 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 +2605,13 @@
  ***************************************************************************/
 
 /* 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 +2627,15 @@
 		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 +2645,21 @@
 	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 +2669,15 @@
 	 * 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 +2697,19 @@
 		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 +2722,14 @@
 				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 +2737,11 @@
 		}
 	} 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 +2750,7 @@
 	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 +2781,11 @@
 		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 +2797,14 @@
 	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 +2839,7 @@
 	}
 }
 
-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 +2870,6 @@
 		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 +2879,18 @@
 
 	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 +2899,23 @@
 		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 +2961,27 @@
 
 	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;
+	write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
 
-	rc = ov51x_upload_quan_tables(sd);
-	if (rc < 0) {
-		PDEBUG(D_ERR, "Error uploading quantization tables");
-		return rc;
-	}
-
-	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 +3029,49 @@
 
 	/* 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;
-	}
+	ov51x_upload_quan_tables(sd);
 
-	rc = reg_w(sd, 0x2f, 0x80);
-	if (rc < 0)
-		return rc;
-
-	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 },
+		{ 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 +3085,92 @@
 
 	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 +3179,119 @@
 {
 	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 +3303,107 @@
 		} 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 +3414,8 @@
 	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 +3518,6 @@
 
 	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 +3527,7 @@
  *
  * 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 +3537,14 @@
 	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 +3578,7 @@
 	/* 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 +3641,8 @@
 	}
 
 	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 +3650,12 @@
  *
  * 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 +3678,7 @@
 	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 +3697,21 @@
 	};
 
 	/******** 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 +3807,16 @@
 		}
 		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 +3828,7 @@
 		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 +3852,7 @@
 		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 +3899,11 @@
 		/* 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 +3919,21 @@
 		}
 		/* 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 +3946,50 @@
 		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 +4036,7 @@
 		vwsbase = vwebase = 0x03;
 		break;
 	default:
-		return -EINVAL;
+		return;
 	}
 
 	switch (sd->sensor) {
@@ -3855,23 +4071,18 @@
 		}
 	}
 
-	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 +4091,46 @@
 	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 +4145,21 @@
 {
 	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 +4380,22 @@
 {
 	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 +4415,14 @@
 		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 +4431,64 @@
 {
 	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 +4501,7 @@
 		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 +4511,7 @@
 	    }
 	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 +4520,13 @@
 		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 +4535,18 @@
 {
 	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 +4570,10 @@
 	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 +4586,31 @@
 {
 	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;
 		}
@@ -4443,14 +4754,14 @@
 	{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 +4775,7 @@
 	{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 --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
index 88ef03f..0edf939 100644
--- a/drivers/media/video/gspca/ov534.c
+++ b/drivers/media/video/gspca/ov534.c
@@ -1243,34 +1243,26 @@
 }
 
 /* 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 +1271,6 @@
 	/* Return the actual framerate */
 	tpf->numerator = 1;
 	tpf->denominator = sd->frame_rate;
-
-	return 0;
 }
 
 /* sub-driver description */
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
index e831f0d2..c5244b4 100644
--- a/drivers/media/video/gspca/ov534_9.c
+++ b/drivers/media/video/gspca/ov534_9.c
@@ -945,7 +945,6 @@
 	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)
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index 15e97fa..96f9986 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -162,7 +162,7 @@
 	{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 @@
 
 	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]);
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
index 55fbea7..2700975 100644
--- a/drivers/media/video/gspca/pac7302.c
+++ b/drivers/media/video/gspca/pac7302.c
@@ -393,7 +393,7 @@
 
 static void reg_w_buf(struct gspca_dev *gspca_dev,
 		  __u8 index,
-		  const char *buffer, int len)
+		  const u8 *buffer, int len)
 {
 	int ret;
 
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index 7657b43..6820f5d 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -261,7 +261,7 @@
 
 static void reg_w_buf(struct gspca_dev *gspca_dev,
 		  __u8 index,
-		  const char *buffer, int len)
+		  const u8 *buffer, int len)
 {
 	int ret;
 
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index 6b155ae..cb08d00 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -33,6 +33,14 @@
 
 #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 @@
 		.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 @@
 		.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 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 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 @@
 {
 	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 @@
 	}
 	/* 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 @@
 		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 @@
 	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 @@
 	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;
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 706f96f..73504a3 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -56,6 +56,8 @@
 	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,14 +73,15 @@
 #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;
 };
 
@@ -303,14 +306,29 @@
 		.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,
+	0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
+};
+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},
@@ -340,7 +358,7 @@
 		 * 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
@@ -505,7 +523,7 @@
 	{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},
@@ -551,7 +569,8 @@
 };
 
 static struct sensor_data sensor_data[] = {
-SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
+SENS(initHv7131d, NULL, hv7131d_sensor_init, NULL, NULL, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
+SENS(initHv7131r, NULL, hv7131r_sensor_init, NULL, NULL, 0, NO_BRIGHTNESS|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),
@@ -701,7 +720,18 @@
 	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: {
 		__u8 i2c[] =
@@ -788,6 +818,23 @@
 	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
@@ -1177,13 +1224,10 @@
 	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,58 +1238,84 @@
 	 *	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);
-
-				if (sd->frames_to_drop) {
-					sd->frames_to_drop--;
-					pkt_type = DISCARD_PACKET;
-				}
-
-				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;
+	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;
+}
+
+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;
+
+	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) {
 		/* In raw mode we sometimes get some garbage after the frame
@@ -1259,6 +1329,33 @@
 	}
 
 	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)
@@ -1431,9 +1528,7 @@
 static const struct usb_device_id device_table[] __devinitconst = {
 	{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)},
@@ -1444,9 +1539,12 @@
 #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, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
 	{USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index e23de57..2d0bb17 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -1598,22 +1598,22 @@
 	}
 }
 
+/* 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]);
 }
@@ -2533,7 +2533,7 @@
 		init = om6802_sensor_param1;
 		if (!mode) {			/* if 640x480 */
 			reg17 &= ~MCK_SIZE_MASK;
-			reg17 |= 0x01;		/* clock / 4 */
+			reg17 |= 0x04;		/* clock / 4 */
 		}
 		break;
 	case SENSOR_OV7630:
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index ad73f48..3a162c6 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -597,7 +597,7 @@
 	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);
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
index c2e88b5..8ba1995 100644
--- a/drivers/media/video/gspca/sq905c.c
+++ b/drivers/media/video/gspca/sq905c.c
@@ -301,6 +301,7 @@
 static const __devinitdata 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 --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c
index 3e4b0b9..a4a9881 100644
--- a/drivers/media/video/gspca/sq930x.c
+++ b/drivers/media/video/gspca/sq930x.c
@@ -687,10 +687,19 @@
 		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 @@
  */
 
 	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 @@
 	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;
 }
 
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index 086de44..28ea417 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -263,7 +263,21 @@
 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 @@
 	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 @@
 		}
 
 		/* 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 @@
 	.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
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
index cf3d0cc..b538dce 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
@@ -146,6 +146,11 @@
 	.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 @@
 	.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 @@
 	{STV_REG04, 0x07},
 
 	{STV_SCAN_RATE, 0x20},
-	{STV_ISO_SIZE_L, 847},
 	{STV_Y_CTRL, 0x01},
 	{STV_X_CTRL, 0x0a}
 };
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
index 285221e..ac47b4c 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
@@ -208,11 +208,24 @@
 
 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 @@
 	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 --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
index 4de4fa5..757de24 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
@@ -138,6 +138,9 @@
 	.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 --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
index 934b9ce..fb229d8 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
@@ -53,6 +53,10 @@
 	/* 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 --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
index 3af5326..8a456de 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -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 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 @@
 			.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 @@
 			.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 @@
 			.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 @@
 		{ 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 @@
 		{ 0x150e, 0x8e },
 		{ 0x150f, 0x37 },
 		{ 0x15c0, 0x00 },
-		{ 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
 		{ 0x15c3, 0x08 },	/* 0x04/0x14 ... test pictures ??? */
 
 
@@ -235,26 +243,72 @@
 	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);
+static int setcontrast(struct sd *sd)
+{
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+
+	/* Val goes from 0 -> 15 */
+	return stv06xx_write_bridge(sd, 0x143a,
+			sensor_settings->ctrls[CONTRAST].val | 0xf0);
+}
+
+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 = stv06xx_write_bridge(sd, 0x050a, gain);
+	if (err < 0)
+		return err;
+
+	err = stv06xx_write_bridge(sd, 0x050b, gain);
+	if (err < 0)
+		return err;
+
+	/* 2 mystery writes */
+	err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
+	if (err < 0)
+		return err;
+
+	return stv06xx_write_bridge(sd, 0x050d, 0x01);
+}
+
+static int setexposure(struct sd *sd)
+{
+	struct st6422_settings *sensor_settings = sd->sensor_priv;
+	u16 expo;
+	int err;
+
+	expo = sensor_settings->ctrls[EXPOSURE].val;
+	err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
+	if (err < 0)
+		return err;
+
+	return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
+}
+
+static int st6422_start(struct sd *sd)
+{
+	int err;
+	struct cam *cam = &sd->gspca_dev.cam;
+
 	if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
 		err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
 	else
@@ -262,29 +316,25 @@
 	if (err < 0)
 		return err;
 
-	err = st6422_set_brightness(&sd->gspca_dev,
-				    sensor_settings[BRIGHTNESS_IDX]);
+	err = setbrightness(sd);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_contrast(&sd->gspca_dev,
-				  sensor_settings[CONTRAST_IDX]);
+	err = setcontrast(sd);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_exposure(&sd->gspca_dev,
-				  sensor_settings[EXPOSURE_IDX]);
+	err = setexposure(sd);
 	if (err < 0)
 		return err;
 
-	err = st6422_set_gain(&sd->gspca_dev,
-			      sensor_settings[GAIN_IDX]);
+	err = setgain(sd);
 	if (err < 0)
 		return err;
 
-	PDEBUG(D_STREAM, "Starting stream");
-
-	return 0;
+	/* commit settings */
+	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+	return (err < 0) ? err : 0;
 }
 
 static int st6422_stop(struct sd *sd)
@@ -294,159 +344,58 @@
 	return 0;
 }
 
-static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[BRIGHTNESS_IDX];
-
-	PDEBUG(D_V4L2, "Read brightness %d", *val);
-
-	return 0;
-}
-
-static int st6422_set_brightness(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[BRIGHTNESS_IDX] = val;
-
-	if (!gspca_dev->streaming)
-		return 0;
-
-	/* val goes from 0 -> 31 */
-	PDEBUG(D_V4L2, "Set brightness to %d", val);
-	err = stv06xx_write_bridge(sd, 0x1432, val);
-	if (err < 0)
-		return err;
+	err = setbrightness(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_contrast(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	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);
-
-	return 0;
-}
-
-static int st6422_set_contrast(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[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 = 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_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);
-
-	return 0;
-}
-
-static int st6422_set_gain(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;
 
-	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 = setgain(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)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	s32 *sensor_settings = sd->sensor_priv;
-
-	*val = sensor_settings[EXPOSURE_IDX];
-
-	PDEBUG(D_V4L2, "Read exposure %d", *val);
-
-	return 0;
-}
-
-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 --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
index b2d45fe..d7498e0 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
@@ -37,18 +37,11 @@
 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 --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
index b3b5508..7fe3587 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -197,6 +197,10 @@
 	.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 @@
 	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 @@
 	{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 --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index b45f4d0..8f0c331 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -487,7 +487,7 @@
 	{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 */
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
index d9e3c60..38c22f0 100644
--- a/drivers/media/video/gspca/tv8532.c
+++ b/drivers/media/video/gspca/tv8532.c
@@ -132,7 +132,7 @@
 #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
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index 38a6efe..9b2ae1b 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -47,24 +47,29 @@
 	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 @@
 };
 
 /* 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 @@
 	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)
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c
index 4066ac8..4a9e622 100644
--- a/drivers/media/video/gspca/w996Xcf.c
+++ b/drivers/media/video/gspca/w996Xcf.c
@@ -59,18 +59,21 @@
 		.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 @@
 			      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 @@
 
 	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 @@
 {
 	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 @@
 			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 @@
   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 @@
  * 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 @@
 	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 @@
 	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 @@
 	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 @@
 	data[2] |= (value & 0x01) ? 0x5400 : 0x0;
 	data[3] = 0xfe1d;
 
-	ret += w9968cf_write_fsb(sd, data);
+	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);
-
-	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 @@
 	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 @@
 	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;
+		      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 */
+	reg_w(sd, 0x00, 0xff00); /* power off */
+	reg_w(sd, 0x00, 0xbf10); /* power on */
 
-	ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */
-	ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
+	reg_w(sd, 0x03, 0x405d); /* DRAM timings */
+	reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
 
-	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, 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, 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, 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, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
-	ret += reg_w(sd, 0x33, y1 >> 16);    /* JPEG buf 0 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, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
-	ret += reg_w(sd, 0x35, y1 >> 16);    /* JPEG bug 1 high */
+	reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
+	reg_w(sd, 0x35, y1 >> 16);    /* JPEG bug 1 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 */
-
-	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 @@
 	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 @@
 	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 @@
 		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 @@
 
 	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 --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
index 8715577..5b5039a 100644
--- a/drivers/media/video/gspca/xirlink_cit.c
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -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 @@
 #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 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 @@
 	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 @@
 		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 @@
 	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_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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	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_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 @@
 		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 @@
 	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 @@
 		   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 @@
 	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 @@
 	.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,10 +3258,15 @@
 	.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 -- */
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index c7e1970..14b85d4 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -35,16 +35,23 @@
 #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 @@
 	SENSOR_ADCM2700,
 	SENSOR_CS2102,
 	SENSOR_CS2102K,
+	SENSOR_GC0303,
 	SENSOR_GC0305,
 	SENSOR_HDCS2020b,
 	SENSOR_HV7131B,
@@ -79,26 +87,17 @@
 	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 @@
 		.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 @@
 		.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 @@
 		.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 @@
 		.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 @@
 		.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 @@
 		.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 @@
 	{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_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_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 @@
 	{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_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_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_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_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_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 */
@@ -5833,12 +5820,13 @@
 		{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,
@@ -5854,7 +5842,6 @@
 		[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 @@
 		{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 @@
 		 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++) {
@@ -5994,6 +5981,10 @@
 		{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 +6045,10 @@
 		{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 +6057,14 @@
 	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 +6081,7 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 autoval;
 
-	if (sd->autogain)
+	if (sd->ctrls[AUTOGAIN].val)
 		autoval = 0x42;
 	else
 		autoval = 0x02;
@@ -6330,8 +6317,8 @@
 	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 +6379,7 @@
 	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 +6408,7 @@
 	/* 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 +6424,7 @@
 		[SENSOR_ADCM2700] =	4,
 		[SENSOR_CS2102] =	4,
 		[SENSOR_CS2102K] =	5,
+		[SENSOR_GC0303] =	3,
 		[SENSOR_GC0305] =	4,
 		[SENSOR_HDCS2020b] =	4,
 		[SENSOR_HV7131B] =	4,
@@ -6456,12 +6440,12 @@
 		[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 +6461,6 @@
 		[SENSOR_PB0330] =	1,
 		[SENSOR_PO2030] =	1,
 		[SENSOR_TAS5130C] =	1,
-		[SENSOR_TAS5130C_VF0250] = 1,
 	};
 
 	sensor = zcxx_probeSensor(gspca_dev);
@@ -6493,8 +6476,8 @@
 			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 +6564,14 @@
 			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 +6612,12 @@
 		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 +6637,8 @@
 			{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 +6669,6 @@
 			{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 +6693,7 @@
 	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) */
@@ -6843,114 +6827,6 @@
 	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)
 {
@@ -7045,8 +6921,8 @@
 	{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 +6942,8 @@
 	{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 --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index b70d6af..f7d1ee5 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -385,6 +385,11 @@
 		v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n");
 		goto error;
 	}
+
+	/* until i2c is working properly */
+	retval = 0; /* hdpvr_register_i2c_ir(dev); */
+	if (retval < 0)
+		v4l2_err(&dev->v4l2_dev, "registering i2c IR devices failed\n");
 #endif /* CONFIG_I2C */
 
 	/* let the user know what node this device is now attached to */
diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c
index 409de11..24966aa 100644
--- a/drivers/media/video/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c
@@ -4,6 +4,9 @@
  *
  * 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.
@@ -22,6 +25,56 @@
 #define REQTYPE_I2C_WRITE	0xb0
 #define REQTYPE_I2C_WRITE_STATT	0xd0
 
+#define Z8F0811_IR_TX_I2C_ADDR	0x70
+#define Z8F0811_IR_RX_I2C_ADDR	0x71
+
+static const u8 ir_i2c_addrs[] = {
+	Z8F0811_IR_TX_I2C_ADDR,
+	Z8F0811_IR_RX_I2C_ADDR,
+};
+
+static const char * const ir_devicenames[] = {
+	"ir_tx_z8f0811_hdpvr",
+	"ir_rx_z8f0811_hdpvr",
+};
+
+static int hdpvr_new_i2c_ir(struct hdpvr_device *dev, struct i2c_adapter *adap,
+			    const char *type, u8 addr)
+{
+	struct i2c_board_info info;
+	struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
+	unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, type, I2C_NAME_SIZE);
+
+	/* Our default information for ir-kbd-i2c.c to use */
+	switch (addr) {
+	case Z8F0811_IR_RX_I2C_ADDR:
+		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";
+		info.platform_data = init_data;
+		break;
+	}
+
+	return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
+	       -1 : 0;
+}
+
+int hdpvr_register_i2c_ir(struct hdpvr_device *dev)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < ARRAY_SIZE(ir_i2c_addrs); i++)
+		ret += hdpvr_new_i2c_ir(dev, dev->i2c_adapter,
+					ir_devicenames[i], ir_i2c_addrs[i]);
+
+	return ret;
+}
+
 static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr,
 			  char *data, int len)
 {
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h
index 5efc963..37f1e4c 100644
--- a/drivers/media/video/hdpvr/hdpvr.h
+++ b/drivers/media/video/hdpvr/hdpvr.h
@@ -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
@@ -109,6 +110,9 @@
 	/* I2C lock */
 	struct mutex		i2c_mutex;
 
+	/* 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;
 	u8			*usbc_buf;
@@ -306,6 +310,8 @@
 /* i2c adapter registration */
 int hdpvr_register_i2c_adapter(struct hdpvr_device *dev);
 
+int hdpvr_register_i2c_ir(struct hdpvr_device *dev);
+
 /*========================================================================*/
 /* buffer management */
 int hdpvr_free_buffers(struct hdpvr_device *dev);
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
index 7ae9636..cdf8b19 100644
--- a/drivers/media/video/hexium_gemini.c
+++ b/drivers/media/video/hexium_gemini.c
@@ -37,15 +37,15 @@
 
 #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 --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index b72d0f0..6ad7e1c 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -38,15 +38,15 @@
 
 #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 --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c
index 27b5dfd..1a11691 100644
--- a/drivers/media/video/imx074.c
+++ b/drivers/media/video/imx074.c
@@ -467,7 +467,6 @@
 	icd->ops = NULL;
 	if (icl->free_bus)
 		icl->free_bus(icl);
-	client->driver = NULL;
 	kfree(priv);
 
 	return 0;
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index ce4a753..c87b6bc 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -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>
 
 /* ----------------------------------------------------------------------- */
@@ -252,7 +252,7 @@
 	}
 
 	if (rc)
-		ir_keydown(ir->input, ir_key, 0);
+		rc_keydown(ir->rc, ir_key, 0);
 }
 
 static void ir_work(struct work_struct *work)
@@ -269,22 +269,18 @@
 {
 	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 +288,7 @@
 	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 +296,7 @@
 	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,19 +306,19 @@
 	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;
 	}
@@ -333,9 +329,11 @@
 						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 +364,21 @@
 		}
 	}
 
+	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 +393,28 @@
 		 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 +423,8 @@
 	return 0;
 
  err_out_free:
+	/* Only frees rc if it were allocated internally */
+	rc_free_device(rc);
 	kfree(ir);
 	return err;
 }
@@ -414,7 +437,7 @@
 	cancel_delayed_work_sync(&ir->work);
 
 	/* unregister device */
-	ir_input_unregister(ir->input);
+	rc_unregister_device(ir->rc);
 
 	/* free memory */
 	kfree(ir);
@@ -426,6 +449,7 @@
 	{ "ir_video", 0 },
 	/* IR device specific entries should be added here */
 	{ "ir_rx_z8f0811_haup", 0 },
+	{ "ir_rx_z8f0811_hdpvr", 0 },
 	{ }
 };
 
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
index be4af1f..89f6591 100644
--- a/drivers/media/video/ivtv/Kconfig
+++ b/drivers/media/video/ivtv/Kconfig
@@ -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 --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c
index 87afbbe..145e474 100644
--- a/drivers/media/video/ivtv/ivtv-cards.c
+++ b/drivers/media/video/ivtv/ivtv-cards.c
@@ -405,7 +405,8 @@
 	.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 @@
 		"Composite 3"
 	};
 
-	memset(input, 0, sizeof(*input));
 	if (index >= itv->nof_inputs)
 		return -EINVAL;
 	input->index = index;
@@ -1331,7 +1331,6 @@
 {
 	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 --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
index 78eca992..e6f5c02 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
@@ -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 --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index e421d15..3994642 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -1029,8 +1029,13 @@
 	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 @@
 		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 @@
 	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 --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index d727485..c57a585 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -570,8 +570,8 @@
 		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 --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index 665191c..e103b8f 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -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 @@
 	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 @@
 	"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 @@
 		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,16 +208,23 @@
 		/* 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;
 	}
 
 	memset(&info, 0, sizeof(struct i2c_board_info));
@@ -218,8 +253,6 @@
 	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
 	};
 
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c
index e1c347e..2dfa957 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/drivers/media/video/ivtv/ivtv-vbi.c
@@ -92,52 +92,95 @@
 	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;
+
+	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;
+	} 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);
+		}
+	} 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);
+		}
+	}
+}
+
+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++) {
-		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 (copy_from_user(&d, sliced + i,
+				   sizeof(struct v4l2_sliced_vbi_data))) {
+			ret = -EFAULT;
+			break;
 		}
-		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);
-			}
-		}
-		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);
-			}
-		}
+		ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
 	}
-	if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
-		vi->cc_payload[vi->cc_payload_idx++] = cc;
-		set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
-	}
+
+	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)
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h
index 970567b..166dd0b 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.h
+++ b/drivers/media/video/ivtv/ivtv-vbi.h
@@ -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 --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
index 3b19f5b..c179041 100644
--- a/drivers/media/video/mem2mem_testdev.c
+++ b/drivers/media/video/mem2mem_testdev.c
@@ -524,7 +524,6 @@
 {
 	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 @@
 	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 @@
 		"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 @@
 		       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 @@
 	.open		= m2mtest_open,
 	.release	= m2mtest_release,
 	.poll		= m2mtest_poll,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 	.mmap		= m2mtest_mmap,
 };
 
@@ -965,6 +961,7 @@
 	}
 
 	*vfd = m2mtest_videodev;
+	vfd->lock = &dev->dev_mutex;
 
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
 	if (ret) {
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index fcb4cd9..f7fc88d 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -798,7 +798,6 @@
 
 	icd->ops = NULL;
 	mt9m001_video_remove(icd);
-	client->driver = NULL;
 	kfree(mt9m001);
 
 	return 0;
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 525a16e..53fa2a7 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -1092,7 +1092,6 @@
 	struct soc_camera_device *icd = client->dev.platform_data;
 
 	icd->ops = NULL;
-	client->driver = NULL;
 	kfree(mt9m111);
 
 	return 0;
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 9bd44a8..7ce279c 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -896,7 +896,6 @@
 
 	if (icd)
 		icd->ops = NULL;
-	client->driver = NULL;
 	kfree(mt9t031);
 
 	return 0;
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index b96171c..6a784c8 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -930,7 +930,6 @@
 
 	icd->ops = NULL;
 	mt9v022_video_remove(icd);
-	client->driver = NULL;
 	kfree(mt9v022);
 
 	return 0;
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 5e486a8..bc0c23a 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -382,10 +382,9 @@
 	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 --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index 13565cb..4eab1c6 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -683,7 +683,8 @@
 
 	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 --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index aa871c2..b9cb4a4 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -443,7 +443,7 @@
 				       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 @@
 		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 --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index 4e8fd96..e8846a0 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -59,10 +59,10 @@
 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 --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 15f8793..83de97a 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -2230,7 +2230,6 @@
 
 	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 --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c
index cbfd07f..0a2fb2b 100644
--- a/drivers/media/video/omap1_camera.c
+++ b/drivers/media/video/omap1_camera.c
@@ -1365,12 +1365,12 @@
 		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 --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index 378b094..0175527 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1198,7 +1198,7 @@
 
 	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 @@
 
 	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 @@
 	 * 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 --git a/drivers/media/video/ov2640.c b/drivers/media/video/ov2640.c
new file mode 100644
index 0000000..0cea0cf
--- /dev/null
+++ b/drivers/media/video/ov2640.c
@@ -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 --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index a84b770..48895ef 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -600,7 +600,7 @@
 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 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_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_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 @@
 			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 @@
 			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_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 --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c
index 99e9e1d..53d88a2 100644
--- a/drivers/media/video/ov9640.c
+++ b/drivers/media/video/ov9640.c
@@ -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 @@
 /* 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_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_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_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_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 --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index 55ea914..7d5a713 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -203,7 +203,7 @@
 	*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 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 @@
 		*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 --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index cb4057b..ac94a8b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -115,7 +115,7 @@
 		} 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 */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 3d7e5aa..281806b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -647,7 +647,7 @@
 	if (ret) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 			   "device_register failed");
-		kfree(class_dev);
+		put_device(class_dev);
 		return;
 	}
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index aaafa03..58617fc 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -852,8 +852,8 @@
 #endif
 
 	default :
-		ret = v4l_compat_translate_ioctl(file, cmd,
-						 arg, pvr2_v4l2_do_ioctl);
+		ret = -EINVAL;
+		break;
 	}
 
 	pvr2_hdw_commit_ctl(hdw);
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 6b8fbdd..1593f8d 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -1386,11 +1386,16 @@
 	{
 		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 --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index f3dc89d..bd1519a 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -287,14 +287,13 @@
 	/* 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 @@
 	/* 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 @@
 	/* 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 @@
 	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 @@
 	/* 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 @@
 		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 @@
 		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 @@
 {
 	struct video_device *vdev = file->private_data;
 	struct pwc_device *pdev;
+	int ret;
 
 	if (vdev == NULL)
 		return -EFAULT;
@@ -1402,6 +1371,13 @@
 	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 --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 7061a03f..8ca4d22 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -309,7 +309,10 @@
 	    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 @@
 			(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 @@
 
 
 	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 @@
 
 		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 --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 36a9c83..16bbc6d 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -275,7 +275,6 @@
 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 --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index c143ed0..0268677 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -852,7 +852,7 @@
 	 */
 	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 --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c
index d2fa2d4..57e11b6 100644
--- a/drivers/media/video/rj54n1cb0c.c
+++ b/drivers/media/video/rj54n1cb0c.c
@@ -1460,7 +1460,6 @@
 	icd->ops = NULL;
 	if (icl->free_bus)
 		icl->free_bus(icl);
-	client->driver = NULL;
 	kfree(rj54n1);
 
 	return 0;
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index a845753..b63f8ca 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -268,7 +268,7 @@
 	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;
@@ -780,20 +780,14 @@
 
 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 +805,8 @@
 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 +1097,6 @@
 	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 +1200,6 @@
 	__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 +1216,6 @@
 	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 +1240,6 @@
 	}
 	/* 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 +1250,11 @@
 	__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 +1274,6 @@
 	}
 	*pstatus = channel->vidstatus;
 	dprintk(4, "%s, vid status %d\n", __func__, *pstatus);
-	mutex_unlock(&dev->lock);
 	return res;
 }
 
@@ -1816,7 +1792,8 @@
 				    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 +1876,7 @@
 	.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 +1900,6 @@
 	.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 +1943,7 @@
 		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 +2650,9 @@
 	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 --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index bb99f2d..817aa66 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -543,7 +543,7 @@
 	unsigned long flags;
 	u32 ret;
 
-	if (WARN(!ctx, "null hardware context"))
+	if (WARN(!ctx, "null hardware context\n"))
 		return;
 
 	fimc = ctx->fimc_dev;
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index 984c0fe..99a2ac1 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -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 @@
 	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 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 --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 301c62b..f35459d 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1348,8 +1348,17 @@
 	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) {
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 3fe71be..380f1b2 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -26,7 +26,7 @@
 
 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 --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 1d4d0a4..e7aa588 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -5176,6 +5176,58 @@
 			.amux = 2,
 		},
 	},
+	[SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = {
+		.name           = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid",
+		.audio_clock    = 0x00187de7,
+#if 0
+	/*
+	 * FIXME: Analog mode doesn't work, if digital is enabled. The proper
+	 * fix is to use tda8290 driver, but Kworld seems to use an
+	 * unsupported version of tda8295.
+	 */
+		.tuner_type     = TUNER_NXP_TDA18271,	/* TUNER_PHILIPS_TDA8290 */
+		.tuner_addr     = 0x60,
+#else
+		.tuner_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+#endif
+		.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 +5538,37 @@
 			.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 +6698,12 @@
 	}, {
 		.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 +6762,12 @@
 		.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 +6926,23 @@
 	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:
+		saa7134_set_gpio(dev, 27, 0);
+		break;
+	case TDA18271_DIGITAL:
+		saa7134_set_gpio(dev, 27, 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev,
 					  int command, int arg)
 {
@@ -6843,6 +6955,9 @@
 		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 +6978,7 @@
 	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;
@@ -6967,6 +7083,7 @@
 	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 +7658,37 @@
 				       dev->name);
 		break;
 	}
+	case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+	{
+		struct i2c_msg msg = { .addr = 0x4b, .flags = 0 };
+		int i;
+		static u8 buffer[][2] = {
+			{0x30, 0x31},
+			{0xff, 0x00},
+			{0x41, 0x03},
+			{0x41, 0x1a},
+			{0xff, 0x02},
+			{0x34, 0x00},
+			{0x45, 0x97},
+			{0x45, 0xc1},
+		};
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
+
+		/*
+		 * FIXME: identify what device is at addr 0x4b and what means
+		 * this initialization
+		 */
+		for (i = 0; i < ARRAY_SIZE(buffer); i++) {
+			msg.buf = &buffer[i][0];
+			msg.len = ARRAY_SIZE(buffer[0]);
+			if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+				printk(KERN_WARNING
+				       "%s: Unable to enable tuner(%i).\n",
+				       dev->name, i);
+		}
+		break;
+	}
 	} /* switch() */
 
 	/* initialize tuner */
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 756a278..6abeecf 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -166,8 +166,14 @@
 	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 @@
 		}
 	}
 
-	request_submodules(dev);
-
 	v4l2_prio_init(&dev->prio);
 
 	mutex_lock(&saa7134_devlist_lock);
@@ -1066,6 +1070,7 @@
 	if (saa7134_dmasound_init && !dev->dmasound.priv_data)
 		saa7134_dmasound_init(dev);
 
+	request_submodules(dev);
 	return 0;
 
  fail4:
@@ -1091,6 +1096,8 @@
 	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 --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index beb95e2..3315a48 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -52,6 +52,7 @@
 #include "tda18271.h"
 #include "lgdt3305.h"
 #include "tda8290.h"
+#include "mb86a20s.h"
 
 #include "zl10353.h"
 
@@ -228,6 +229,20 @@
 	.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,
+};
+
+static const struct mb86a20s_config kworld_mb86a20s_config = {
+	.demod_address = 0x10,
+};
+
 /* ==================================================================
  * tda1004x based DVB-T cards, helper functions
  */
@@ -608,6 +623,37 @@
 
 /* ------------------------------------------------------------------ */
 
+static int __kworld_sbtvd_i2c_gate_ctrl(struct saa7134_dev *dev, int enable)
+{
+	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;
+}
+static int kworld_sbtvd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct saa7134_dev *dev = fe->dvb->priv;
+
+	return __kworld_sbtvd_i2c_gate_ctrl(dev, enable);
+}
+
+/* ------------------------------------------------------------------ */
+
 static struct tda1004x_config tda827x_lifeview_config = {
 	.demod_address = 0x08,
 	.invert        = 1,
@@ -1613,6 +1659,29 @@
 				   &dtv1000s_tda18271_config);
 		}
 		break;
+	case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+		__kworld_sbtvd_i2c_gate_ctrl(dev, 0);
+		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(20);
+		fe0->dvb.frontend = dvb_attach(mb86a20s_attach,
+					       &kworld_mb86a20s_config,
+					       &dev->i2c_adap);
+		__kworld_sbtvd_i2c_gate_ctrl(dev, 1);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_adap,
+				   &kworld_tda18271_config);
+			/*
+			 * Only after success, it can initialize the gate, otherwise
+			 * an OOPS will hit, due to kfree(fe0->dvb.frontend)
+			 */
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_i2c_gate_ctrl;
+		}
+		break;
 	default:
 		wprintk("Huh? unknown DVB card?\n");
 		break;
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index b890aaf..6b8459c7 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -553,7 +553,7 @@
 
 	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 --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 46d31df..dc646e6 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -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 @@
 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 @@
 	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 @@
 		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 @@
 
 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 @@
 	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 @@
 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 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 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 @@
 		__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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 	}
 
 	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 @@
 	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;
+		rc->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;
-
-	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 @@
 		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_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 @@
 		   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 @@
 		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 @@
 
 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 @@
 	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 @@
 	 */
 	if (!ir->active) {
 		timeout = jiffies + jiffies_to_msecs(15);
-		mod_timer(&ir->timer_end, timeout);
-		ir->active = 1;
+		mod_timer(&ir->timer, timeout);
+		ir->active = true;
 	}
 
 	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;
-	}
-
-	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 --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 3e7d2fd1..57e646b 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -550,16 +550,16 @@
 		} 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 --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index f0b1573..776ba2d 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -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 @@
 {
 	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 @@
 
 	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 @@
 {
 	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 @@
 {
 	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 @@
 		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 @@
 	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 @@
 	.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 --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index d3b6a19..5b0a347 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -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 @@
 	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 @@
 #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 @@
 
 	/* infrared remote */
 	int                        has_remote;
-	struct card_ir		   *remote;
+	struct saa7134_card_ir     *remote;
 
 	/* pci i/o */
 	char                       name[32];
diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c
index ad3bc41..bd86d97 100644
--- a/drivers/media/video/saa7164/saa7164-api.c
+++ b/drivers/media/video/saa7164/saa7164-api.c
@@ -40,9 +40,8 @@
 
 	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 @@
 
 		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 @@
 	/* 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 @@
 	/* 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 @@
 				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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 	} 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 @@
 		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 @@
 						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 @@
 					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 @@
 					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 @@
 				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 @@
 					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 @@
 					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 --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c
index 7230912..ddd2521 100644
--- a/drivers/media/video/saa7164/saa7164-buffer.c
+++ b/drivers/media/video/saa7164/saa7164-buffer.c
@@ -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 @@
 	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 @@
 	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 --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c
index 30d5283..b2b0d97 100644
--- a/drivers/media/video/saa7164/saa7164-bus.c
+++ b/drivers/media/video/saa7164/saa7164-bus.c
@@ -43,7 +43,8 @@
 
 	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_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 @@
  *  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 @@
 /*
  * 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 --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c
index 4cb634e..69822a4 100644
--- a/drivers/media/video/saa7164/saa7164-cards.c
+++ b/drivers/media/video/saa7164/saa7164-cards.c
@@ -482,7 +482,7 @@
 		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 --git a/drivers/media/video/saa7164/saa7164-cmd.c b/drivers/media/video/saa7164/saa7164-cmd.c
index 301a9e3..a97ae17 100644
--- a/drivers/media/video/saa7164/saa7164-cmd.c
+++ b/drivers/media/video/saa7164/saa7164-cmd.c
@@ -122,8 +122,8 @@
 				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 @@
 	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 @@
 			 * 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 --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c
index e1bac50..d6bf3f8 100644
--- a/drivers/media/video/saa7164/saa7164-core.c
+++ b/drivers/media/video/saa7164/saa7164-core.c
@@ -40,12 +40,12 @@
 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 @@
 
 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 @@
 		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 @@
 	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 @@
 					(*(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
 				}
 			}
 
@@ -961,9 +963,7 @@
 
 		/* 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 @@
 	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 @@
 	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 --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c
index cbb53d0..1838408 100644
--- a/drivers/media/video/saa7164/saa7164-encoder.c
+++ b/drivers/media/video/saa7164/saa7164-encoder.c
@@ -125,16 +125,22 @@
 
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 		}
 	}
 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 @@
 	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 --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c
index 484533c..ebed6f7 100644
--- a/drivers/media/video/saa7164/saa7164-fw.c
+++ b/drivers/media/video/saa7164/saa7164-fw.c
@@ -178,7 +178,7 @@
 			goto out;
 		}
 
-		msleep(10);
+		msleep(10); /* Checkpatch throws a < 20ms warning */
 		if (timeout++ > 60)
 			break;
 	}
@@ -235,7 +235,7 @@
 		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 @@
 			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 @@
 
 			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 @@
 	ret = 0;
 
 out:
-	if (fw)
-		release_firmware(fw);
-
+	release_firmware(fw);
 	return ret;
 }
diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c
index b5167d3..26148f7 100644
--- a/drivers/media/video/saa7164/saa7164-i2c.c
+++ b/drivers/media/video/saa7164/saa7164-i2c.c
@@ -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 @@
 	}
 	return num;
 
- err:
+err:
 	return retval;
 }
 
diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/video/saa7164/saa7164-vbi.c
index 323c7cd..8abbe6d 100644
--- a/drivers/media/video/saa7164/saa7164-vbi.c
+++ b/drivers/media/video/saa7164/saa7164-vbi.c
@@ -51,11 +51,15 @@
 	/* 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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 	.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 --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h
index 041ae8e..16745d2 100644
--- a/drivers/media/video/saa7164/saa7164.h
+++ b/drivers/media/video/saa7164/saa7164.h
@@ -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_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_tvnorm {
 	char		*name;
 	v4l2_std_id	id;
-//	u32		cxiformat;
-//	u32		cxoformat;
 };
 
 struct saa7164_encoder_params {
@@ -447,7 +442,7 @@
 	int	nr;
 	int	hwrevision;
 	u32	board;
-	char	name[32];
+	char	name[16];
 
 	/* firmware status */
 	struct saa7164_fw_status	fw_status;
@@ -510,7 +505,8 @@
 /* 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_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 --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h
deleted file mode 100644
index bf7d2e9..0000000
--- a/drivers/media/video/se401.h
+++ /dev/null
@@ -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 --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 2486520..954222b 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -1786,7 +1786,7 @@
 				       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 --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index f49fbfb..84984f6 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -2189,6 +2189,7 @@
 	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 --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index ccfa59c..41064c7 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -43,9 +43,7 @@
 #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 */
@@ -56,8 +54,8 @@
 #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), },
+#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), },
 #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 335120c..a66811b 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -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(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 @@
 		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 @@
 			},
 		};
 
-		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)
@@ -405,15 +443,13 @@
 		ret = soc_camera_set_fmt(icd, &f);
 		if (ret < 0)
 			goto esfmt;
+
+		ici->ops->init_videobuf(&icd->vb_vidq, icd);
 	}
 
 	file->private_data = icd;
 	dev_dbg(&icd->dev, "camera device open\n");
 
-	ici->ops->init_videobuf(&icd->vb_vidq, icd);
-
-	mutex_unlock(&icd->video_lock);
-
 	return 0;
 
 	/*
@@ -425,11 +461,9 @@
 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 @@
 	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 @@
 
 		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 @@
 	.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 @@
 	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 @@
 	if (!ret && !icd->streamer)
 		icd->streamer = file;
 
-unlock:
-	mutex_unlock(&icd->vb_vidq.vb_lock);
-
 	return ret;
 }
 
@@ -622,15 +646,11 @@
 	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 @@
 	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 @@
 
 	v4l2_subdev_call(sd, video, s_stream, 0);
 
-	mutex_unlock(&icd->video_lock);
-
 	return 0;
 }
 
@@ -748,9 +764,7 @@
 	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 @@
 	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 @@
 		ret = ici->ops->set_crop(icd, a);
 	}
 
-	mutex_unlock(&icd->vb_vidq.vb_lock);
-
 	return ret;
 }
 
@@ -941,14 +950,14 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 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 @@
 	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 @@
 	}
 	soc_camera_free_user_formats(icd);
 
+	regulator_bulk_free(icl->num_regulators, icl->regulators);
+
 	return 0;
 }
 
diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/video/sr030pc30.c
index c9dc67a..864696b 100644
--- a/drivers/media/video/sr030pc30.c
+++ b/drivers/media/video/sr030pc30.c
@@ -735,7 +735,7 @@
 	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;
 
 	/*
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index b5afe5f..d1a2cef 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -230,120 +230,6 @@
 		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 @@
 		.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 @@
 	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 @@
 	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 @@
 		goto error;
 	}
 
-	stk_create_sysfs_files(&dev->vdev);
-
 	return 0;
 
 error:
@@ -1411,7 +1324,6 @@
 	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 --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 3e99cea..19621ed5 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -148,7 +148,7 @@
 
 	/* 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 --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c
new file mode 100644
index 0000000..fc611eb
--- /dev/null
+++ b/drivers/media/video/timblogiw.c
@@ -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 --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig
index 1686ebf..645d915 100644
--- a/drivers/media/video/tlg2300/Kconfig
+++ b/drivers/media/video/tlg2300/Kconfig
@@ -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 --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
index c91424c..99c81a9 100644
--- a/drivers/media/video/tlg2300/pd-main.c
+++ b/drivers/media/video/tlg2300/pd-main.c
@@ -452,7 +452,8 @@
 
 	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 --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
deleted file mode 100644
index dfa7fc6..0000000
--- a/drivers/media/video/usbvideo/Kconfig
+++ /dev/null
@@ -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 --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile
deleted file mode 100644
index bb52eb8..0000000
--- a/drivers/media/video/usbvideo/Makefile
+++ /dev/null
@@ -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 --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
deleted file mode 100644
index b085496..0000000
--- a/drivers/media/video/usbvideo/ibmcam.c
+++ /dev/null
@@ -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 --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
deleted file mode 100644
index 562e1d1..0000000
--- a/drivers/media/video/usbvideo/konicawc.c
+++ /dev/null
@@ -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 --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
deleted file mode 100644
index fbd1b63..0000000
--- a/drivers/media/video/usbvideo/ultracam.c
+++ /dev/null
@@ -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 --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h
deleted file mode 100644
index c66985b..0000000
--- a/drivers/media/video/usbvideo/usbvideo.h
+++ /dev/null
@@ -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 --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
deleted file mode 100644
index dc17cce..0000000
--- a/drivers/media/video/usbvideo/vicam.c
+++ /dev/null
@@ -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 = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev);
-	if (err) {
-		printk(KERN_ERR "Failed to load \"vicam/firmware.fw\": %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");
-MODULE_FIRMWARE("vicam/firmware.fw");
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
index 503b13b..68b998b 100644
--- a/drivers/media/video/usbvision/usbvision-cards.c
+++ b/drivers/media/video/usbvision/usbvision-cards.c
@@ -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 --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index b9dd74f..c8feb0d 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -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 @@
 				__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 @@
  * 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 @@
 		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_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 @@
 	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 @@
 			     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 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 @@
 		       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_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 @@
 		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 @@
 	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 @@
 {
 	vfree(usbvision->scratch);
 	usbvision->scratch = NULL;
-
 }
 
 /*
@@ -420,13 +413,13 @@
 		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 @@
 		}
 	}
 
-	frame->grabstate = FrameState_Done;
+	frame->grabstate = frame_state_done;
 	frame->scanlength += scan_length;
 	++num_pass;
-
 }
 
 /*
@@ -487,8 +479,9 @@
 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 @@
  */
 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 @@
  *
  * 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 @@
 		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 @@
 	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;
+	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;
 
-	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;
+	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;
 
-	for (Idx = 0; Idx < Len; Idx++) {
-
-		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 (block_len > 0) {
+			if ((block_len % 4) == 0) {
+				block_byte = compressed[pos];
+				pos++;
 			}
-			if (BlockType == 1) { //inter Block
-				Integrator = Decompressed[Idx];
+			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;
 			}
-			switch (BlockByte & 0xC0) {
-				case 0x03<<6:
-					Integrator += Compressed[ExtraPos];
-					ExtraPos++;
-					break;
-				case 0x02<<6:
-					Integrator += BlockCode;
-					break;
-				case 0x00:
-					Integrator -= BlockCode;
-					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 @@
  * 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 @@
 #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 @@
  * 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 			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 @@
 
 			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 @@
 			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 @@
 			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 @@
 	*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 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 @@
 			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 @@
 		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 @@
 		 * 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 @@
 		/* 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 @@
 		}
 	}
 #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 @@
 		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 @@
 	/* 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 @@
 
 	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 @@
 
 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_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)
+	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 */
 			}
-			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
-			}
-			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 @@
 
 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 @@
 	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 @@
 		       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 @@
 		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 @@
 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 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 @@
 	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 @@
 	/* 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 @@
 		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 @@
 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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 		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 @@
 	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 @@
 		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 @@
 	}
 
 
-	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 @@
 
 	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 @@
 	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 @@
 		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 @@
 	/* 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 @@
 	}
 
 	/* 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 @@
 
 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 @@
  * 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 @@
  */
 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 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_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_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_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 @@
 
 	/* 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 @@
 				"%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 @@
 		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 @@
  */
 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 @@
 {
 	/* 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 --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 81dd53b..05b1344 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -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 @@
 		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 @@
 		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 @@
 		else
 			ret = try_write_address(i2c_adap, addr, retries);
 
-		if (ret != 1) {
+		if (ret != 1)
 			return -EREMOTEIO;
-		}
 	}
 	return 0;
 }
@@ -164,22 +163,20 @@
 		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 @@
 
 	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 @@
 	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 @@
 				"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 @@
 	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 @@
 
 	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 @@
 
 	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(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 --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 011c0c3..6083137 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -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 @@
 				__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 @@
 	{ 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 @@
 
 /* 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 @@
 /* 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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 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 @@
 	}
 
 	/* 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 @@
 		/* 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 @@
 	usbvision_empty_framequeues(usbvision);
 
 	PDEBUG(DBG_IO, "success");
-	mutex_unlock(&usbvision->lock);
-	return errCode;
+	return err_code;
 }
 
 /*
@@ -429,7 +428,6 @@
 	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 @@
 
 	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 @@
  *
  */
 #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 @@
 	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 @@
 
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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);
-
 	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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	/* 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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 	       (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 @@
 
 	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 @@
 	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 @@
 
 	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 @@
 		size -= PAGE_SIZE;
 	}
 
-	mutex_unlock(&usbvision->lock);
 	return 0;
 }
 
@@ -1154,21 +1124,18 @@
 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 @@
 		}
 
 		/* 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 @@
 	.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 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 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 @@
 	}
 
 	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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 		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 int __init usbvision_init(void)
 {
-	int errCode;
+	int err_code;
 
 	PDEBUG(DBG_PROBE, "");
 
@@ -1726,27 +1659,27 @@
 	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 --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index cc4e96c..8074787 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -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 @@
 };
 
 /* 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 @@
  * 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 @@
 	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 @@
 /* ----------------------------------------------------------------- */
 /* 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 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_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_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 @@
 #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 @@
 
 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 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 @@
 	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 @@
 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_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 --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 8cf61e8..9005a8d 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -1035,11 +1035,8 @@
 		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 --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
deleted file mode 100644
index d4ac751..0000000
--- a/drivers/media/video/v4l1-compat.c
+++ /dev/null
@@ -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 --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b5eb1f3..3f0871b 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -150,7 +150,7 @@
    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 @@
    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 @@
    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)
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index e30e8df..dc82eb8 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -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 @@
 		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 @@
 		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 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 @@
 
 	/* 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 @@
 	}
 
 	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 @@
 		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 @@
 		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 @@
 		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 --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 9d2502c..8f81efc 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -38,15 +38,15 @@
    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 @@
 		"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 @@
 		"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 @@
 		"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 @@
 		"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 @@
 		"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 @@
 		"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 @@
 		"Vivid",
 		NULL
 	};
-	static const char *tune_preemphasis[] = {
+	static const char * const tune_preemphasis[] = {
 		"No preemphasis",
 		"50 useconds",
 		"75 useconds",
@@ -952,7 +952,7 @@
 			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 @@
 
 	/* 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 @@
 	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 @@
 			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;
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index dd9283f..7e47f15 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -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 @@
 
 /* ------------------------------------------------------------------ */
 /* 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 @@
 	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 @@
 		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 @@
 
 	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:
 	{
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c
index 9eda7cc..e25aca5 100644
--- a/drivers/media/video/via-camera.c
+++ b/drivers/media/video/via-camera.c
@@ -1161,16 +1161,6 @@
 	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 +1241,6 @@
 	.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 --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index 8979f91..de4fa4e 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -1202,33 +1202,3 @@
 	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 --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
index 20f227e..ddb8f4b 100644
--- a/drivers/media/video/videobuf-dma-sg.c
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -69,10 +69,9 @@
 	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 @@
 
 	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 @@
 	}
 
 	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 --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 7e7eec4..d63e9d9 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -2954,9 +2954,6 @@
 	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 --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 9797e5a..c49c393 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -870,15 +870,6 @@
 				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 @@
 	.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 --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index 1355256..fe8ef64 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -35,7 +35,6 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-ctrls.h>
-#include <media/wm8775.h>
 
 MODULE_DESCRIPTION("wm8775 driver");
 MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
@@ -51,16 +50,10 @@
 	TOT_REGS
 };
 
-#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */
-#define ALC_EN 0x100  /* R17: ALC enable */
-
 struct wm8775_state {
 	struct v4l2_subdev sd;
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_ctrl *mute;
-	struct v4l2_ctrl *vol;
-	struct v4l2_ctrl *bal;
-	struct v4l2_ctrl *loud;
 	u8 input;		/* Last selected input (0-0xf) */
 };
 
@@ -92,30 +85,6 @@
 	return -1;
 }
 
-static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
-{
-	struct wm8775_state *state = to_state(sd);
-	u8 vol_l, vol_r;
-	int muted = 0 != state->mute->val;
-	u16 volume = (u16)state->vol->val;
-	u16 balance = (u16)state->bal->val;
-
-	/* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
-	vol_l = (min(65536 - balance, 32768) * volume) >> 23;
-	vol_r = (min(balance, (u16)32768) * volume) >> 23;
-
-	/* Mute */
-	if (muted || quietly)
-		wm8775_write(sd, R21, 0x0c0 | state->input);
-
-	wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
-	wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */
-
-	/* Un-mute */
-	if (!muted)
-		wm8775_write(sd, R21, state->input);
-}
-
 static int wm8775_s_routing(struct v4l2_subdev *sd,
 			    u32 input, u32 output, u32 config)
 {
@@ -133,26 +102,25 @@
 	state->input = input;
 	if (!v4l2_ctrl_g_ctrl(state->mute))
 		return 0;
-	if (!v4l2_ctrl_g_ctrl(state->vol))
-		return 0;
-	if (!v4l2_ctrl_g_ctrl(state->bal))
-		return 0;
-	wm8775_set_audio(sd, 1);
+	wm8775_write(sd, R21, 0x0c0);
+	wm8775_write(sd, R14, 0x1d4);
+	wm8775_write(sd, R15, 0x1d4);
+	wm8775_write(sd, R21, 0x100 + state->input);
 	return 0;
 }
 
 static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct wm8775_state *state = to_state(sd);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BALANCE:
-		wm8775_set_audio(sd, 0);
-		return 0;
-	case V4L2_CID_AUDIO_LOUDNESS:
-		wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD);
+		wm8775_write(sd, R21, 0x0c0);
+		wm8775_write(sd, R14, 0x1d4);
+		wm8775_write(sd, R15, 0x1d4);
+		if (!ctrl->val)
+			wm8775_write(sd, R21, 0x100 + state->input);
 		return 0;
 	}
 	return -EINVAL;
@@ -176,7 +144,16 @@
 
 static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
 {
-	wm8775_set_audio(sd, 0);
+	struct wm8775_state *state = to_state(sd);
+
+	/* If I remove this, then it can happen that I have no
+	   sound the first time I tune from static to a valid channel.
+	   It's difficult to reproduce and is almost certainly related
+	   to the zero cross detect circuit. */
+	wm8775_write(sd, R21, 0x0c0);
+	wm8775_write(sd, R14, 0x1d4);
+	wm8775_write(sd, R15, 0x1d4);
+	wm8775_write(sd, R21, 0x100 + state->input);
 	return 0;
 }
 
@@ -226,7 +203,6 @@
 {
 	struct wm8775_state *state;
 	struct v4l2_subdev *sd;
-	int err;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -240,21 +216,15 @@
 		return -ENOMEM;
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
-	sd->grp_id = WM8775_GID; /* subdev group id */
 	state->input = 2;
 
-	v4l2_ctrl_handler_init(&state->hdl, 4);
+	v4l2_ctrl_handler_init(&state->hdl, 1);
 	state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
 			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
-	state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
-			V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/
-	state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
-			V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768);
-	state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
-			V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);
 	sd->ctrl_handler = &state->hdl;
-	err = state->hdl.error;
-	if (err) {
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
 		v4l2_ctrl_handler_free(&state->hdl);
 		kfree(state);
 		return err;
@@ -266,25 +236,29 @@
 	wm8775_write(sd, R23, 0x000);
 	/* Disable zero cross detect timeout */
 	wm8775_write(sd, R7, 0x000);
-	/* HPF enable, I2S mode, 24-bit */
-	wm8775_write(sd, R11, 0x022);
+	/* Left justified, 24-bit mode */
+	wm8775_write(sd, R11, 0x021);
 	/* Master mode, clock ratio 256fs */
 	wm8775_write(sd, R12, 0x102);
 	/* Powered up */
 	wm8775_write(sd, R13, 0x000);
-	/* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */
-	wm8775_write(sd, R16, 0x1bb);
-	/* Set ALC mode and hold time */
-	wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD);
+	/* ADC gain +2.5dB, enable zero cross */
+	wm8775_write(sd, R14, 0x1d4);
+	/* ADC gain +2.5dB, enable zero cross */
+	wm8775_write(sd, R15, 0x1d4);
+	/* ALC Stereo, ALC target level -1dB FS max gain +8dB */
+	wm8775_write(sd, R16, 0x1bf);
+	/* Enable gain control, use zero cross detection,
+	   ALC hold time 42.6 ms */
+	wm8775_write(sd, R17, 0x185);
 	/* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */
 	wm8775_write(sd, R18, 0x0a2);
 	/* Enable noise gate, threshold -72dBfs */
 	wm8775_write(sd, R19, 0x005);
-	/* Transient window 4ms, ALC min gain -5dB  */
-	wm8775_write(sd, R20, 0x0fb);
-
-	wm8775_set_audio(sd, 1);      /* set volume/mute/mux */
-
+	/* Transient window 4ms, lower PGA gain limit -1dB */
+	wm8775_write(sd, R20, 0x07a);
+	/* LRBOTH = 1, use input 2. */
+	wm8775_write(sd, R21, 0x102);
 	return 0;
 }
 
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h
index 27f0555..4bb368e 100644
--- a/drivers/media/video/zoran/zoran.h
+++ b/drivers/media/video/zoran/zoran.h
@@ -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 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 @@
 #define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
 #define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
 
-#endif				/* __kernel__ */
-
 #endif
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
index e520abf..9cdc3bb 100644
--- a/drivers/media/video/zoran/zoran_card.c
+++ b/drivers/media/video/zoran/zoran_card.c
@@ -943,7 +943,7 @@
 	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",
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c
index b02007e..e8a2784 100644
--- a/drivers/media/video/zoran/zoran_device.c
+++ b/drivers/media/video/zoran/zoran_device.c
@@ -1523,7 +1523,7 @@
 		    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 --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index 67a52e8..7c3921d 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -1528,323 +1528,6 @@
  *   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 @@
 			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 @@
 
 	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 @@
 	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 @@
 	.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 --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3a1493b..da9d297 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -218,12 +218,12 @@
 		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
@@ -606,6 +606,16 @@
 	  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 --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f54b365..848e7ea 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -16,7 +16,7 @@
 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
@@ -81,3 +81,4 @@
 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
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index 4ba85bb..9cee8e7 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -1259,7 +1259,7 @@
 	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 @@
 	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 --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c
deleted file mode 100644
index e619e2a..0000000
--- a/drivers/mfd/tc35892.c
+++ /dev/null
@@ -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 --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
new file mode 100644
index 0000000..729dbee
--- /dev/null
+++ b/drivers/mfd/tc3589x.c
@@ -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 --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index 727f62c..6ad8a7f 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -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 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 @@
 	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 @@
 		.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 @@
 		.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 @@
 		.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 @@
 		.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 --git a/drivers/mfd/timberdale.h b/drivers/mfd/timberdale.h
index c11bf6e..4412acd 100644
--- a/drivers/mfd/timberdale.h
+++ b/drivers/mfd/timberdale.h
@@ -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 --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index d0016b6..90187fe 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -242,7 +242,7 @@
 	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 @@
 			&& (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 @@
 {
 	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 @@
 
 	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 @@
 	}
 	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 @@
 			&& 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 --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 35275ba..12abd5b 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -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 @@
 			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 @@
 		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);
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index aaedb11..06c8955 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -74,7 +74,7 @@
 	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 @@
 
 		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) {
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
new file mode 100644
index 0000000..d2ecc24
--- /dev/null
+++ b/drivers/mfd/wl1273-core.c
@@ -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 --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 1932066..668d41e 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -273,13 +273,11 @@
 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 @@
 	 * 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 @@
 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 --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 31ae07a..a3a780f 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1773,6 +1773,7 @@
 
 	case PM_POST_SUSPEND:
 	case PM_POST_HIBERNATION:
+	case PM_POST_RESTORE:
 
 		spin_lock_irqsave(&host->lock, flags);
 		host->rescan_disable = 0;
@@ -1789,7 +1790,7 @@
 {
 	int ret;
 
-	workqueue = create_singlethread_workqueue("kmmcd");
+	workqueue = alloc_ordered_workqueue("kmmcd", 0);
 	if (!workqueue)
 		return -ENOMEM;
 
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 591ab54..d3e6a96 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -69,6 +69,7 @@
 #include <linux/highmem.h>
 
 #include <linux/mmc/host.h>
+#include <linux/mmc/sdio.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -493,10 +494,14 @@
 		else if (data->flags & MMC_DATA_WRITE)
 			cmdr |= AT91_MCI_TRCMD_START;
 
-		if (data->flags & MMC_DATA_STREAM)
-			cmdr |= AT91_MCI_TRTYP_STREAM;
-		if (data->blocks > 1)
-			cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+		if (cmd->opcode == SD_IO_RW_EXTENDED) {
+			cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK;
+		} else {
+			if (data->flags & MMC_DATA_STREAM)
+				cmdr |= AT91_MCI_TRTYP_STREAM;
+			if (data->blocks > 1)
+				cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+		}
 	}
 	else {
 		block_length = 0;
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 301351a..ad2a7a0 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -26,6 +26,7 @@
 #include <linux/stat.h>
 
 #include <linux/mmc/host.h>
+#include <linux/mmc/sdio.h>
 
 #include <mach/atmel-mci.h>
 #include <linux/atmel-mci.h>
@@ -532,12 +533,17 @@
 	data = cmd->data;
 	if (data) {
 		cmdr |= MCI_CMDR_START_XFER;
-		if (data->flags & MMC_DATA_STREAM)
-			cmdr |= MCI_CMDR_STREAM;
-		else if (data->blocks > 1)
-			cmdr |= MCI_CMDR_MULTI_BLOCK;
-		else
-			cmdr |= MCI_CMDR_BLOCK;
+
+		if (cmd->opcode == SD_IO_RW_EXTENDED) {
+			cmdr |= MCI_CMDR_SDIO_BLOCK;
+		} else {
+			if (data->flags & MMC_DATA_STREAM)
+				cmdr |= MCI_CMDR_STREAM;
+			else if (data->blocks > 1)
+				cmdr |= MCI_CMDR_MULTI_BLOCK;
+			else
+				cmdr |= MCI_CMDR_BLOCK;
+		}
 
 		if (data->flags & MMC_DATA_READ)
 			cmdr |= MCI_CMDR_TRDIR_READ;
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 87b4fc6..5630228 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -19,6 +19,7 @@
 #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 +46,12 @@
  *	      is asserted (likewise for RX)
  * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
  *		  is asserted (likewise for RX)
+ * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware
+ *		and will not work at all.
+ * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when
+ *		using DMA.
+ * @sdio: variant supports SDIO
+ * @st_clkdiv: true if using a ST-specific clock divider algorithm
  */
 struct variant_data {
 	unsigned int		clkreg;
@@ -52,6 +59,10 @@
 	unsigned int		datalength_bits;
 	unsigned int		fifosize;
 	unsigned int		fifohalfsize;
+	bool			broken_blockend;
+	bool			broken_blockend_dma;
+	bool			sdio;
+	bool			st_clkdiv;
 };
 
 static struct variant_data variant_arm = {
@@ -65,6 +76,8 @@
 	.fifohalfsize		= 8 * 4,
 	.clkreg_enable		= 1 << 13, /* HWFCEN */
 	.datalength_bits	= 16,
+	.broken_blockend_dma	= true,
+	.sdio			= true,
 };
 
 static struct variant_data variant_ux500 = {
@@ -73,7 +86,11 @@
 	.clkreg			= MCI_CLK_ENABLE,
 	.clkreg_enable		= 1 << 14, /* HWFCEN */
 	.datalength_bits	= 24,
+	.broken_blockend	= true,
+	.sdio			= true,
+	.st_clkdiv		= true,
 };
+
 /*
  * This must be called with host->lock held
  */
@@ -86,7 +103,22 @@
 		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 +161,26 @@
 	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;
 }
 
@@ -162,6 +210,8 @@
 	host->data = data;
 	host->size = data->blksz * data->blocks;
 	host->data_xfered = 0;
+	host->blockend = false;
+	host->dataend = false;
 
 	mmci_init_sg(host, data);
 
@@ -196,9 +246,14 @@
 		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,20 +288,9 @@
 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
-	}
+	struct variant_data *variant = host->variant;
+
+	/* First check for errors */
 	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
 		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
 		if (status & MCI_DATACRCFAIL)
@@ -255,7 +299,10 @@
 			data->error = -ETIMEDOUT;
 		else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
 			data->error = -EIO;
-		status |= MCI_DATAEND;
+
+		/* Force-complete the transaction */
+		host->blockend = true;
+		host->dataend = true;
 
 		/*
 		 * We hit an error condition.  Ensure that any data
@@ -273,9 +320,64 @@
 			local_irq_restore(flags);
 		}
 	}
-	if (status & MCI_DATAEND) {
+
+	/*
+	 * On ARM variants in PIO mode, MCI_DATABLOCKEND
+	 * is always sent first, and we increase the
+	 * transfered number of bytes for that IRQ. Then
+	 * MCI_DATAEND follows and we conclude the transaction.
+	 *
+	 * On the Ux500 single-IRQ variant MCI_DATABLOCKEND
+	 * doesn't seem to immediately clear from the status,
+	 * so we can't use it keep count when only one irq is
+	 * used because the irq will hit for other reasons, and
+	 * then the flag is still up. So we use the MCI_DATAEND
+	 * IRQ at the end of the entire transfer because
+	 * MCI_DATABLOCKEND is broken.
+	 *
+	 * In the U300, the IRQs can arrive out-of-order,
+	 * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND,
+	 * so for this case we use the flags "blockend" and
+	 * "dataend" to make sure both IRQs have arrived before
+	 * concluding the transaction. (This does not apply
+	 * to the Ux500 which doesn't fire MCI_DATABLOCKEND
+	 * at all.) In DMA mode it suffers from the same problem
+	 * as the Ux500.
+	 */
+	if (status & MCI_DATABLOCKEND) {
+		/*
+		 * Just being a little over-cautious, we do not
+		 * use this progressive update if the hardware blockend
+		 * flag is unreliable: since it can stay high between
+		 * IRQs it will corrupt the transfer counter.
+		 */
+		if (!variant->broken_blockend)
+			host->data_xfered += data->blksz;
+		host->blockend = true;
+	}
+
+	if (status & MCI_DATAEND)
+		host->dataend = true;
+
+	/*
+	 * On variants with broken blockend we shall only wait for dataend,
+	 * on others we must sync with the blockend signal since they can
+	 * appear out-of-order.
+	 */
+	if (host->dataend && (host->blockend || variant->broken_blockend)) {
 		mmci_stop_data(host);
 
+		/* Reset these flags */
+		host->blockend = false;
+		host->dataend = false;
+
+		/*
+		 * Variants with broken blockend flags need to handle the
+		 * end of the entire transfer here.
+		 */
+		if (variant->broken_blockend && !data->error)
+			host->data_xfered += data->blksz * data->blocks;
+
 		if (!data->stop) {
 			mmci_request_end(host, data->mrq);
 		} else {
@@ -356,7 +458,32 @@
 			 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 +564,7 @@
 	 * "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 +573,7 @@
 	 * 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 +596,14 @@
 		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);
 
@@ -635,6 +770,7 @@
 	struct variant_data *variant = id->data;
 	struct mmci_host *host;
 	struct mmc_host *mmc;
+	unsigned int mask;
 	int ret;
 
 	/* must have platform data */
@@ -806,20 +942,30 @@
 	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);
+	mask = MCI_IRQENABLE;
+	/* Don't use the datablockend flag if it's broken */
+	if (variant->broken_blockend)
+		mask &= ~MCI_DATABLOCKEND;
+
+	writel(mask, 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 +1010,8 @@
 		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 --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 4ae887f..df06f01 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -139,6 +139,11 @@
 	MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|	\
 	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
 
+/* 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
 
 struct clk;
@@ -154,6 +159,7 @@
 	int			gpio_cd;
 	int			gpio_wp;
 	int			gpio_cd_irq;
+	bool			singleirq;
 
 	unsigned int		data_xfered;
 
@@ -171,6 +177,9 @@
 	struct timer_list	timer;
 	unsigned int		oldstat;
 
+	bool			blockend;
+	bool			dataend;
+
 	/* pio stuff */
 	struct sg_mapping_iter	sg_miter;
 	unsigned int		size;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 1290d14..5decfd0 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -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 @@
 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 @@
 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 @@
 }
 
 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 @@
 	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 @@
 	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)
@@ -424,6 +474,11 @@
 	      (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 +505,6 @@
 	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 +548,8 @@
 			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 +611,9 @@
 	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 +634,14 @@
 	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 +762,26 @@
 			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 +795,7 @@
 	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 +811,7 @@
 			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 +825,10 @@
 	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 +865,7 @@
 
 	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 +1190,9 @@
 	host->dmares = dmares;
 	spin_lock_init(&host->lock);
 
+	tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
+			(unsigned long)host);
+
 	/*
 	 * Setup DMA
 	 */
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index ff2b0f7..939557a 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -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_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 @@
 	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 @@
 	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 mmc_command	*cmd_cmd;
 	u32			cmd_c;
 
+	bool prog_scan;
+	bool prog_enable;
 };
 
 #endif
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 0c7e37f..379d2ff 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -173,6 +173,8 @@
 	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 @@
 		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 @@
 	}
 
 	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 @@
 		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 @@
 		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 @@
 
 	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 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 --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 5d46021..078fdf1 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2290,7 +2290,7 @@
 		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 --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index ddd09840..12884c2 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -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 @@
 	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 @@
 	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 @@
 		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 @@
 			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 @@
 	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 @@
 
 	/* 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 @@
 						     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 @@
 	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 @@
 	/* 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 @@
 
 	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 @@
 		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 @@
 			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 @@
 	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 @@
 		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 @@
 	int ret = 0, mask = 0;
 	u32 opc = cmd->opcode;
 
-	host->cmd = cmd;
-
 	switch (opc) {
 	/* respons busy check */
 	case MMC_SWITCH:
@@ -579,13 +722,12 @@
 	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 @@
 			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 @@
 	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 @@
 		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 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 @@
 		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 @@
 {
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	struct sh_mmcif_host *host = platform_get_drvdata(pdev);
 	int irq[2];
 
+	mmc_remove_host(host->mmc);
+	sh_mmcif_release_dma(host);
+
+	if (host->addr)
+		iounmap(host->addr);
+
 	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);
 
-	if (host->addr)
-		iounmap(host->addr);
-
-	platform_set_drvdata(pdev, NULL);
-	mmc_remove_host(host->mmc);
-
 	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_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 --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 4759d82..f511dd1 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1201,7 +1201,7 @@
 static void __exit cleanup_mtdchar(void)
 {
 	unregister_mtd_user(&mtdchar_notifier);
-	mntput(mtd_inode_mnt);
+	mntput_long(mtd_inode_mnt);
 	unregister_filesystem(&mtd_inodefs_type);
 	__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
 }
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 9f322f1..d0894ca7 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -721,6 +721,9 @@
 	case 3:
 		c->freq = 83;
 		break;
+	case 4:
+		c->freq = 104;
+		break;
 	}
 
 #ifdef CONFIG_MTD_PARTITIONS
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 3fda24a..5780dad 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1944,18 +1944,19 @@
 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)"
+	bool "Second FEC ethernet controller"
 	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.
+	  ethernet controller on some Motorola ColdFire and Freescale
+	  i.MX processors.
 
 config FEC_MPC52xx
 	tristate "MPC52xx FEC driver"
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 77d6c8d..6a858a2 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -636,6 +636,7 @@
 
 #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 */
diff --git a/drivers/net/bnx2x/bnx2x_dump.h b/drivers/net/bnx2x/bnx2x_dump.h
index dc18c25..fb3ff7c 100644
--- a/drivers/net/bnx2x/bnx2x_dump.h
+++ b/drivers/net/bnx2x/bnx2x_dump.h
@@ -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
 
 
+
+/*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 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_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)
+
 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
-
-#define RI_E1				0x1
-#define RI_E1H				0x2
-#define RI_E2			0x4
-#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
-
-
 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 @@
 	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 @@
 	{ 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 @@
 	{ 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 @@
 	{ 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 @@
 	{ 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 --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 99c672d..5b44a8b 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -24,6 +24,7 @@
 #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
@@ -472,7 +473,7 @@
 {
 	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++)
@@ -502,6 +503,15 @@
 			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);
@@ -539,6 +549,12 @@
 	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);
@@ -580,6 +596,10 @@
 
 		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
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h
index a9d5487..5a268e9 100644
--- a/drivers/net/bnx2x/bnx2x_init.h
+++ b/drivers/net/bnx2x/bnx2x_init.h
@@ -192,5 +192,225 @@
 	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, 0x3ffffff, 0x3ffffff, 0x3ffffff, 0x3ffffff),
+	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 --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 489a5512..84e1af4 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -3152,7 +3152,6 @@
 #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
@@ -3527,7 +3526,7 @@
 	   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);
@@ -4754,7 +4753,7 @@
 	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))
@@ -4808,53 +4807,9 @@
 	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 */
+	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);
-}
-
-
 static void bnx2x_reset_common(struct bnx2x *bp)
 {
 	/* reset_common */
@@ -5350,9 +5305,9 @@
 	/* 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 */
@@ -8751,13 +8706,6 @@
 		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;
 
@@ -9560,9 +9508,15 @@
 	/* 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);
 
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h
index bfd875b..38ef7ca 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/bnx2x/bnx2x_reg.h
@@ -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
@@ -2082,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
@@ -2091,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)
@@ -2446,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
@@ -2599,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
@@ -3001,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
@@ -3157,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 */
@@ -3442,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. */
@@ -3470,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
@@ -3596,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;
@@ -3755,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
@@ -3835,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
@@ -3914,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 */
@@ -4116,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;
@@ -4292,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
@@ -4421,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
@@ -4797,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
@@ -4929,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)
@@ -6316,3 +6389,4 @@
 }
 
 
+#endif /* BNX2X_REG_H */
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c
index 6e4d9b1..bda60d5 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/bnx2x/bnx2x_stats.c
@@ -158,6 +158,11 @@
 
 		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_eth_queue(bp, i)
diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c
index 32b1c6f..5f771ab 100644
--- a/drivers/net/caif/caif_shm_u5500.c
+++ b/drivers/net/caif/caif_shm_u5500.c
@@ -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 --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c
index 4c60285..a683fd3 100644
--- a/drivers/net/chelsio/my3126.c
+++ b/drivers/net/chelsio/my3126.c
@@ -22,7 +22,7 @@
 
 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 --git a/drivers/net/fec.c b/drivers/net/fec.c
index cce32d4..2a71373 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -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,41 @@
 
 #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 +147,8 @@
  * 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 +201,6 @@
 	int     mii_timeout;
 	uint    phy_speed;
 	phy_interface_t	phy_interface;
-	int	index;
 	int	link;
 	int	full_duplex;
 	struct	completion mdio_done;
@@ -213,10 +227,23 @@
 /* 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 +288,14 @@
 		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 +464,8 @@
 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 +529,9 @@
 	        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 +578,50 @@
 }
 
 /* ------------------------------------------------------------------------- */
-#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 +704,8 @@
 	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 +734,7 @@
 	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 +746,8 @@
 			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 +785,35 @@
 
 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 +850,10 @@
 	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 +1152,8 @@
  /*
   * 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 +1170,11 @@
 
 	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 +1225,25 @@
 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 +1290,45 @@
 	/* 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 +1423,7 @@
 	}
 	clk_enable(fep->clk);
 
-	ret = fec_enet_init(ndev, 0);
+	ret = fec_enet_init(ndev);
 	if (ret)
 		goto failed_init;
 
@@ -1380,8 +1487,10 @@
 
 	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 +1505,10 @@
 	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 +1525,13 @@
 
 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 --git a/drivers/net/fec.h b/drivers/net/fec.h
index 2c48b25..ace318d 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -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 --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 4e7d1d0..7d9ced0 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -396,7 +396,7 @@
 	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 @@
 	p->bitrate = bitrate;
 	p->next = yam_data;
 	yam_data = p;
-
+ out:
 	release_firmware(fw);
 	return p->bits;
 }
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 8f11d29..6d9275c 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -1279,7 +1279,7 @@
 	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 @@
 
 	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);
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 39996bf..7d85a38 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -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 @@
 	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 @@
 	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 @@
 	}
 
 	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 @@
 		le->length = cpu_to_be16(vlan_tx_tag_get(skb));
 		ctrl |= INS_VLAN;
 	}
-#endif
 
 	/* Handle TCP checksum offload */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -2432,11 +2420,8 @@
 	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",
@@ -2504,17 +2489,9 @@
 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
@@ -2631,7 +2608,6 @@
 				goto exit_loop;
 			break;
 
-#ifdef SKY2_VLAN_TAG_USED
 		case OP_RXVLAN:
 			sky2->rx_tag = length;
 			break;
@@ -2639,7 +2615,6 @@
 		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);
@@ -3042,6 +3017,10 @@
 			| 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:
@@ -3411,18 +3390,15 @@
 		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)
@@ -3436,9 +3412,11 @@
 	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;
@@ -3455,8 +3433,19 @@
 	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 {
@@ -3500,8 +3489,6 @@
 		sky2->flags &= ~SKY2_FLAG_AUTO_SPEED;
 	}
 
-	sky2->advertising = ecmd->advertising;
-
 	if (netif_running(dev)) {
 		sky2_phy_reinit(sky2);
 		sky2_set_multicast(dev);
@@ -4229,15 +4216,28 @@
 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;
 }
@@ -4273,6 +4273,7 @@
 	.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
@@ -4554,9 +4555,6 @@
 	.ndo_change_mtu		= sky2_change_mtu,
 	.ndo_tx_timeout		= sky2_tx_timeout,
 	.ndo_get_stats64	= sky2_get_stats,
-#ifdef SKY2_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= sky2_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= sky2_netpoll,
 #endif
@@ -4572,9 +4570,6 @@
 	.ndo_change_mtu		= sky2_change_mtu,
 	.ndo_tx_timeout		= sky2_tx_timeout,
 	.ndo_get_stats64	= sky2_get_stats,
-#ifdef SKY2_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= sky2_vlan_rx_register,
-#endif
   },
 };
 
@@ -4625,7 +4620,8 @@
 	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;
 
@@ -4633,13 +4629,8 @@
 	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);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 80bdc40..6861b0e 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -2236,11 +2236,8 @@
 	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;
@@ -2284,6 +2281,7 @@
 #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;
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 10e3ab3..298f2b0 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -514,7 +514,7 @@
 #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
 
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 43307bd..6107304 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1207,7 +1207,6 @@
 static void housekeeping_disable(struct zd_mac *mac)
 {
 	dev_dbg_f(zd_mac_dev(mac), "\n");
-	cancel_rearming_delayed_workqueue(zd_workqueue,
-		&mac->housekeeping.link_led_work);
+	cancel_delayed_work_sync(&mac->housekeeping.link_led_work);
 	zd_chip_control_leds(&mac->chip, ZD_LED_OFF);
 }
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 2574700..5f72262 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -115,7 +115,8 @@
 static int __init select_detection_mode(void)
 {
 	struct dummy_slot *slot, *tmp;
-	pcie_port_service_register(&dummy_driver);
+	if (pcie_port_service_register(&dummy_driver))
+		return PCIEHP_DETECT_ACPI;
 	pcie_port_service_unregister(&dummy_driver);
 	list_for_each_entry_safe(slot, tmp, &dummy_slots, list) {
 		list_del(&slot->list);
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index c80a7a6..de886f3 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -215,7 +215,8 @@
 	depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
 		    || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
 		    || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \
-		    || MACH_VPAC270 || MACH_BALLOON3)
+		    || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
+		    || MACH_COLIBRI320)
 	select PCMCIA_SOC_COMMON
 	help
 	  Say Y here to include support for the PXA2xx PCMCIA controller
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 8d9386a..29935ea 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -50,8 +50,9 @@
 sa1100_cs-y					+= sa1100_generic.o
 sa1100_cs-$(CONFIG_SA1100_ASSABET)		+= sa1100_assabet.o
 sa1100_cs-$(CONFIG_SA1100_CERF)			+= sa1100_cerf.o
-sa1100_cs-$(CONFIG_SA1100_COLLIE)              += pxa2xx_sharpsl.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE)		+= pxa2xx_sharpsl.o
 sa1100_cs-$(CONFIG_SA1100_H3600)		+= sa1100_h3600.o
+sa1100_cs-$(CONFIG_SA1100_NANOENGINE)		+= sa1100_nanoengine.o
 sa1100_cs-$(CONFIG_SA1100_SHANNON)		+= sa1100_shannon.o
 sa1100_cs-$(CONFIG_SA1100_SIMPAD)		+= sa1100_simpad.o
 
@@ -70,6 +71,8 @@
 pxa2xx-obj-$(CONFIG_MACH_STARGATE2)		+= pxa2xx_stargate2.o
 pxa2xx-obj-$(CONFIG_MACH_VPAC270)		+= pxa2xx_vpac270.o
 pxa2xx-obj-$(CONFIG_MACH_BALLOON3)		+= pxa2xx_balloon3.o
+pxa2xx-obj-$(CONFIG_MACH_COLIBRI)		+= pxa2xx_colibri.o
+pxa2xx-obj-$(CONFIG_MACH_COLIBRI320)		+= pxa2xx_colibri.o
 
 obj-$(CONFIG_PCMCIA_PXA2XX)			+= pxa2xx_base.o $(pxa2xx-obj-y)
 
diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c
index dbbdd00..453c54c 100644
--- a/drivers/pcmcia/pxa2xx_balloon3.c
+++ b/drivers/pcmcia/pxa2xx_balloon3.c
@@ -39,12 +39,10 @@
 static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	uint16_t ver;
-	int ret;
-	static void __iomem *fpga_ver;
 
 	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. "
 			"PCMCIA/CF support might be broken in this version!",
 			ver);
 
@@ -97,8 +95,9 @@
 static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				       const socket_state_t *state)
 {
-	__raw_writew((state->flags & SS_RESET) ? BALLOON3_CF_RESET : 0,
-			BALLOON3_CF_CONTROL_REG);
+	__raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG |
+			((state->flags & SS_RESET) ?
+			BALLOON3_FPGA_SETnCLR : 0));
 	return 0;
 }
 
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index ae07b4d..3755e7c 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 
 #include <mach/hardware.h>
+#include <mach/smemc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -116,37 +117,49 @@
 
 static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock )
 {
-	MCMEM(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+	uint32_t val;
+
+	val = ((pxa2xx_mcxx_setup(speed, clock)
 		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
 		| ((pxa2xx_mcxx_asst(speed, clock)
 		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
 		| ((pxa2xx_mcxx_hold(speed, clock)
 		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+	__raw_writel(val, MCMEM(sock));
+
 	return 0;
 }
 
 static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock )
 {
-	MCIO(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+	uint32_t val;
+
+	val = ((pxa2xx_mcxx_setup(speed, clock)
 		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
 		| ((pxa2xx_mcxx_asst(speed, clock)
 		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
 		| ((pxa2xx_mcxx_hold(speed, clock)
 		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+	__raw_writel(val, MCIO(sock));
+
 	return 0;
 }
 
 static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock )
 {
-	MCATT(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+	uint32_t val;
+
+	val = ((pxa2xx_mcxx_setup(speed, clock)
 		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
 		| ((pxa2xx_mcxx_asst(speed, clock)
 		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
 		| ((pxa2xx_mcxx_hold(speed, clock)
 		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
 
+	__raw_writel(val, MCATT(sock));
+
 	return 0;
 }
 
@@ -166,8 +179,8 @@
 
 static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
 {
-	unsigned int clk = get_memclk_frequency_10khz();
-	return pxa2xx_pcmcia_set_mcxx(skt, clk);
+	unsigned long clk = clk_get_rate(skt->clk);
+	return pxa2xx_pcmcia_set_mcxx(skt, clk / 10000);
 }
 
 #ifdef CONFIG_CPU_FREQ
@@ -205,19 +218,18 @@
 static void pxa2xx_configure_sockets(struct device *dev)
 {
 	struct pcmcia_low_level *ops = dev->platform_data;
-
 	/*
 	 * We have at least one socket, so set MECR:CIT
 	 * (Card Is There)
 	 */
-	MECR |= MECR_CIT;
+	uint32_t mecr = MECR_CIT;
 
 	/* Set MECR:NOS (Number Of Sockets) */
 	if ((ops->first + ops->nr) > 1 ||
 	    machine_is_viper() || machine_is_arcom_zeus())
-		MECR |= MECR_NOS;
-	else
-		MECR &= ~MECR_NOS;
+		mecr |= MECR_NOS;
+
+	__raw_writel(mecr, MECR);
 }
 
 static const char *skt_names[] = {
@@ -270,24 +282,41 @@
 	struct pcmcia_low_level *ops;
 	struct skt_dev_info *sinfo;
 	struct soc_pcmcia_socket *skt;
+	struct clk *clk;
 
 	ops = (struct pcmcia_low_level *)dev->dev.platform_data;
-	if (!ops)
+	if (!ops) {
+		ret = -ENODEV;
+		goto err0;
+	}
+
+	if (cpu_is_pxa320() && ops->nr > 1) {
+		dev_err(&dev->dev, "pxa320 supports only one pcmcia slot");
+		ret = -EINVAL;
+		goto err0;
+	}
+
+	clk = clk_get(&dev->dev, NULL);
+	if (!clk)
 		return -ENODEV;
 
 	pxa2xx_drv_pcmcia_ops(ops);
 
 	sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
-	if (!sinfo)
+	if (!sinfo) {
+		clk_put(clk);
 		return -ENOMEM;
+	}
 
 	sinfo->nskt = ops->nr;
+	sinfo->clk = clk;
 
 	/* Initialize processor specific parameters */
 	for (i = 0; i < ops->nr; i++) {
 		skt = &sinfo->skt[i];
 
 		skt->nr = ops->first + i;
+		skt->clk = clk;
 		skt->ops = ops;
 		skt->socket.owner = ops->owner;
 		skt->socket.dev.parent = &dev->dev;
@@ -295,18 +324,26 @@
 
 		ret = pxa2xx_drv_pcmcia_add_one(skt);
 		if (ret)
-			break;
+			goto err1;
 	}
 
 	if (ret) {
 		while (--i >= 0)
 			soc_pcmcia_remove_one(&sinfo->skt[i]);
 		kfree(sinfo);
+		clk_put(clk);
 	} else {
 		pxa2xx_configure_sockets(&dev->dev);
 		dev_set_drvdata(&dev->dev, sinfo);
 	}
 
+	return 0;
+
+err1:
+	while (--i >= 0)
+		soc_pcmcia_remove_one(&sinfo->skt[i]);
+	kfree(sinfo);
+err0:
 	return ret;
 }
 
@@ -320,6 +357,7 @@
 	for (i = 0; i < sinfo->nskt; i++)
 		soc_pcmcia_remove_one(&sinfo->skt[i]);
 
+	clk_put(sinfo->clk);
 	kfree(sinfo);
 	return 0;
 }
diff --git a/drivers/pcmcia/pxa2xx_colibri.c b/drivers/pcmcia/pxa2xx_colibri.c
new file mode 100644
index 0000000..c3f7219
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_colibri.c
@@ -0,0 +1,229 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_colibri.c
+ *
+ * Driver for Toradex Colibri PXA270 CF socket
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+
+#include "soc_common.h"
+
+#define	COLIBRI270_RESET_GPIO	53
+#define	COLIBRI270_PPEN_GPIO	107
+#define	COLIBRI270_BVD1_GPIO	83
+#define	COLIBRI270_BVD2_GPIO	82
+#define	COLIBRI270_DETECT_GPIO	84
+#define	COLIBRI270_READY_GPIO	1
+
+#define	COLIBRI320_RESET_GPIO	77
+#define	COLIBRI320_PPEN_GPIO	57
+#define	COLIBRI320_BVD1_GPIO	53
+#define	COLIBRI320_BVD2_GPIO	79
+#define	COLIBRI320_DETECT_GPIO	81
+#define	COLIBRI320_READY_GPIO	29
+
+static struct {
+	int	reset_gpio;
+	int	ppen_gpio;
+	int	bvd1_gpio;
+	int	bvd2_gpio;
+	int	detect_gpio;
+	int	ready_gpio;
+} colibri_pcmcia_gpio;
+
+static struct pcmcia_irqs colibri_irqs[] = {
+	{
+		.sock = 0,
+		.str  = "PCMCIA CD"
+	},
+};
+
+static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	int ret;
+
+	ret = gpio_request(colibri_pcmcia_gpio.detect_gpio, "DETECT");
+	if (ret)
+		goto err1;
+	ret = gpio_direction_input(colibri_pcmcia_gpio.detect_gpio);
+	if (ret)
+		goto err2;
+
+	ret = gpio_request(colibri_pcmcia_gpio.ready_gpio, "READY");
+	if (ret)
+		goto err2;
+	ret = gpio_direction_input(colibri_pcmcia_gpio.ready_gpio);
+	if (ret)
+		goto err3;
+
+	ret = gpio_request(colibri_pcmcia_gpio.bvd1_gpio, "BVD1");
+	if (ret)
+		goto err3;
+	ret = gpio_direction_input(colibri_pcmcia_gpio.bvd1_gpio);
+	if (ret)
+		goto err4;
+
+	ret = gpio_request(colibri_pcmcia_gpio.bvd2_gpio, "BVD2");
+	if (ret)
+		goto err4;
+	ret = gpio_direction_input(colibri_pcmcia_gpio.bvd2_gpio);
+	if (ret)
+		goto err5;
+
+	ret = gpio_request(colibri_pcmcia_gpio.ppen_gpio, "PPEN");
+	if (ret)
+		goto err5;
+	ret = gpio_direction_output(colibri_pcmcia_gpio.ppen_gpio, 0);
+	if (ret)
+		goto err6;
+
+	ret = gpio_request(colibri_pcmcia_gpio.reset_gpio, "RESET");
+	if (ret)
+		goto err6;
+	ret = gpio_direction_output(colibri_pcmcia_gpio.reset_gpio, 1);
+	if (ret)
+		goto err7;
+
+	colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpio.detect_gpio);
+	skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpio.ready_gpio);
+
+	return soc_pcmcia_request_irqs(skt, colibri_irqs,
+					ARRAY_SIZE(colibri_irqs));
+
+err7:
+	gpio_free(colibri_pcmcia_gpio.detect_gpio);
+err6:
+	gpio_free(colibri_pcmcia_gpio.ready_gpio);
+err5:
+	gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
+err4:
+	gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
+err3:
+	gpio_free(colibri_pcmcia_gpio.reset_gpio);
+err2:
+	gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+err1:
+	return ret;
+}
+
+static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	gpio_free(colibri_pcmcia_gpio.detect_gpio);
+	gpio_free(colibri_pcmcia_gpio.ready_gpio);
+	gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
+	gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
+	gpio_free(colibri_pcmcia_gpio.reset_gpio);
+	gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+}
+
+static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+					struct pcmcia_state *state)
+{
+
+	state->detect = !!gpio_get_value(colibri_pcmcia_gpio.detect_gpio);
+	state->ready  = !!gpio_get_value(colibri_pcmcia_gpio.ready_gpio);
+	state->bvd1   = !!gpio_get_value(colibri_pcmcia_gpio.bvd1_gpio);
+	state->bvd2   = !!gpio_get_value(colibri_pcmcia_gpio.bvd2_gpio);
+	state->wrprot = 0;
+	state->vs_3v  = 1;
+	state->vs_Xv  = 0;
+}
+
+static int
+colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+				const socket_state_t *state)
+{
+	gpio_set_value(colibri_pcmcia_gpio.ppen_gpio,
+			!(state->Vcc == 33 && state->Vpp < 50));
+	gpio_set_value(colibri_pcmcia_gpio.reset_gpio, state->flags & SS_RESET);
+	return 0;
+}
+
+static void colibri_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void colibri_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level colibri_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+
+	.first			= 0,
+	.nr			= 1,
+
+	.hw_init		= colibri_pcmcia_hw_init,
+	.hw_shutdown		= colibri_pcmcia_hw_shutdown,
+
+	.socket_state		= colibri_pcmcia_socket_state,
+	.configure_socket	= colibri_pcmcia_configure_socket,
+
+	.socket_init		= colibri_pcmcia_socket_init,
+	.socket_suspend		= colibri_pcmcia_socket_suspend,
+};
+
+static struct platform_device *colibri_pcmcia_device;
+
+static int __init colibri_pcmcia_init(void)
+{
+	int ret;
+
+	colibri_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+	if (!colibri_pcmcia_device)
+		return -ENOMEM;
+
+	/* Colibri PXA270 */
+	if (machine_is_colibri()) {
+		colibri_pcmcia_gpio.reset_gpio	= COLIBRI270_RESET_GPIO;
+		colibri_pcmcia_gpio.ppen_gpio	= COLIBRI270_PPEN_GPIO;
+		colibri_pcmcia_gpio.bvd1_gpio	= COLIBRI270_BVD1_GPIO;
+		colibri_pcmcia_gpio.bvd2_gpio	= COLIBRI270_BVD2_GPIO;
+		colibri_pcmcia_gpio.detect_gpio	= COLIBRI270_DETECT_GPIO;
+		colibri_pcmcia_gpio.ready_gpio	= COLIBRI270_READY_GPIO;
+	/* Colibri PXA320 */
+	} else if (machine_is_colibri320()) {
+		colibri_pcmcia_gpio.reset_gpio	= COLIBRI320_RESET_GPIO;
+		colibri_pcmcia_gpio.ppen_gpio	= COLIBRI320_PPEN_GPIO;
+		colibri_pcmcia_gpio.bvd1_gpio	= COLIBRI320_BVD1_GPIO;
+		colibri_pcmcia_gpio.bvd2_gpio	= COLIBRI320_BVD2_GPIO;
+		colibri_pcmcia_gpio.detect_gpio	= COLIBRI320_DETECT_GPIO;
+		colibri_pcmcia_gpio.ready_gpio	= COLIBRI320_READY_GPIO;
+	}
+
+	ret = platform_device_add_data(colibri_pcmcia_device,
+		&colibri_pcmcia_ops, sizeof(colibri_pcmcia_ops));
+
+	if (!ret)
+		ret = platform_device_add(colibri_pcmcia_device);
+
+	if (ret)
+		platform_device_put(colibri_pcmcia_device);
+
+	return ret;
+}
+
+static void __exit colibri_pcmcia_exit(void)
+{
+	platform_device_unregister(colibri_pcmcia_device);
+}
+
+module_init(colibri_pcmcia_init);
+module_exit(colibri_pcmcia_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PCMCIA support for Toradex Colibri PXA270/PXA320");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 6b22859..fb9740d 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -53,6 +53,9 @@
 #if defined(CONFIG_SA1100_H3100) || defined(CONFIG_SA1100_H3600)
 	pcmcia_h3600_init,
 #endif
+#ifdef CONFIG_SA1100_NANOENGINE
+	pcmcia_nanoengine_init,
+#endif
 #ifdef CONFIG_SA1100_SHANNON
 	pcmcia_shannon_init,
 #endif
diff --git a/drivers/pcmcia/sa1100_generic.h b/drivers/pcmcia/sa1100_generic.h
index 794f96a..adb08db 100644
--- a/drivers/pcmcia/sa1100_generic.h
+++ b/drivers/pcmcia/sa1100_generic.h
@@ -13,6 +13,7 @@
 extern int pcmcia_gcplus_init(struct device *);
 extern int pcmcia_graphicsmaster_init(struct device *);
 extern int pcmcia_h3600_init(struct device *);
+extern int pcmcia_nanoengine_init(struct device *);
 extern int pcmcia_pangolin_init(struct device *);
 extern int pcmcia_pfs168_init(struct device *);
 extern int pcmcia_shannon_init(struct device *);
diff --git a/drivers/pcmcia/sa1100_nanoengine.c b/drivers/pcmcia/sa1100_nanoengine.c
new file mode 100644
index 0000000..3d2652e
--- /dev/null
+++ b/drivers/pcmcia/sa1100_nanoengine.c
@@ -0,0 +1,219 @@
+/*
+ * drivers/pcmcia/sa1100_nanoengine.c
+ *
+ * PCMCIA implementation routines for BSI nanoEngine.
+ *
+ * In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
+ * board you should carefully read this:
+ * http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * Based on original work for kernel 2.4 by
+ * Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "sa1100_generic.h"
+
+static struct pcmcia_irqs irqs_skt0[] = {
+	/* socket, IRQ, name */
+	{ 0, NANOENGINE_IRQ_GPIO_PC_CD0, "PC CD0" },
+};
+
+static struct pcmcia_irqs irqs_skt1[] = {
+	/* socket, IRQ, name */
+	{ 1, NANOENGINE_IRQ_GPIO_PC_CD1, "PC CD1" },
+};
+
+struct nanoengine_pins {
+	unsigned input_pins;
+	unsigned output_pins;
+	unsigned clear_outputs;
+	unsigned transition_pins;
+	unsigned pci_irq;
+	struct pcmcia_irqs *pcmcia_irqs;
+	unsigned pcmcia_irqs_size;
+};
+
+static struct nanoengine_pins nano_skts[] = {
+	{
+		.input_pins		= GPIO_PC_READY0 | GPIO_PC_CD0,
+		.output_pins		= GPIO_PC_RESET0,
+		.clear_outputs		= GPIO_PC_RESET0,
+		.transition_pins	= NANOENGINE_IRQ_GPIO_PC_CD0,
+		.pci_irq		= NANOENGINE_IRQ_GPIO_PC_READY0,
+		.pcmcia_irqs		= irqs_skt0,
+		.pcmcia_irqs_size	= ARRAY_SIZE(irqs_skt0)
+	}, {
+		.input_pins		= GPIO_PC_READY1 | GPIO_PC_CD1,
+		.output_pins		= GPIO_PC_RESET1,
+		.clear_outputs		= GPIO_PC_RESET1,
+		.transition_pins	= NANOENGINE_IRQ_GPIO_PC_CD1,
+		.pci_irq		= NANOENGINE_IRQ_GPIO_PC_READY1,
+		.pcmcia_irqs		= irqs_skt1,
+		.pcmcia_irqs_size	= ARRAY_SIZE(irqs_skt1)
+	}
+};
+
+unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts);
+
+static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return -ENXIO;
+
+	GPDR &= ~nano_skts[i].input_pins;
+	GPDR |= nano_skts[i].output_pins;
+	GPCR = nano_skts[i].clear_outputs;
+	set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
+	skt->socket.pci_irq = nano_skts[i].pci_irq;
+
+	return soc_pcmcia_request_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Release all resources.
+ */
+static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	soc_pcmcia_free_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static int nanoengine_pcmcia_configure_socket(
+	struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+	unsigned reset;
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return -ENXIO;
+
+	switch (i) {
+	case 0:
+		reset = GPIO_PC_RESET0;
+		break;
+	case 1:
+		reset = GPIO_PC_RESET1;
+		break;
+	default:
+		return -ENXIO;
+	}
+
+	if (state->flags & SS_RESET)
+		GPSR = reset;
+	else
+		GPCR = reset;
+
+	return 0;
+}
+
+static void nanoengine_pcmcia_socket_state(
+	struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
+{
+	unsigned long levels = GPLR;
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	memset(state, 0, sizeof(struct pcmcia_state));
+	switch (i) {
+	case 0:
+		state->ready = (levels & GPIO_PC_READY0) ? 1 : 0;
+		state->detect = !(levels & GPIO_PC_CD0) ? 1 : 0;
+		break;
+	case 1:
+		state->ready = (levels & GPIO_PC_READY1) ? 1 : 0;
+		state->detect = !(levels & GPIO_PC_CD1) ? 1 : 0;
+		break;
+	default:
+		return;
+	}
+	state->bvd1 = 1;
+	state->bvd2 = 1;
+	state->wrprot = 0; /* Not available */
+	state->vs_3v = 1; /* Can only apply 3.3V */
+	state->vs_Xv = 0;
+}
+
+/*
+ * Enable card status IRQs on (re-)initialisation.  This can
+ * be called at initialisation, power management event, or
+ * pcmcia event.
+ */
+static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	soc_pcmcia_enable_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Disable card status IRQs on suspend.
+ */
+static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+	unsigned i = skt->nr;
+
+	if (i >= num_nano_pcmcia_sockets)
+		return;
+
+	soc_pcmcia_disable_irqs(skt,
+		nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static struct pcmcia_low_level nanoengine_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+
+	.hw_init		= nanoengine_pcmcia_hw_init,
+	.hw_shutdown		= nanoengine_pcmcia_hw_shutdown,
+
+	.configure_socket	= nanoengine_pcmcia_configure_socket,
+	.socket_state		= nanoengine_pcmcia_socket_state,
+	.socket_init		= nanoengine_pcmcia_socket_init,
+	.socket_suspend		= nanoengine_pcmcia_socket_suspend,
+};
+
+int pcmcia_nanoengine_init(struct device *dev)
+{
+	int ret = -ENODEV;
+
+	if (machine_is_nanoengine())
+		ret = sa11xx_drv_pcmcia_probe(
+			dev, &nanoengine_pcmcia_ops, 0, 2);
+
+	return ret;
+}
+
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 2fe8cb8..5a9a392 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -31,20 +31,20 @@
 ======================================================================*/
 
 
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
 #include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <linux/cpufreq.h>
+#include <linux/timer.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 #include "soc_common.h"
@@ -74,7 +74,8 @@
 
 #endif
 
-#define to_soc_pcmcia_socket(x)	container_of(x, struct soc_pcmcia_socket, socket)
+#define to_soc_pcmcia_socket(x)	\
+	container_of(x, struct soc_pcmcia_socket, socket)
 
 static unsigned short
 calc_speed(unsigned short *spds, int num, unsigned short dflt)
@@ -91,11 +92,15 @@
 	return speed;
 }
 
-void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing)
+void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
+	struct soc_pcmcia_timing *timing)
 {
-	timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
-	timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
-	timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+	timing->io =
+		calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
+	timing->mem =
+		calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+	timing->attr =
+		calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
 }
 EXPORT_SYMBOL(soc_common_pcmcia_get_timing);
 
@@ -137,8 +142,8 @@
  *
  * Convert PCMCIA socket state to our socket configure structure.
  */
-static int
-soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
+static int soc_common_pcmcia_config_skt(
+	struct soc_pcmcia_socket *skt, socket_state_t *state)
 {
 	int ret;
 
@@ -150,7 +155,8 @@
 		 */
 		if (skt->irq_state != 1 && state->io_irq) {
 			skt->irq_state = 1;
-			set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);
+			set_irq_type(skt->socket.pci_irq,
+				IRQ_TYPE_EDGE_FALLING);
 		} else if (skt->irq_state == 1 && state->io_irq == 0) {
 			skt->irq_state = 0;
 			set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
@@ -304,24 +310,24 @@
  * of power configuration, reset, &c. We also record the value of
  * `state' in order to regurgitate it to the PCMCIA core later.
  */
-static int
-soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int soc_common_pcmcia_set_socket(
+	struct pcmcia_socket *sock, socket_state_t *state)
 {
 	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 
-	debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
-			(state->csc_mask==0)?"<NONE> ":"",
-			(state->csc_mask&SS_DETECT)?"DETECT ":"",
-			(state->csc_mask&SS_READY)?"READY ":"",
-			(state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
-			(state->csc_mask&SS_BATWARN)?"BATWARN ":"",
-			(state->csc_mask&SS_STSCHG)?"STSCHG ":"",
-			(state->flags==0)?"<NONE> ":"",
-			(state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
-			(state->flags&SS_IOCARD)?"IOCARD ":"",
-			(state->flags&SS_RESET)?"RESET ":"",
-			(state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
-			(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+	debug(skt, 2, "mask: %s%s%s%s%s%s flags: %s%s%s%s%s%s Vcc %d Vpp %d irq %d\n",
+			(state->csc_mask == 0)		? "<NONE> " :	"",
+			(state->csc_mask & SS_DETECT)	? "DETECT " :	"",
+			(state->csc_mask & SS_READY)	? "READY " :	"",
+			(state->csc_mask & SS_BATDEAD)	? "BATDEAD " :	"",
+			(state->csc_mask & SS_BATWARN)	? "BATWARN " :	"",
+			(state->csc_mask & SS_STSCHG)	? "STSCHG " :	"",
+			(state->flags == 0)		? "<NONE> " :	"",
+			(state->flags & SS_PWR_AUTO)	? "PWR_AUTO " :	"",
+			(state->flags & SS_IOCARD)	? "IOCARD " :	"",
+			(state->flags & SS_RESET)	? "RESET " :	"",
+			(state->flags & SS_SPKR_ENA)	? "SPKR_ENA " :	"",
+			(state->flags & SS_OUTPUT_ENA)	? "OUTPUT_ENA " : "",
 			state->Vcc, state->Vpp, state->io_irq);
 
 	return soc_common_pcmcia_config_skt(skt, state);
@@ -336,8 +342,8 @@
  *
  * Returns: 0 on success, -1 on error
  */
-static int
-soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
+static int soc_common_pcmcia_set_io_map(
+	struct pcmcia_socket *sock, struct pccard_io_map *map)
 {
 	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 	unsigned short speed = map->speed;
@@ -346,14 +352,14 @@
 		map->map, map->speed, (unsigned long long)map->start,
 		(unsigned long long)map->stop);
 	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-		(map->flags==0)?"<NONE>":"",
-		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-		(map->flags&MAP_16BIT)?"16BIT ":"",
-		(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-		(map->flags&MAP_0WS)?"0WS ":"",
-		(map->flags&MAP_WRPROT)?"WRPROT ":"",
-		(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
-		(map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+		(map->flags == 0)		? "<NONE>"	: "",
+		(map->flags & MAP_ACTIVE)	? "ACTIVE "	: "",
+		(map->flags & MAP_16BIT)	? "16BIT "	: "",
+		(map->flags & MAP_AUTOSZ)	? "AUTOSZ "	: "",
+		(map->flags & MAP_0WS)		? "0WS "	: "",
+		(map->flags & MAP_WRPROT)	? "WRPROT "	: "",
+		(map->flags & MAP_USE_WAIT)	? "USE_WAIT "	: "",
+		(map->flags & MAP_PREFETCH)	? "PREFETCH "	: "");
 
 	if (map->map >= MAX_IO_WIN) {
 		printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
@@ -390,8 +396,8 @@
  *
  * Returns: 0 on success, -ERRNO on error
  */
-static int
-soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
+static int soc_common_pcmcia_set_mem_map(
+	struct pcmcia_socket *sock, struct pccard_mem_map *map)
 {
 	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 	struct resource *res;
@@ -400,14 +406,14 @@
 	debug(skt, 2, "map %u speed %u card_start %08x\n",
 		map->map, map->speed, map->card_start);
 	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-		(map->flags==0)?"<NONE>":"",
-		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-		(map->flags&MAP_16BIT)?"16BIT ":"",
-		(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-		(map->flags&MAP_0WS)?"0WS ":"",
-		(map->flags&MAP_WRPROT)?"WRPROT ":"",
-		(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
-		(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+		(map->flags == 0)		? "<NONE>"	: "",
+		(map->flags & MAP_ACTIVE)	? "ACTIVE "	: "",
+		(map->flags & MAP_16BIT)	? "16BIT "	: "",
+		(map->flags & MAP_AUTOSZ)	? "AUTOSZ "	: "",
+		(map->flags & MAP_0WS)		? "0WS "	: "",
+		(map->flags & MAP_WRPROT)	? "WRPROT "	: "",
+		(map->flags & MAP_ATTRIB)	? "ATTRIB "	: "",
+		(map->flags & MAP_USE_WAIT)	? "USE_WAIT "	: "");
 
 	if (map->map >= MAX_WIN)
 		return -EINVAL;
@@ -462,8 +468,8 @@
 	{ SS_OUTPUT_ENA,	"SS_OUTPUT_ENA"	},
 };
 
-static void
-dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
+static void dump_bits(char **p, const char *prefix,
+	unsigned int val, struct bittbl *bits, int sz)
 {
 	char *b = *p;
 	int i;
@@ -481,13 +487,14 @@
  *
  * Returns: the number of characters added to the buffer
  */
-static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_status(
+	struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct soc_pcmcia_socket *skt =
 		container_of(dev, struct soc_pcmcia_socket, socket.dev);
 	char *p = buf;
 
-	p+=sprintf(p, "slot     : %d\n", skt->nr);
+	p += sprintf(p, "slot     : %d\n", skt->nr);
 
 	dump_bits(&p, "status", skt->status,
 		  status_bits, ARRAY_SIZE(status_bits));
@@ -496,12 +503,12 @@
 	dump_bits(&p, "cs_flags", skt->cs_state.flags,
 		  conf_bits, ARRAY_SIZE(conf_bits));
 
-	p+=sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
-	p+=sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
-	p+=sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
+	p += sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
+	p += sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
+	p += sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
 		skt->socket.pci_irq);
 	if (skt->ops->show_timing)
-		p+=skt->ops->show_timing(skt, p);
+		p += skt->ops->show_timing(skt, p);
 
 	return p-buf;
 }
@@ -594,7 +601,7 @@
 
 	mutex_lock(&soc_pcmcia_sockets_lock);
 	list_for_each_entry(skt, &soc_pcmcia_sockets, node)
-		if ( skt->ops->frequency_change )
+		if (skt->ops->frequency_change)
 			ret += skt->ops->frequency_change(skt, val, freqs);
 	mutex_unlock(&soc_pcmcia_sockets_lock);
 
@@ -620,7 +627,8 @@
 
 static void soc_pcmcia_cpufreq_unregister(void)
 {
-	cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+	cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
+		CPUFREQ_TRANSITION_NOTIFIER);
 }
 module_exit(soc_pcmcia_cpufreq_unregister);
 
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h
index bbcd538..9daa736 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -10,6 +10,7 @@
 #define _ASM_ARCH_PCMCIA
 
 /* include the world */
+#include <linux/clk.h>
 #include <linux/cpufreq.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
@@ -29,6 +30,7 @@
 	 * Info from low level handler
 	 */
 	unsigned int		nr;
+	struct clk		*clk;
 
 	/*
 	 * Core PCMCIA state
@@ -56,6 +58,7 @@
 
 struct skt_dev_info {
 	int nskt;
+	struct clk *clk;
 	struct soc_pcmcia_socket skt[0];
 };
 
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index c44a5e8..f0b3ad1 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -75,6 +75,7 @@
 #include <drm/i915_drm.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include "intel_ips.h"
 
 #define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
 
@@ -245,6 +246,7 @@
 #define thm_writel(off, val) writel((val), ips->regmap + (off))
 
 static const int IPS_ADJUST_PERIOD = 5000; /* ms */
+static bool late_i915_load = false;
 
 /* For initial average collection */
 static const int IPS_SAMPLE_PERIOD = 200; /* ms */
@@ -339,6 +341,9 @@
 	u64 orig_turbo_ratios;
 };
 
+static bool
+ips_gpu_turbo_enabled(struct ips_driver *ips);
+
 /**
  * ips_cpu_busy - is CPU busy?
  * @ips: IPS driver struct
@@ -517,7 +522,7 @@
  */
 static bool ips_gpu_busy(struct ips_driver *ips)
 {
-	if (!ips->gpu_turbo_enabled)
+	if (!ips_gpu_turbo_enabled(ips))
 		return false;
 
 	return ips->gpu_busy();
@@ -532,7 +537,7 @@
  */
 static void ips_gpu_raise(struct ips_driver *ips)
 {
-	if (!ips->gpu_turbo_enabled)
+	if (!ips_gpu_turbo_enabled(ips))
 		return;
 
 	if (!ips->gpu_raise())
@@ -549,7 +554,7 @@
  */
 static void ips_gpu_lower(struct ips_driver *ips)
 {
-	if (!ips->gpu_turbo_enabled)
+	if (!ips_gpu_turbo_enabled(ips))
 		return;
 
 	if (!ips->gpu_lower())
@@ -1454,6 +1459,31 @@
 	return false;
 }
 
+static bool
+ips_gpu_turbo_enabled(struct ips_driver *ips)
+{
+	if (!ips->gpu_busy && late_i915_load) {
+		if (ips_get_i915_syms(ips)) {
+			dev_info(&ips->dev->dev,
+				 "i915 driver attached, reenabling gpu turbo\n");
+			ips->gpu_turbo_enabled = !(thm_readl(THM_HTS) & HTS_GTD_DIS);
+		}
+	}
+
+	return ips->gpu_turbo_enabled;
+}
+
+void
+ips_link_to_i915_driver()
+{
+	/* We can't cleanly get at the various ips_driver structs from
+	 * this caller (the i915 driver), so just set a flag saying
+	 * that it's time to try getting the symbols again.
+	 */
+	late_i915_load = true;
+}
+EXPORT_SYMBOL_GPL(ips_link_to_i915_driver);
+
 static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
 		     PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },
diff --git a/drivers/platform/x86/intel_ips.h b/drivers/platform/x86/intel_ips.h
new file mode 100644
index 0000000..73299be
--- /dev/null
+++ b/drivers/platform/x86/intel_ips.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 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".
+ */
+
+void ips_link_to_i915_driver(void);
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 41a9e34..ca35b0c 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -26,6 +26,7 @@
 #include <linux/sfi.h>
 #include <asm/mrst.h>
 #include <asm/intel_scu_ipc.h>
+#include <asm/mrst.h>
 
 /* IPC defines the following message types */
 #define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */
@@ -699,6 +700,9 @@
 		iounmap(ipcdev.ipc_base);
 		return -ENOMEM;
 	}
+
+	intel_scu_devices_create();
+
 	return 0;
 }
 
@@ -720,6 +724,7 @@
 	iounmap(ipcdev.ipc_base);
 	iounmap(ipcdev.i2c_base);
 	ipcdev.pdev = NULL;
+	intel_scu_devices_destroy();
 }
 
 static const struct pci_device_id pci_ids[] = {
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index b3c01c1..e7f8978 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -580,10 +580,8 @@
 {
 	struct ds2760_device_info *di = platform_get_drvdata(pdev);
 
-	cancel_rearming_delayed_workqueue(di->monitor_wqueue,
-					  &di->monitor_work);
-	cancel_rearming_delayed_workqueue(di->monitor_wqueue,
-					  &di->set_charged_work);
+	cancel_delayed_work_sync(&di->monitor_work);
+	cancel_delayed_work_sync(&di->set_charged_work);
 	destroy_workqueue(di->monitor_wqueue);
 	power_supply_unregister(&di->bat);
 	kfree(di);
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
index 2a10cd3..36cf402 100644
--- a/drivers/power/intel_mid_battery.c
+++ b/drivers/power/intel_mid_battery.c
@@ -730,8 +730,7 @@
 power_reg_failed_1:
 	power_supply_unregister(&pbi->batt);
 power_reg_failed:
-	cancel_rearming_delayed_workqueue(pbi->monitor_wqueue,
-						&pbi->monitor_battery);
+	cancel_delayed_work_sync(&pbi->monitor_battery);
 requestirq_failed:
 	destroy_workqueue(pbi->monitor_wqueue);
 wqueue_failed:
@@ -760,8 +759,7 @@
 	struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev);
 
 	free_irq(pbi->irq, pbi);
-	cancel_rearming_delayed_workqueue(pbi->monitor_wqueue,
-					&pbi->monitor_battery);
+	cancel_delayed_work_sync(&pbi->monitor_battery);
 	destroy_workqueue(pbi->monitor_wqueue);
 
 	power_supply_unregister(&pbi->usb);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2883428..4941cad 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -463,6 +463,18 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-cmos.
 
+config RTC_DRV_VRTC
+	tristate "Virtual RTC for Moorestown platforms"
+	depends on X86_MRST
+	default y if X86_MRST
+
+	help
+	Say "yes" here to get direct support for the real time clock
+	found on Moorestown platforms. The VRTC is a emulated RTC that
+	derives its clock source from a real RTC in the PMIC. The MC146818
+	style programming interface is mostly conserved, but any
+	updates are done via IPC calls to the system controller FW.
+
 config RTC_DRV_DS1216
 	tristate "Dallas DS1216"
 	depends on SNI_RM
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 4c2832d..2afdaf3 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -30,6 +30,7 @@
 obj-$(CONFIG_RTC_DRV_COH901331)	+= rtc-coh901331.o
 obj-$(CONFIG_RTC_DRV_DAVINCI)	+= rtc-davinci.o
 obj-$(CONFIG_RTC_DRV_DM355EVM)	+= rtc-dm355evm.o
+obj-$(CONFIG_RTC_DRV_VRTC)	+= rtc-mrst.o
 obj-$(CONFIG_RTC_DRV_DS1216)	+= rtc-ds1216.o
 obj-$(CONFIG_RTC_DRV_DS1286)	+= rtc-ds1286.o
 obj-$(CONFIG_RTC_DRV_DS1302)	+= rtc-ds1302.o
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 62227cd..0cc0984 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -104,7 +104,7 @@
 		}
 		if (rtc->uie_task_active) {
 			spin_unlock_irq(&rtc->irq_lock);
-			flush_scheduled_work();
+			flush_work_sync(&rtc->uie_task);
 			spin_lock_irq(&rtc->irq_lock);
 		}
 		rtc->uie_irq_active = 0;
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index 48da85e..077af1d 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -813,7 +813,7 @@
 	if (spi->irq) {
 		set_bit(FLAG_EXITING, &ds1305->flags);
 		free_irq(spi->irq, ds1305);
-		flush_scheduled_work();
+		cancel_work_sync(&ds1305->work);
 	}
 
 	rtc_device_unregister(ds1305->rtc);
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 1f0007f..47fb635 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -417,7 +417,7 @@
 		mutex_unlock(&ds1374->mutex);
 
 		free_irq(client->irq, client);
-		flush_scheduled_work();
+		cancel_work_sync(&ds1374->work);
 	}
 
 	rtc_device_unregister(ds1374->rtc);
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 5706355..23a9ee1 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -463,7 +463,7 @@
 		mutex_unlock(&ds3232->mutex);
 
 		free_irq(client->irq, client);
-		flush_scheduled_work();
+		cancel_work_sync(&ds3232->work);
 	}
 
 	rtc_device_unregister(ds3232->rtc);
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
new file mode 100644
index 0000000..bcd0cf6
--- /dev/null
+++ b/drivers/rtc/rtc-mrst.c
@@ -0,0 +1,582 @@
+/*
+ * rtc-mrst.c: Driver for Moorestown virtual RTC
+ *
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@intel.com)
+ *	   Feng Tang (feng.tang@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; 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 upon drivers/rtc/rtc-cmos.c
+ */
+
+/*
+ * Note:
+ *  * vRTC only supports binary mode and 24H mode
+ *  * vRTC only support PIE and AIE, no UIE, and its PIE only happens
+ *    at 23:59:59pm everyday, no support for adjustable frequency
+ *  * Alarm function is also limited to hr/min/sec.
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+
+#include <asm-generic/rtc.h>
+#include <asm/intel_scu_ipc.h>
+#include <asm/mrst.h>
+#include <asm/mrst-vrtc.h>
+
+struct mrst_rtc {
+	struct rtc_device	*rtc;
+	struct device		*dev;
+	int			irq;
+	struct resource		*iomem;
+
+	u8			enabled_wake;
+	u8			suspend_ctrl;
+};
+
+static const char driver_name[] = "rtc_mrst";
+
+#define	RTC_IRQMASK	(RTC_PF | RTC_AF)
+
+static inline int is_intr(u8 rtc_intr)
+{
+	if (!(rtc_intr & RTC_IRQF))
+		return 0;
+	return rtc_intr & RTC_IRQMASK;
+}
+
+/*
+ * rtc_time's year contains the increment over 1900, but vRTC's YEAR
+ * register can't be programmed to value larger than 0x64, so vRTC
+ * driver chose to use 1960 (1970 is UNIX time start point) as the base,
+ * and does the translation at read/write time.
+ *
+ * Why not just use 1970 as the offset? it's because using 1960 will
+ * make it consistent in leap year setting for both vrtc and low-level
+ * physical rtc devices.
+ */
+static int mrst_read_time(struct device *dev, struct rtc_time *time)
+{
+	unsigned long flags;
+
+	if (rtc_is_updating())
+		mdelay(20);
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	time->tm_sec = vrtc_cmos_read(RTC_SECONDS);
+	time->tm_min = vrtc_cmos_read(RTC_MINUTES);
+	time->tm_hour = vrtc_cmos_read(RTC_HOURS);
+	time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH);
+	time->tm_mon = vrtc_cmos_read(RTC_MONTH);
+	time->tm_year = vrtc_cmos_read(RTC_YEAR);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+
+	/* Adjust for the 1960/1900 */
+	time->tm_year += 60;
+	time->tm_mon--;
+	return RTC_24H;
+}
+
+static int mrst_set_time(struct device *dev, struct rtc_time *time)
+{
+	int ret;
+	unsigned long flags;
+	unsigned char mon, day, hrs, min, sec;
+	unsigned int yrs;
+
+	yrs = time->tm_year;
+	mon = time->tm_mon + 1;   /* tm_mon starts at zero */
+	day = time->tm_mday;
+	hrs = time->tm_hour;
+	min = time->tm_min;
+	sec = time->tm_sec;
+
+	if (yrs < 70 || yrs > 138)
+		return -EINVAL;
+	yrs -= 60;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+
+	vrtc_cmos_write(yrs, RTC_YEAR);
+	vrtc_cmos_write(mon, RTC_MONTH);
+	vrtc_cmos_write(day, RTC_DAY_OF_MONTH);
+	vrtc_cmos_write(hrs, RTC_HOURS);
+	vrtc_cmos_write(min, RTC_MINUTES);
+	vrtc_cmos_write(sec, RTC_SECONDS);
+
+	spin_unlock_irqrestore(&rtc_lock, flags);
+
+	ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME);
+	return ret;
+}
+
+static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
+	unsigned char rtc_control;
+
+	if (mrst->irq <= 0)
+		return -EIO;
+
+	/* Basic alarms only support hour, minute, and seconds fields.
+	 * Some also support day and month, for alarms up to a year in
+	 * the future.
+	 */
+	t->time.tm_mday = -1;
+	t->time.tm_mon = -1;
+	t->time.tm_year = -1;
+
+	/* vRTC only supports binary mode */
+	spin_lock_irq(&rtc_lock);
+	t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM);
+	t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM);
+	t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM);
+
+	rtc_control = vrtc_cmos_read(RTC_CONTROL);
+	spin_unlock_irq(&rtc_lock);
+
+	t->enabled = !!(rtc_control & RTC_AIE);
+	t->pending = 0;
+
+	return 0;
+}
+
+static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control)
+{
+	unsigned char	rtc_intr;
+
+	/*
+	 * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
+	 * allegedly some older rtcs need that to handle irqs properly
+	 */
+	rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS);
+	rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+	if (is_intr(rtc_intr))
+		rtc_update_irq(mrst->rtc, 1, rtc_intr);
+}
+
+static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask)
+{
+	unsigned char	rtc_control;
+
+	/*
+	 * Flush any pending IRQ status, notably for update irqs,
+	 * before we enable new IRQs
+	 */
+	rtc_control = vrtc_cmos_read(RTC_CONTROL);
+	mrst_checkintr(mrst, rtc_control);
+
+	rtc_control |= mask;
+	vrtc_cmos_write(rtc_control, RTC_CONTROL);
+
+	mrst_checkintr(mrst, rtc_control);
+}
+
+static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask)
+{
+	unsigned char	rtc_control;
+
+	rtc_control = vrtc_cmos_read(RTC_CONTROL);
+	rtc_control &= ~mask;
+	vrtc_cmos_write(rtc_control, RTC_CONTROL);
+	mrst_checkintr(mrst, rtc_control);
+}
+
+static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
+	unsigned char hrs, min, sec;
+	int ret = 0;
+
+	if (!mrst->irq)
+		return -EIO;
+
+	hrs = t->time.tm_hour;
+	min = t->time.tm_min;
+	sec = t->time.tm_sec;
+
+	spin_lock_irq(&rtc_lock);
+	/* Next rtc irq must not be from previous alarm setting */
+	mrst_irq_disable(mrst, RTC_AIE);
+
+	/* Update alarm */
+	vrtc_cmos_write(hrs, RTC_HOURS_ALARM);
+	vrtc_cmos_write(min, RTC_MINUTES_ALARM);
+	vrtc_cmos_write(sec, RTC_SECONDS_ALARM);
+
+	spin_unlock_irq(&rtc_lock);
+
+	ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM);
+	if (ret)
+		return ret;
+
+	spin_lock_irq(&rtc_lock);
+	if (t->enabled)
+		mrst_irq_enable(mrst, RTC_AIE);
+
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+static int mrst_irq_set_state(struct device *dev, int enabled)
+{
+	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	if (!mrst->irq)
+		return -ENXIO;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+
+	if (enabled)
+		mrst_irq_enable(mrst, RTC_PIE);
+	else
+		mrst_irq_disable(mrst, RTC_PIE);
+
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return 0;
+}
+
+#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
+
+/* Currently, the vRTC doesn't support UIE ON/OFF */
+static int
+mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	switch (cmd) {
+	case RTC_AIE_OFF:
+	case RTC_AIE_ON:
+		if (!mrst->irq)
+			return -EINVAL;
+		break;
+	default:
+		/* PIE ON/OFF is handled by mrst_irq_set_state() */
+		return -ENOIOCTLCMD;
+	}
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	switch (cmd) {
+	case RTC_AIE_OFF:	/* alarm off */
+		mrst_irq_disable(mrst, RTC_AIE);
+		break;
+	case RTC_AIE_ON:	/* alarm on */
+		mrst_irq_enable(mrst, RTC_AIE);
+		break;
+	}
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return 0;
+}
+
+#else
+#define	mrst_rtc_ioctl	NULL
+#endif
+
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+
+static int mrst_procfs(struct device *dev, struct seq_file *seq)
+{
+	unsigned char	rtc_control, valid;
+
+	spin_lock_irq(&rtc_lock);
+	rtc_control = vrtc_cmos_read(RTC_CONTROL);
+	valid = vrtc_cmos_read(RTC_VALID);
+	spin_unlock_irq(&rtc_lock);
+
+	return seq_printf(seq,
+			"periodic_IRQ\t: %s\n"
+			"alarm\t\t: %s\n"
+			"BCD\t\t: no\n"
+			"periodic_freq\t: daily (not adjustable)\n",
+			(rtc_control & RTC_PIE) ? "on" : "off",
+			(rtc_control & RTC_AIE) ? "on" : "off");
+}
+
+#else
+#define	mrst_procfs	NULL
+#endif
+
+static const struct rtc_class_ops mrst_rtc_ops = {
+	.ioctl		= mrst_rtc_ioctl,
+	.read_time	= mrst_read_time,
+	.set_time	= mrst_set_time,
+	.read_alarm	= mrst_read_alarm,
+	.set_alarm	= mrst_set_alarm,
+	.proc		= mrst_procfs,
+	.irq_set_state	= mrst_irq_set_state,
+};
+
+static struct mrst_rtc	mrst_rtc;
+
+/*
+ * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in
+ * Reg B, so no need for this driver to clear it
+ */
+static irqreturn_t mrst_rtc_irq(int irq, void *p)
+{
+	u8 irqstat;
+
+	spin_lock(&rtc_lock);
+	/* This read will clear all IRQ flags inside Reg C */
+	irqstat = vrtc_cmos_read(RTC_INTR_FLAGS);
+	spin_unlock(&rtc_lock);
+
+	irqstat &= RTC_IRQMASK | RTC_IRQF;
+	if (is_intr(irqstat)) {
+		rtc_update_irq(p, 1, irqstat);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static int __init
+vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
+{
+	int retval = 0;
+	unsigned char rtc_control;
+
+	/* There can be only one ... */
+	if (mrst_rtc.dev)
+		return -EBUSY;
+
+	if (!iomem)
+		return -ENODEV;
+
+	iomem = request_mem_region(iomem->start,
+			iomem->end + 1 - iomem->start,
+			driver_name);
+	if (!iomem) {
+		dev_dbg(dev, "i/o mem already in use.\n");
+		return -EBUSY;
+	}
+
+	mrst_rtc.irq = rtc_irq;
+	mrst_rtc.iomem = iomem;
+
+	mrst_rtc.rtc = rtc_device_register(driver_name, dev,
+				&mrst_rtc_ops, THIS_MODULE);
+	if (IS_ERR(mrst_rtc.rtc)) {
+		retval = PTR_ERR(mrst_rtc.rtc);
+		goto cleanup0;
+	}
+
+	mrst_rtc.dev = dev;
+	dev_set_drvdata(dev, &mrst_rtc);
+	rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
+
+	spin_lock_irq(&rtc_lock);
+	mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE);
+	rtc_control = vrtc_cmos_read(RTC_CONTROL);
+	spin_unlock_irq(&rtc_lock);
+
+	if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))
+		dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n");
+
+	if (rtc_irq) {
+		retval = request_irq(rtc_irq, mrst_rtc_irq,
+				IRQF_DISABLED, dev_name(&mrst_rtc.rtc->dev),
+				mrst_rtc.rtc);
+		if (retval < 0) {
+			dev_dbg(dev, "IRQ %d is already in use, err %d\n",
+				rtc_irq, retval);
+			goto cleanup1;
+		}
+	}
+	dev_dbg(dev, "initialised\n");
+	return 0;
+
+cleanup1:
+	mrst_rtc.dev = NULL;
+	rtc_device_unregister(mrst_rtc.rtc);
+cleanup0:
+	release_region(iomem->start, iomem->end + 1 - iomem->start);
+	dev_err(dev, "rtc-mrst: unable to initialise\n");
+	return retval;
+}
+
+static void rtc_mrst_do_shutdown(void)
+{
+	spin_lock_irq(&rtc_lock);
+	mrst_irq_disable(&mrst_rtc, RTC_IRQMASK);
+	spin_unlock_irq(&rtc_lock);
+}
+
+static void __exit rtc_mrst_do_remove(struct device *dev)
+{
+	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
+	struct resource *iomem;
+
+	rtc_mrst_do_shutdown();
+
+	if (mrst->irq)
+		free_irq(mrst->irq, mrst->rtc);
+
+	rtc_device_unregister(mrst->rtc);
+	mrst->rtc = NULL;
+
+	iomem = mrst->iomem;
+	release_region(iomem->start, iomem->end + 1 - iomem->start);
+	mrst->iomem = NULL;
+
+	mrst->dev = NULL;
+	dev_set_drvdata(dev, NULL);
+}
+
+#ifdef	CONFIG_PM
+static int mrst_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
+	unsigned char	tmp;
+
+	/* Only the alarm might be a wakeup event source */
+	spin_lock_irq(&rtc_lock);
+	mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL);
+	if (tmp & (RTC_PIE | RTC_AIE)) {
+		unsigned char	mask;
+
+		if (device_may_wakeup(dev))
+			mask = RTC_IRQMASK & ~RTC_AIE;
+		else
+			mask = RTC_IRQMASK;
+		tmp &= ~mask;
+		vrtc_cmos_write(tmp, RTC_CONTROL);
+
+		mrst_checkintr(mrst, tmp);
+	}
+	spin_unlock_irq(&rtc_lock);
+
+	if (tmp & RTC_AIE) {
+		mrst->enabled_wake = 1;
+		enable_irq_wake(mrst->irq);
+	}
+
+	dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n",
+			(tmp & RTC_AIE) ? ", alarm may wake" : "",
+			tmp);
+
+	return 0;
+}
+
+/*
+ * We want RTC alarms to wake us from the deep power saving state
+ */
+static inline int mrst_poweroff(struct device *dev)
+{
+	return mrst_suspend(dev, PMSG_HIBERNATE);
+}
+
+static int mrst_resume(struct device *dev)
+{
+	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
+	unsigned char tmp = mrst->suspend_ctrl;
+
+	/* Re-enable any irqs previously active */
+	if (tmp & RTC_IRQMASK) {
+		unsigned char	mask;
+
+		if (mrst->enabled_wake) {
+			disable_irq_wake(mrst->irq);
+			mrst->enabled_wake = 0;
+		}
+
+		spin_lock_irq(&rtc_lock);
+		do {
+			vrtc_cmos_write(tmp, RTC_CONTROL);
+
+			mask = vrtc_cmos_read(RTC_INTR_FLAGS);
+			mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
+			if (!is_intr(mask))
+				break;
+
+			rtc_update_irq(mrst->rtc, 1, mask);
+			tmp &= ~RTC_AIE;
+		} while (mask & RTC_AIE);
+		spin_unlock_irq(&rtc_lock);
+	}
+
+	dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp);
+
+	return 0;
+}
+
+#else
+#define	mrst_suspend	NULL
+#define	mrst_resume	NULL
+
+static inline int mrst_poweroff(struct device *dev)
+{
+	return -ENOSYS;
+}
+
+#endif
+
+static int __init vrtc_mrst_platform_probe(struct platform_device *pdev)
+{
+	return vrtc_mrst_do_probe(&pdev->dev,
+			platform_get_resource(pdev, IORESOURCE_MEM, 0),
+			platform_get_irq(pdev, 0));
+}
+
+static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev)
+{
+	rtc_mrst_do_remove(&pdev->dev);
+	return 0;
+}
+
+static void vrtc_mrst_platform_shutdown(struct platform_device *pdev)
+{
+	if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev))
+		return;
+
+	rtc_mrst_do_shutdown();
+}
+
+MODULE_ALIAS("platform:vrtc_mrst");
+
+static struct platform_driver vrtc_mrst_platform_driver = {
+	.probe		= vrtc_mrst_platform_probe,
+	.remove		= __exit_p(vrtc_mrst_platform_remove),
+	.shutdown	= vrtc_mrst_platform_shutdown,
+	.driver = {
+		.name		= (char *) driver_name,
+		.suspend	= mrst_suspend,
+		.resume		= mrst_resume,
+	}
+};
+
+static int __init vrtc_mrst_init(void)
+{
+	return platform_driver_register(&vrtc_mrst_platform_driver);
+}
+
+static void __exit vrtc_mrst_exit(void)
+{
+	platform_driver_unregister(&vrtc_mrst_platform_driver);
+}
+
+module_init(vrtc_mrst_init);
+module_exit(vrtc_mrst_exit);
+
+MODULE_AUTHOR("Jacob Pan; Feng Tang");
+MODULE_DESCRIPTION("Driver for Moorestown virtual RTC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 1146e35..af32a62 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -650,7 +650,7 @@
 		mutex_unlock(lock);
 
 		free_irq(client->irq, client);
-		flush_scheduled_work();
+		cancel_work_sync(&rx8025->work);
 	}
 
 	rx8025_sysfs_unregister(&client->dev);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index e4a44b6..88ea52b 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -39,10 +39,10 @@
 #include <mach/regs-ost.h>
 #endif
 
-#define RTC_DEF_DIVIDER		32768 - 1
+#define RTC_DEF_DIVIDER		(32768 - 1)
 #define RTC_DEF_TRIM		0
 
-static unsigned long rtc_freq = 1024;
+static const unsigned long RTC_FREQ = 1024;
 static unsigned long timer_freq;
 static struct rtc_time rtc_alarm;
 static DEFINE_SPINLOCK(sa1100_rtc_lock);
@@ -61,7 +61,8 @@
  * Calculate the next alarm time given the requested alarm time mask
  * and the current time.
  */
-static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm)
+static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
+	struct rtc_time *alrm)
 {
 	unsigned long next_time;
 	unsigned long now_time;
@@ -116,7 +117,23 @@
 	rtsr = RTSR;
 	/* clear interrupt sources */
 	RTSR = 0;
-	RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
+	 * See also the comments in sa1100_rtc_probe(). */
+	if (rtsr & (RTSR_ALE | RTSR_HZE)) {
+		/* This is the original code, before there was the if test
+		 * above. This code does not clear interrupts that were not
+		 * enabled. */
+		RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+	} else {
+		/* For some reason, it is possible to enter this routine
+		 * without interruptions enabled, it has been tested with
+		 * several units (Bug in SA11xx chip?).
+		 *
+		 * This situation leads to an infinite "loop" of interrupt
+		 * routine calling and as a result the processor seems to
+		 * lock on its first call to open(). */
+		RTSR = RTSR_AL | RTSR_HZ;
+	}
 
 	/* clear alarm interrupt if it has occurred */
 	if (rtsr & RTSR_AL)
@@ -139,8 +156,58 @@
 	return IRQ_HANDLED;
 }
 
+static int sa1100_irq_set_freq(struct device *dev, int freq)
+{
+	if (freq < 1 || freq > timer_freq) {
+		return -EINVAL;
+	} else {
+		struct rtc_device *rtc = (struct rtc_device *)dev;
+
+		rtc->irq_freq = freq;
+
+		return 0;
+	}
+}
+
 static int rtc_timer1_count;
 
+static int sa1100_irq_set_state(struct device *dev, int enabled)
+{
+	spin_lock_irq(&sa1100_rtc_lock);
+	if (enabled) {
+		struct rtc_device *rtc = (struct rtc_device *)dev;
+
+		OSMR1 = timer_freq / rtc->irq_freq + OSCR;
+		OIER |= OIER_E1;
+		rtc_timer1_count = 1;
+	} else {
+		OIER &= ~OIER_E1;
+	}
+	spin_unlock_irq(&sa1100_rtc_lock);
+
+	return 0;
+}
+
+static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
+{
+	unsigned long diff;
+	unsigned long period = timer_freq / rtc->irq_freq;
+
+	spin_lock_irq(&sa1100_rtc_lock);
+
+	do {
+		OSMR1 += period;
+		diff = OSMR1 - OSCR;
+		/* If OSCR > OSMR1, diff is a very large number (unsigned
+		 * math). This means we have a lost interrupt. */
+	} while (diff > period);
+	OIER |= OIER_E1;
+
+	spin_unlock_irq(&sa1100_rtc_lock);
+
+	return 0;
+}
+
 static irqreturn_t timer1_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = to_platform_device(dev_id);
@@ -158,7 +225,11 @@
 	rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
 
 	if (rtc_timer1_count == 1)
-		rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
+		rtc_timer1_count =
+			(rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
+
+	/* retrigger. */
+	sa1100_timer1_retrigger(rtc);
 
 	return IRQ_HANDLED;
 }
@@ -166,8 +237,10 @@
 static int sa1100_rtc_read_callback(struct device *dev, int data)
 {
 	if (data & RTC_PF) {
+		struct rtc_device *rtc = (struct rtc_device *)dev;
+
 		/* interpolate missed periods and set match for the next */
-		unsigned long period = timer_freq / rtc_freq;
+		unsigned long period = timer_freq / rtc->irq_freq;
 		unsigned long oscr = OSCR;
 		unsigned long osmr1 = OSMR1;
 		unsigned long missed = (oscr - osmr1)/period;
@@ -178,7 +251,7 @@
 		 * Here we compare (match - OSCR) 8 instead of 0 --
 		 * see comment in pxa_timer_interrupt() for explanation.
 		 */
-		while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
+		while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
 			data += 0x100;
 			OSSR = OSSR_M1;	/* clear match on timer 1 */
 			OSMR1 = osmr1 + period;
@@ -190,25 +263,29 @@
 static int sa1100_rtc_open(struct device *dev)
 {
 	int ret;
+	struct rtc_device *rtc = (struct rtc_device *)dev;
 
 	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
-				"rtc 1Hz", dev);
+		"rtc 1Hz", dev);
 	if (ret) {
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
 		goto fail_ui;
 	}
 	ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
-				"rtc Alrm", dev);
+		"rtc Alrm", dev);
 	if (ret) {
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
 		goto fail_ai;
 	}
 	ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
-				"rtc timer", dev);
+		"rtc timer", dev);
 	if (ret) {
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
 		goto fail_pi;
 	}
+	rtc->max_user_freq = RTC_FREQ;
+	sa1100_irq_set_freq(dev, RTC_FREQ);
+
 	return 0;
 
  fail_pi:
@@ -236,7 +313,7 @@
 static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
 		unsigned long arg)
 {
-	switch(cmd) {
+	switch (cmd) {
 	case RTC_AIE_OFF:
 		spin_lock_irq(&sa1100_rtc_lock);
 		RTSR &= ~RTSR_ALE;
@@ -257,25 +334,6 @@
 		RTSR |= RTSR_HZE;
 		spin_unlock_irq(&sa1100_rtc_lock);
 		return 0;
-	case RTC_PIE_OFF:
-		spin_lock_irq(&sa1100_rtc_lock);
-		OIER &= ~OIER_E1;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	case RTC_PIE_ON:
-		spin_lock_irq(&sa1100_rtc_lock);
-		OSMR1 = timer_freq / rtc_freq + OSCR;
-		OIER |= OIER_E1;
-		rtc_timer1_count = 1;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	case RTC_IRQP_READ:
-		return put_user(rtc_freq, (unsigned long *)arg);
-	case RTC_IRQP_SET:
-		if (arg < 1 || arg > timer_freq)
-			return -EINVAL;
-		rtc_freq = arg;
-		return 0;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -327,12 +385,15 @@
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
+	struct rtc_device *rtc = (struct rtc_device *)dev;
+
 	seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
 	seq_printf(seq, "update_IRQ\t: %s\n",
 			(RTSR & RTSR_HZE) ? "yes" : "no");
 	seq_printf(seq, "periodic_IRQ\t: %s\n",
 			(OIER & OIER_E1) ? "yes" : "no");
-	seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
+	seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
+	seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
 
 	return 0;
 }
@@ -347,6 +408,8 @@
 	.read_alarm = sa1100_rtc_read_alarm,
 	.set_alarm = sa1100_rtc_set_alarm,
 	.proc = sa1100_rtc_proc,
+	.irq_set_freq = sa1100_irq_set_freq,
+	.irq_set_state = sa1100_irq_set_state,
 };
 
 static int sa1100_rtc_probe(struct platform_device *pdev)
@@ -364,7 +427,8 @@
 	 */
 	if (RTTR == 0) {
 		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
+		dev_warn(&pdev->dev, "warning: "
+			"initializing default clock divider/trim value\n");
 		/* The current RTC value probably doesn't make sense either */
 		RCNR = 0;
 	}
@@ -372,13 +436,42 @@
 	device_init_wakeup(&pdev->dev, 1);
 
 	rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
-				THIS_MODULE);
+		THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 
 	platform_set_drvdata(pdev, rtc);
 
+	/* Set the irq_freq */
+	/*TODO: Find out who is messing with this value after we initialize
+	 * it here.*/
+	rtc->irq_freq = RTC_FREQ;
+
+	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
+	 * See also the comments in sa1100_rtc_interrupt().
+	 *
+	 * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
+	 * interrupt pending, even though interrupts were never enabled.
+	 * In this case, this bit it must be reset before enabling
+	 * interruptions to avoid a nonexistent interrupt to occur.
+	 *
+	 * In principle, the same problem would apply to bit 0, although it has
+	 * never been observed to happen.
+	 *
+	 * This issue is addressed both here and in sa1100_rtc_interrupt().
+	 * If the issue is not addressed here, in the times when the processor
+	 * wakes up with the bit set there will be one spurious interrupt.
+	 *
+	 * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
+	 * safe side, once the condition that lead to this strange
+	 * initialization is unknown and could in principle happen during
+	 * normal processing.
+	 *
+	 * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
+	 * the corresponding bits in RTSR. */
+	RTSR = RTSR_AL | RTSR_HZ;
+
 	return 0;
 }
 
@@ -386,7 +479,7 @@
 {
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
 
- 	if (rtc)
+	if (rtc)
 		rtc_device_unregister(rtc);
 
 	return 0;
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 0788319..8e477bb 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -2,7 +2,8 @@
 	depends on S390 && BLOCK
 
 config BLK_DEV_XPRAM
-	tristate "XPRAM disk support"
+	def_tristate m
+	prompt "XPRAM disk support"
 	depends on S390 && BLOCK
 	help
 	  Select this option if you want to use your expanded storage on S/390
@@ -12,13 +13,15 @@
 	  xpram.  If unsure, say "N".
 
 config DCSSBLK
-	tristate "DCSSBLK support"
+	def_tristate m
+	prompt "DCSSBLK support"
 	depends on S390 && BLOCK
 	help
 	  Support for dcss block device
 
 config DASD
-	tristate "Support for DASD devices"
+	def_tristate y
+	prompt "Support for DASD devices"
 	depends on CCW && BLOCK
 	select IOSCHED_DEADLINE
 	help
@@ -27,28 +30,32 @@
 	  natively on a single image or an LPAR.
 
 config DASD_PROFILE
-	bool "Profiling support for dasd devices"
+	def_bool y
+	prompt "Profiling support for dasd devices"
 	depends on DASD
 	help
 	  Enable this option if you want to see profiling information
           in /proc/dasd/statistics.
 
 config DASD_ECKD
-	tristate "Support for ECKD Disks"
+	def_tristate y
+	prompt "Support for ECKD Disks"
 	depends on DASD
 	help
 	  ECKD devices are the most commonly used devices. You should enable
 	  this option unless you are very sure to have no ECKD device.
 
 config DASD_FBA
-	tristate "Support for FBA  Disks"
+	def_tristate y
+	prompt "Support for FBA  Disks"
 	depends on DASD
 	help
 	  Select this option to be able to access FBA devices. It is safe to
 	  say "Y".
 
 config DASD_DIAG
-	tristate "Support for DIAG access to Disks"
+	def_tristate y
+	prompt "Support for DIAG access to Disks"
 	depends on DASD
 	help
 	  Select this option if you want to use Diagnose250 command to access
@@ -56,7 +63,8 @@
 	  say "N".
 
 config DASD_EER
-	bool "Extended error reporting (EER)"
+	def_bool y
+	prompt "Extended error reporting (EER)"
 	depends on DASD
 	help
 	  This driver provides a character device interface to the
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index fb613d7..794bfd9 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -11,6 +11,7 @@
 #define KMSG_COMPONENT "dasd"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -368,6 +369,11 @@
 	device->state = DASD_STATE_ONLINE;
 	if (device->block) {
 		dasd_schedule_block_bh(device->block);
+		if ((device->features & DASD_FEATURE_USERAW)) {
+			disk = device->block->gdp;
+			kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
+			return 0;
+		}
 		disk = device->block->bdev->bd_disk;
 		disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
 		while ((part = disk_part_iter_next(&piter)))
@@ -393,7 +399,7 @@
 			return rc;
 	}
 	device->state = DASD_STATE_READY;
-	if (device->block) {
+	if (device->block && !(device->features & DASD_FEATURE_USERAW)) {
 		disk = device->block->bdev->bd_disk;
 		disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
 		while ((part = disk_part_iter_next(&piter)))
@@ -744,10 +750,6 @@
 	char *data;
 	int size;
 
-	/* Sanity checks */
-	BUG_ON(datasize > PAGE_SIZE ||
-	     (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
-
 	size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
 	if (cplength > 0)
 		size += cplength * sizeof(struct ccw1);
@@ -853,7 +855,6 @@
 		rc = ccw_device_clear(device->cdev, (long) cqr);
 		switch (rc) {
 		case 0:	/* termination successful */
-			cqr->retries--;
 			cqr->status = DASD_CQR_CLEAR_PENDING;
 			cqr->stopclk = get_clock();
 			cqr->starttime = 0;
@@ -905,6 +906,16 @@
 		return rc;
 	}
 	device = (struct dasd_device *) cqr->startdev;
+	if (((cqr->block &&
+	      test_bit(DASD_FLAG_LOCK_STOLEN, &cqr->block->base->flags)) ||
+	     test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags)) &&
+	    !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
+		DBF_DEV_EVENT(DBF_DEBUG, device, "start_IO: return request %p "
+			      "because of stolen lock", cqr);
+		cqr->status = DASD_CQR_ERROR;
+		cqr->intrc = -EPERM;
+		return -EPERM;
+	}
 	if (cqr->retries < 0) {
 		/* internal error 14 - start_IO run out of retries */
 		sprintf(errorstring, "14 %p", cqr);
@@ -916,6 +927,11 @@
 	cqr->startclk = get_clock();
 	cqr->starttime = jiffies;
 	cqr->retries--;
+	if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
+		cqr->lpm &= device->path_data.opm;
+		if (!cqr->lpm)
+			cqr->lpm = device->path_data.opm;
+	}
 	if (cqr->cpmode == 1) {
 		rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
 					 (long) cqr, cqr->lpm);
@@ -928,35 +944,53 @@
 		cqr->status = DASD_CQR_IN_IO;
 		break;
 	case -EBUSY:
-		DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
 			      "start_IO: device busy, retry later");
 		break;
 	case -ETIMEDOUT:
-		DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
 			      "start_IO: request timeout, retry later");
 		break;
 	case -EACCES:
-		/* -EACCES indicates that the request used only a
-		 * subset of the available pathes and all these
-		 * pathes are gone.
-		 * Do a retry with all available pathes.
+		/* -EACCES indicates that the request used only a subset of the
+		 * available paths and all these paths are gone. If the lpm of
+		 * this request was only a subset of the opm (e.g. the ppm) then
+		 * we just do a retry with all available paths.
+		 * If we already use the full opm, something is amiss, and we
+		 * need a full path verification.
 		 */
-		cqr->lpm = LPM_ANYPATH;
-		DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
-			      "start_IO: selected pathes gone,"
-			      " retry on all pathes");
+		if (test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
+			DBF_DEV_EVENT(DBF_WARNING, device,
+				      "start_IO: selected paths gone (%x)",
+				      cqr->lpm);
+		} else if (cqr->lpm != device->path_data.opm) {
+			cqr->lpm = device->path_data.opm;
+			DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+				      "start_IO: selected paths gone,"
+				      " retry on all paths");
+		} else {
+			DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+				      "start_IO: all paths in opm gone,"
+				      " do path verification");
+			dasd_generic_last_path_gone(device);
+			device->path_data.opm = 0;
+			device->path_data.ppm = 0;
+			device->path_data.npm = 0;
+			device->path_data.tbvpm =
+				ccw_device_get_path_mask(device->cdev);
+		}
 		break;
 	case -ENODEV:
-		DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
 			      "start_IO: -ENODEV device gone, retry");
 		break;
 	case -EIO:
-		DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
 			      "start_IO: -EIO device gone, retry");
 		break;
 	case -EINVAL:
 		/* most likely caused in power management context */
-		DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
 			      "start_IO: -EINVAL device currently "
 			      "not accessible");
 		break;
@@ -1076,6 +1110,7 @@
 	unsigned long long now;
 	int expires;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_DAS]++;
 	if (IS_ERR(irb)) {
 		switch (PTR_ERR(irb)) {
 		case -EIO:
@@ -1094,16 +1129,11 @@
 	}
 
 	now = get_clock();
-
-	/* check for unsolicited interrupts */
 	cqr = (struct dasd_ccw_req *) intparm;
-	if (!cqr || ((scsw_cc(&irb->scsw) == 1) &&
-		     (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) &&
-		     ((scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND) ||
-		      (scsw_stctl(&irb->scsw) == (SCSW_STCTL_STATUS_PEND |
-						  SCSW_STCTL_ALERT_STATUS))))) {
-		if (cqr && cqr->status == DASD_CQR_IN_IO)
-			cqr->status = DASD_CQR_QUEUED;
+	/* check for conditions that should be handled immediately */
+	if (!cqr ||
+	    !(scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
+	      scsw_cstat(&irb->scsw) == 0)) {
 		if (cqr)
 			memcpy(&cqr->irb, irb, sizeof(*irb));
 		device = dasd_device_from_cdev_locked(cdev);
@@ -1114,17 +1144,14 @@
 			dasd_put_device(device);
 			return;
 		}
-		device->discipline->dump_sense_dbf(device, irb,
-						   "unsolicited");
-		if ((device->features & DASD_FEATURE_ERPLOG))
-			device->discipline->dump_sense(device, cqr,
-						       irb);
-		dasd_device_clear_timer(device);
-		device->discipline->handle_unsolicited_interrupt(device,
-								 irb);
+		device->discipline->dump_sense_dbf(device, irb, "int");
+		if (device->features & DASD_FEATURE_ERPLOG)
+			device->discipline->dump_sense(device, cqr, irb);
+		device->discipline->check_for_device_change(device, cqr, irb);
 		dasd_put_device(device);
-		return;
 	}
+	if (!cqr)
+		return;
 
 	device = (struct dasd_device *) cqr->startdev;
 	if (!device ||
@@ -1164,25 +1191,19 @@
 					  struct dasd_ccw_req, devlist);
 		}
 	} else {  /* error */
-		memcpy(&cqr->irb, irb, sizeof(struct irb));
-		/* log sense for every failed I/O to s390 debugfeature */
-		dasd_log_sense_dbf(cqr, irb);
-		if (device->features & DASD_FEATURE_ERPLOG) {
-			dasd_log_sense(cqr, irb);
-		}
-
 		/*
 		 * If we don't want complex ERP for this request, then just
 		 * reset this and retry it in the fastpath
 		 */
 		if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) &&
 		    cqr->retries > 0) {
-			if (cqr->lpm == LPM_ANYPATH)
+			if (cqr->lpm == device->path_data.opm)
 				DBF_DEV_EVENT(DBF_DEBUG, device,
 					      "default ERP in fastpath "
 					      "(%i retries left)",
 					      cqr->retries);
-			cqr->lpm    = LPM_ANYPATH;
+			if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))
+				cqr->lpm = device->path_data.opm;
 			cqr->status = DASD_CQR_QUEUED;
 			next = cqr;
 		} else
@@ -1210,13 +1231,13 @@
 		goto out;
 	if (test_bit(DASD_FLAG_OFFLINE, &device->flags) ||
 	   device->state != device->target ||
-	   !device->discipline->handle_unsolicited_interrupt){
+	   !device->discipline->check_for_device_change){
 		dasd_put_device(device);
 		goto out;
 	}
-
-	dasd_device_clear_timer(device);
-	device->discipline->handle_unsolicited_interrupt(device, irb);
+	if (device->discipline->dump_sense_dbf)
+		device->discipline->dump_sense_dbf(device, irb, "uc");
+	device->discipline->check_for_device_change(device, NULL, irb);
 	dasd_put_device(device);
 out:
 	return UC_TODO_RETRY;
@@ -1366,8 +1387,14 @@
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist);
 	if (cqr->status != DASD_CQR_QUEUED)
 		return;
-	/* when device is stopped, return request to previous layer */
-	if (device->stopped) {
+	/* when device is stopped, return request to previous layer
+	 * exception: only the disconnect or unresumed bits are set and the
+	 * cqr is a path verification request
+	 */
+	if (device->stopped &&
+	    !(!(device->stopped & ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM))
+	      && test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))) {
+		cqr->intrc = -EAGAIN;
 		cqr->status = DASD_CQR_CLEARED;
 		dasd_schedule_device_bh(device);
 		return;
@@ -1383,6 +1410,23 @@
 		dasd_device_set_timer(device, 50);
 }
 
+static void __dasd_device_check_path_events(struct dasd_device *device)
+{
+	int rc;
+
+	if (device->path_data.tbvpm) {
+		if (device->stopped & ~(DASD_STOPPED_DC_WAIT |
+					DASD_UNRESUMED_PM))
+			return;
+		rc = device->discipline->verify_path(
+			device, device->path_data.tbvpm);
+		if (rc)
+			dasd_device_set_timer(device, 50);
+		else
+			device->path_data.tbvpm = 0;
+	}
+};
+
 /*
  * Go through all request on the dasd_device request queue,
  * terminate them on the cdev if necessary, and return them to the
@@ -1457,6 +1501,7 @@
 	__dasd_device_check_expire(device);
 	/* find final requests on ccw queue */
 	__dasd_device_process_ccw_queue(device, &final_queue);
+	__dasd_device_check_path_events(device);
 	spin_unlock_irq(get_ccwdev_lock(device->cdev));
 	/* Now call the callback function of requests with final status */
 	__dasd_device_process_final_queue(device, &final_queue);
@@ -1613,7 +1658,12 @@
 			continue;
 		if (cqr->status != DASD_CQR_FILLED) /* could be failed */
 			continue;
-
+		if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
+		    !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
+			cqr->status = DASD_CQR_FAILED;
+			cqr->intrc = -EPERM;
+			continue;
+		}
 		/* Non-temporary stop condition will trigger fail fast */
 		if (device->stopped & ~DASD_STOPPED_PENDING &&
 		    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
@@ -1621,7 +1671,6 @@
 			cqr->status = DASD_CQR_FAILED;
 			continue;
 		}
-
 		/* Don't try to start requests if device is stopped */
 		if (interruptible) {
 			rc = wait_event_interruptible(
@@ -1706,13 +1755,18 @@
 	int rc;
 
 	device = cqr->startdev;
+	if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
+	    !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
+		cqr->status = DASD_CQR_FAILED;
+		cqr->intrc = -EPERM;
+		return -EIO;
+	}
 	spin_lock_irq(get_ccwdev_lock(device->cdev));
 	rc = _dasd_term_running_cqr(device);
 	if (rc) {
 		spin_unlock_irq(get_ccwdev_lock(device->cdev));
 		return rc;
 	}
-
 	cqr->callback = dasd_wakeup_cb;
 	cqr->callback_data = DASD_SLEEPON_START_TAG;
 	cqr->status = DASD_CQR_QUEUED;
@@ -2016,6 +2070,13 @@
 	list_for_each_entry(cqr, &block->ccw_queue, blocklist) {
 		if (cqr->status != DASD_CQR_FILLED)
 			continue;
+		if (test_bit(DASD_FLAG_LOCK_STOLEN, &block->base->flags) &&
+		    !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
+			cqr->status = DASD_CQR_FAILED;
+			cqr->intrc = -EPERM;
+			dasd_schedule_block_bh(block);
+			continue;
+		}
 		/* Non-temporary stop condition will trigger fail fast */
 		if (block->base->stopped & ~DASD_STOPPED_PENDING &&
 		    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
@@ -2201,8 +2262,20 @@
 {
 	int max;
 
-	blk_queue_logical_block_size(block->request_queue, block->bp_block);
-	max = block->base->discipline->max_blocks << block->s2b_shift;
+	if (block->base->features & DASD_FEATURE_USERAW) {
+		/*
+		 * the max_blocks value for raw_track access is 256
+		 * it is higher than the native ECKD value because we
+		 * only need one ccw per track
+		 * so the max_hw_sectors are
+		 * 2048 x 512B = 1024kB = 16 tracks
+		 */
+		max = 2048;
+	} else {
+		max = block->base->discipline->max_blocks << block->s2b_shift;
+	}
+	blk_queue_logical_block_size(block->request_queue,
+				     block->bp_block);
 	blk_queue_max_hw_sectors(block->request_queue, max);
 	blk_queue_max_segments(block->request_queue, -1L);
 	/* with page sized segments we can translate each segement into
@@ -2588,10 +2661,53 @@
 	return 0;
 }
 
+int dasd_generic_last_path_gone(struct dasd_device *device)
+{
+	struct dasd_ccw_req *cqr;
+
+	dev_warn(&device->cdev->dev, "No operational channel path is left "
+		 "for the device\n");
+	DBF_DEV_EVENT(DBF_WARNING, device, "%s", "last path gone");
+	/* First of all call extended error reporting. */
+	dasd_eer_write(device, NULL, DASD_EER_NOPATH);
+
+	if (device->state < DASD_STATE_BASIC)
+		return 0;
+	/* Device is active. We want to keep it. */
+	list_for_each_entry(cqr, &device->ccw_queue, devlist)
+		if ((cqr->status == DASD_CQR_IN_IO) ||
+		    (cqr->status == DASD_CQR_CLEAR_PENDING)) {
+			cqr->status = DASD_CQR_QUEUED;
+			cqr->retries++;
+		}
+	dasd_device_set_stop_bits(device, DASD_STOPPED_DC_WAIT);
+	dasd_device_clear_timer(device);
+	dasd_schedule_device_bh(device);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(dasd_generic_last_path_gone);
+
+int dasd_generic_path_operational(struct dasd_device *device)
+{
+	dev_info(&device->cdev->dev, "A channel path to the device has become "
+		 "operational\n");
+	DBF_DEV_EVENT(DBF_WARNING, device, "%s", "path operational");
+	dasd_device_remove_stop_bits(device, DASD_STOPPED_DC_WAIT);
+	if (device->stopped & DASD_UNRESUMED_PM) {
+		dasd_device_remove_stop_bits(device, DASD_UNRESUMED_PM);
+		dasd_restore_device(device);
+		return 1;
+	}
+	dasd_schedule_device_bh(device);
+	if (device->block)
+		dasd_schedule_block_bh(device->block);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(dasd_generic_path_operational);
+
 int dasd_generic_notify(struct ccw_device *cdev, int event)
 {
 	struct dasd_device *device;
-	struct dasd_ccw_req *cqr;
 	int ret;
 
 	device = dasd_device_from_cdev_locked(cdev);
@@ -2602,41 +2718,64 @@
 	case CIO_GONE:
 	case CIO_BOXED:
 	case CIO_NO_PATH:
-		/* First of all call extended error reporting. */
-		dasd_eer_write(device, NULL, DASD_EER_NOPATH);
-
-		if (device->state < DASD_STATE_BASIC)
-			break;
-		/* Device is active. We want to keep it. */
-		list_for_each_entry(cqr, &device->ccw_queue, devlist)
-			if (cqr->status == DASD_CQR_IN_IO) {
-				cqr->status = DASD_CQR_QUEUED;
-				cqr->retries++;
-			}
-		dasd_device_set_stop_bits(device, DASD_STOPPED_DC_WAIT);
-		dasd_device_clear_timer(device);
-		dasd_schedule_device_bh(device);
-		ret = 1;
+		device->path_data.opm = 0;
+		device->path_data.ppm = 0;
+		device->path_data.npm = 0;
+		ret = dasd_generic_last_path_gone(device);
 		break;
 	case CIO_OPER:
-		/* FIXME: add a sanity check. */
-		dasd_device_remove_stop_bits(device, DASD_STOPPED_DC_WAIT);
-		if (device->stopped & DASD_UNRESUMED_PM) {
-			dasd_device_remove_stop_bits(device, DASD_UNRESUMED_PM);
-			dasd_restore_device(device);
-			ret = 1;
-			break;
-		}
-		dasd_schedule_device_bh(device);
-		if (device->block)
-			dasd_schedule_block_bh(device->block);
 		ret = 1;
+		if (device->path_data.opm)
+			ret = dasd_generic_path_operational(device);
 		break;
 	}
 	dasd_put_device(device);
 	return ret;
 }
 
+void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
+{
+	int chp;
+	__u8 oldopm, eventlpm;
+	struct dasd_device *device;
+
+	device = dasd_device_from_cdev_locked(cdev);
+	if (IS_ERR(device))
+		return;
+	for (chp = 0; chp < 8; chp++) {
+		eventlpm = 0x80 >> chp;
+		if (path_event[chp] & PE_PATH_GONE) {
+			oldopm = device->path_data.opm;
+			device->path_data.opm &= ~eventlpm;
+			device->path_data.ppm &= ~eventlpm;
+			device->path_data.npm &= ~eventlpm;
+			if (oldopm && !device->path_data.opm)
+				dasd_generic_last_path_gone(device);
+		}
+		if (path_event[chp] & PE_PATH_AVAILABLE) {
+			device->path_data.opm &= ~eventlpm;
+			device->path_data.ppm &= ~eventlpm;
+			device->path_data.npm &= ~eventlpm;
+			device->path_data.tbvpm |= eventlpm;
+			dasd_schedule_device_bh(device);
+		}
+	}
+	dasd_put_device(device);
+}
+EXPORT_SYMBOL_GPL(dasd_generic_path_event);
+
+int dasd_generic_verify_path(struct dasd_device *device, __u8 lpm)
+{
+	if (!device->path_data.opm && lpm) {
+		device->path_data.opm = lpm;
+		dasd_generic_path_operational(device);
+	} else
+		device->path_data.opm |= lpm;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dasd_generic_verify_path);
+
+
 int dasd_generic_pm_freeze(struct ccw_device *cdev)
 {
 	struct dasd_ccw_req *cqr, *n;
@@ -2646,6 +2785,10 @@
 
 	if (IS_ERR(device))
 		return PTR_ERR(device);
+
+	if (device->discipline->freeze)
+		rc = device->discipline->freeze(device);
+
 	/* disallow new I/O  */
 	dasd_device_set_stop_bits(device, DASD_STOPPED_PM);
 	/* clear active requests */
@@ -2682,9 +2825,6 @@
 	list_splice_tail(&freeze_queue, &device->ccw_queue);
 	spin_unlock_irq(get_ccwdev_lock(cdev));
 
-	if (device->discipline->freeze)
-		rc = device->discipline->freeze(device);
-
 	dasd_put_device(device);
 	return rc;
 }
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 968c76c..1654a24 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -152,9 +152,9 @@
 	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
 	opm = ccw_device_get_path_mask(device->cdev);
 	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
-	//FIXME: start with get_opm ?
 	if (erp->lpm == 0)
-		erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);
+		erp->lpm = device->path_data.opm &
+			~(erp->irb.esw.esw0.sublog.lpum);
 	else
 		erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum);
 
@@ -270,10 +270,11 @@
 {
 	erp->function = dasd_3990_erp_action_1;
 	dasd_3990_erp_alternate_path(erp);
-	if (erp->status == DASD_CQR_FAILED) {
+	if (erp->status == DASD_CQR_FAILED &&
+	    !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) {
 		erp->status = DASD_CQR_FILLED;
 		erp->retries = 10;
-		erp->lpm = LPM_ANYPATH;
+		erp->lpm = erp->startdev->path_data.opm;
 		erp->function = dasd_3990_erp_action_1_sec;
 	}
 	return erp;
@@ -1907,15 +1908,14 @@
 static void
 dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
 {
-
 	if (sense[25] & DASD_SENSE_BIT_3) {
 		dasd_3990_erp_alternate_path(erp);
 
-		if (erp->status == DASD_CQR_FAILED) {
+		if (erp->status == DASD_CQR_FAILED &&
+		    !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) {
 			/* reset the lpm and the status to be able to
 			 * try further actions. */
-
-			erp->lpm = 0;
+			erp->lpm = erp->startdev->path_data.opm;
 			erp->status = DASD_CQR_NEED_ERP;
 		}
 	}
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 8d41f3e..cb6a67b 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -208,6 +208,8 @@
 			features |= DASD_FEATURE_READONLY;
 		else if (len == 4 && !strncmp(str, "diag", 4))
 			features |= DASD_FEATURE_USEDIAG;
+		else if (len == 3 && !strncmp(str, "raw", 3))
+			features |= DASD_FEATURE_USERAW;
 		else if (len == 6 && !strncmp(str, "erplog", 6))
 			features |= DASD_FEATURE_ERPLOG;
 		else if (len == 8 && !strncmp(str, "failfast", 8))
@@ -639,6 +641,7 @@
 {
 	wake_up(&dasd_delete_wq);
 }
+EXPORT_SYMBOL_GPL(dasd_put_device_wake);
 
 /*
  * Return dasd_device structure associated with cdev.
@@ -856,7 +859,7 @@
 	spin_lock(&dasd_devmap_lock);
 	/* Changing diag discipline flag is only allowed in offline state. */
 	rc = count;
-	if (!devmap->device) {
+	if (!devmap->device && !(devmap->features & DASD_FEATURE_USERAW)) {
 		if (val)
 			devmap->features |= DASD_FEATURE_USEDIAG;
 		else
@@ -869,6 +872,56 @@
 
 static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
 
+/*
+ * use_raw controls whether the driver should give access to raw eckd data or
+ * operate in standard mode
+ */
+static ssize_t
+dasd_use_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct dasd_devmap *devmap;
+	int use_raw;
+
+	devmap = dasd_find_busid(dev_name(dev));
+	if (!IS_ERR(devmap))
+		use_raw = (devmap->features & DASD_FEATURE_USERAW) != 0;
+	else
+		use_raw = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USERAW) != 0;
+	return sprintf(buf, use_raw ? "1\n" : "0\n");
+}
+
+static ssize_t
+dasd_use_raw_store(struct device *dev, struct device_attribute *attr,
+		    const char *buf, size_t count)
+{
+	struct dasd_devmap *devmap;
+	ssize_t rc;
+	unsigned long val;
+
+	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
+	if (IS_ERR(devmap))
+		return PTR_ERR(devmap);
+
+	if ((strict_strtoul(buf, 10, &val) != 0) || val > 1)
+		return -EINVAL;
+
+	spin_lock(&dasd_devmap_lock);
+	/* Changing diag discipline flag is only allowed in offline state. */
+	rc = count;
+	if (!devmap->device && !(devmap->features & DASD_FEATURE_USEDIAG)) {
+		if (val)
+			devmap->features |= DASD_FEATURE_USERAW;
+		else
+			devmap->features &= ~DASD_FEATURE_USERAW;
+	} else
+		rc = -EPERM;
+	spin_unlock(&dasd_devmap_lock);
+	return rc;
+}
+
+static DEVICE_ATTR(raw_track_access, 0644, dasd_use_raw_show,
+		   dasd_use_raw_store);
+
 static ssize_t
 dasd_discipline_show(struct device *dev, struct device_attribute *attr,
 		     char *buf)
@@ -1126,6 +1179,103 @@
 
 static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store);
 
+static ssize_t dasd_reservation_policy_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct dasd_devmap *devmap;
+	int rc = 0;
+
+	devmap = dasd_find_busid(dev_name(dev));
+	if (IS_ERR(devmap)) {
+		rc = snprintf(buf, PAGE_SIZE, "ignore\n");
+	} else {
+		spin_lock(&dasd_devmap_lock);
+		if (devmap->features & DASD_FEATURE_FAILONSLCK)
+			rc = snprintf(buf, PAGE_SIZE, "fail\n");
+		else
+			rc = snprintf(buf, PAGE_SIZE, "ignore\n");
+		spin_unlock(&dasd_devmap_lock);
+	}
+	return rc;
+}
+
+static ssize_t dasd_reservation_policy_store(struct device *dev,
+					     struct device_attribute *attr,
+					     const char *buf, size_t count)
+{
+	struct dasd_devmap *devmap;
+	int rc;
+
+	devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
+	if (IS_ERR(devmap))
+		return PTR_ERR(devmap);
+	rc = 0;
+	spin_lock(&dasd_devmap_lock);
+	if (sysfs_streq("ignore", buf))
+		devmap->features &= ~DASD_FEATURE_FAILONSLCK;
+	else if (sysfs_streq("fail", buf))
+		devmap->features |= DASD_FEATURE_FAILONSLCK;
+	else
+		rc = -EINVAL;
+	if (devmap->device)
+		devmap->device->features = devmap->features;
+	spin_unlock(&dasd_devmap_lock);
+	if (rc)
+		return rc;
+	else
+		return count;
+}
+
+static DEVICE_ATTR(reservation_policy, 0644,
+		   dasd_reservation_policy_show, dasd_reservation_policy_store);
+
+static ssize_t dasd_reservation_state_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct dasd_device *device;
+	int rc = 0;
+
+	device = dasd_device_from_cdev(to_ccwdev(dev));
+	if (IS_ERR(device))
+		return snprintf(buf, PAGE_SIZE, "none\n");
+
+	if (test_bit(DASD_FLAG_IS_RESERVED, &device->flags))
+		rc = snprintf(buf, PAGE_SIZE, "reserved\n");
+	else if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags))
+		rc = snprintf(buf, PAGE_SIZE, "lost\n");
+	else
+		rc = snprintf(buf, PAGE_SIZE, "none\n");
+	dasd_put_device(device);
+	return rc;
+}
+
+static ssize_t dasd_reservation_state_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
+	struct dasd_device *device;
+	int rc = 0;
+
+	device = dasd_device_from_cdev(to_ccwdev(dev));
+	if (IS_ERR(device))
+		return -ENODEV;
+	if (sysfs_streq("reset", buf))
+		clear_bit(DASD_FLAG_LOCK_STOLEN, &device->flags);
+	else
+		rc = -EINVAL;
+	dasd_put_device(device);
+
+	if (rc)
+		return rc;
+	else
+		return count;
+}
+
+static DEVICE_ATTR(last_known_reservation_state, 0644,
+		   dasd_reservation_state_show, dasd_reservation_state_store);
+
 static struct attribute * dasd_attrs[] = {
 	&dev_attr_readonly.attr,
 	&dev_attr_discipline.attr,
@@ -1134,10 +1284,13 @@
 	&dev_attr_vendor.attr,
 	&dev_attr_uid.attr,
 	&dev_attr_use_diag.attr,
+	&dev_attr_raw_track_access.attr,
 	&dev_attr_eer_enabled.attr,
 	&dev_attr_erplog.attr,
 	&dev_attr_failfast.attr,
 	&dev_attr_expires.attr,
+	&dev_attr_reservation_policy.attr,
+	&dev_attr_last_known_reservation_state.attr,
 	NULL,
 };
 
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 266b34b..29143ed 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -10,6 +10,7 @@
 
 #define KMSG_COMPONENT "dasd"
 
+#include <linux/kernel_stat.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -238,6 +239,7 @@
 	addr_t ip;
 	int rc;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
 	switch (ext_int_code >> 24) {
 	case DASD_DIAG_CODE_31BIT:
 		ip = (addr_t) param32;
@@ -617,6 +619,7 @@
 	.ebcname = "DIAG",
 	.max_blocks = DIAG_MAX_BLOCKS,
 	.check_device = dasd_diag_check_device,
+	.verify_path = dasd_generic_verify_path,
 	.fill_geometry = dasd_diag_fill_geometry,
 	.start_IO = dasd_start_diag,
 	.term_IO = dasd_diag_term_IO,
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index bf61274a..318672d 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -54,6 +54,15 @@
 #define ECKD_F7(i) (i->factor7)
 #define ECKD_F8(i) (i->factor8)
 
+/*
+ * raw track access always map to 64k in memory
+ * so it maps to 16 blocks of 4k per track
+ */
+#define DASD_RAW_BLOCK_PER_TRACK 16
+#define DASD_RAW_BLOCKSIZE 4096
+/* 64k are 128 x 512 byte sectors  */
+#define DASD_RAW_SECTORS_PER_TRACK 128
+
 MODULE_LICENSE("GPL");
 
 static struct dasd_discipline dasd_eckd_discipline;
@@ -90,6 +99,18 @@
 } *dasd_reserve_req;
 static DEFINE_MUTEX(dasd_reserve_mutex);
 
+/* definitions for the path verification worker */
+struct path_verification_work_data {
+	struct work_struct worker;
+	struct dasd_device *device;
+	struct dasd_ccw_req cqr;
+	struct ccw1 ccw;
+	__u8 rcd_buffer[DASD_ECKD_RCD_DATA_SIZE];
+	int isglobal;
+	__u8 tbvpm;
+};
+static struct path_verification_work_data *path_verification_worker;
+static DEFINE_MUTEX(dasd_path_verification_mutex);
 
 /* initial attempt at a probe function. this can be simplified once
  * the other detection code is gone */
@@ -373,6 +394,23 @@
 		data->length = reclen;
 		data->operation.operation = 0x03;
 		break;
+	case DASD_ECKD_CCW_WRITE_FULL_TRACK:
+		data->operation.orientation = 0x0;
+		data->operation.operation = 0x3F;
+		data->extended_operation = 0x11;
+		data->length = 0;
+		data->extended_parameter_length = 0x02;
+		if (data->count > 8) {
+			data->extended_parameter[0] = 0xFF;
+			data->extended_parameter[1] = 0xFF;
+			data->extended_parameter[1] <<= (16 - count);
+		} else {
+			data->extended_parameter[0] = 0xFF;
+			data->extended_parameter[0] <<= (8 - count);
+			data->extended_parameter[1] = 0x00;
+		}
+		data->sector = 0xFF;
+		break;
 	case DASD_ECKD_CCW_WRITE_TRACK_DATA:
 		data->auxiliary.length_valid = 0x1;
 		data->length = reclen;	/* not tlf, as one might think */
@@ -396,6 +434,12 @@
 	case DASD_ECKD_CCW_READ_COUNT:
 		data->operation.operation = 0x06;
 		break;
+	case DASD_ECKD_CCW_READ_TRACK:
+		data->operation.orientation = 0x1;
+		data->operation.operation = 0x0C;
+		data->extended_parameter_length = 0;
+		data->sector = 0xFF;
+		break;
 	case DASD_ECKD_CCW_READ_TRACK_DATA:
 		data->auxiliary.length_valid = 0x1;
 		data->length = tlf;
@@ -439,10 +483,16 @@
 
 	ccw->cmd_code = DASD_ECKD_CCW_PFX;
 	ccw->flags = 0;
-	ccw->count = sizeof(*pfxdata);
-	ccw->cda = (__u32) __pa(pfxdata);
+	if (cmd == DASD_ECKD_CCW_WRITE_FULL_TRACK) {
+		ccw->count = sizeof(*pfxdata) + 2;
+		ccw->cda = (__u32) __pa(pfxdata);
+		memset(pfxdata, 0, sizeof(*pfxdata) + 2);
+	} else {
+		ccw->count = sizeof(*pfxdata);
+		ccw->cda = (__u32) __pa(pfxdata);
+		memset(pfxdata, 0, sizeof(*pfxdata));
+	}
 
-	memset(pfxdata, 0, sizeof(*pfxdata));
 	/* prefix data */
 	if (format > 1) {
 		DBF_DEV_EVENT(DBF_ERR, basedev,
@@ -476,6 +526,7 @@
 		dedata->mask.perm = 0x1;
 		dedata->attributes.operation = basepriv->attrib.operation;
 		break;
+	case DASD_ECKD_CCW_READ_TRACK:
 	case DASD_ECKD_CCW_READ_TRACK_DATA:
 		dedata->mask.perm = 0x1;
 		dedata->attributes.operation = basepriv->attrib.operation;
@@ -502,6 +553,11 @@
 		dedata->attributes.operation = DASD_BYPASS_CACHE;
 		rc = check_XRC_on_prefix(pfxdata, basedev);
 		break;
+	case DASD_ECKD_CCW_WRITE_FULL_TRACK:
+		dedata->mask.perm = 0x03;
+		dedata->attributes.operation = basepriv->attrib.operation;
+		dedata->blk_size = 0;
+		break;
 	case DASD_ECKD_CCW_WRITE_TRACK_DATA:
 		dedata->mask.perm = 0x02;
 		dedata->attributes.operation = basepriv->attrib.operation;
@@ -755,26 +811,27 @@
 	return -EINVAL;
 }
 
-static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
-						    void *rcd_buffer,
-						    struct ciw *ciw, __u8 lpm)
+static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device,
+				   struct dasd_ccw_req *cqr,
+				   __u8 *rcd_buffer,
+				   __u8 lpm)
 {
-	struct dasd_ccw_req *cqr;
 	struct ccw1 *ccw;
-
-	cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* RCD */, ciw->count,
-				   device);
-
-	if (IS_ERR(cqr)) {
-		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
-			      "Could not allocate RCD request");
-		return cqr;
-	}
+	/*
+	 * buffer has to start with EBCDIC "V1.0" to show
+	 * support for virtual device SNEQ
+	 */
+	rcd_buffer[0] = 0xE5;
+	rcd_buffer[1] = 0xF1;
+	rcd_buffer[2] = 0x4B;
+	rcd_buffer[3] = 0xF0;
 
 	ccw = cqr->cpaddr;
-	ccw->cmd_code = ciw->cmd;
+	ccw->cmd_code = DASD_ECKD_CCW_RCD;
+	ccw->flags = 0;
 	ccw->cda = (__u32)(addr_t)rcd_buffer;
-	ccw->count = ciw->count;
+	ccw->count = DASD_ECKD_RCD_DATA_SIZE;
+	cqr->magic = DASD_ECKD_MAGIC;
 
 	cqr->startdev = device;
 	cqr->memdev = device;
@@ -784,7 +841,30 @@
 	cqr->retries = 256;
 	cqr->buildclk = get_clock();
 	cqr->status = DASD_CQR_FILLED;
-	return cqr;
+	set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
+}
+
+static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
+					   struct dasd_ccw_req *cqr,
+					   __u8 *rcd_buffer,
+					   __u8 lpm)
+{
+	struct ciw *ciw;
+	int rc;
+	/*
+	 * sanity check: scan for RCD command in extended SenseID data
+	 * some devices do not support RCD
+	 */
+	ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
+	if (!ciw || ciw->cmd != DASD_ECKD_CCW_RCD)
+		return -EOPNOTSUPP;
+
+	dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buffer, lpm);
+	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+	set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
+	cqr->retries = 5;
+	rc = dasd_sleep_on_immediatly(cqr);
+	return rc;
 }
 
 static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
@@ -797,32 +877,29 @@
 	struct dasd_ccw_req *cqr;
 
 	/*
-	 * scan for RCD command in extended SenseID data
+	 * sanity check: scan for RCD command in extended SenseID data
+	 * some devices do not support RCD
 	 */
 	ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
-	if (!ciw || ciw->cmd == 0) {
+	if (!ciw || ciw->cmd != DASD_ECKD_CCW_RCD) {
 		ret = -EOPNOTSUPP;
 		goto out_error;
 	}
-	rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+	rcd_buf = kzalloc(DASD_ECKD_RCD_DATA_SIZE, GFP_KERNEL | GFP_DMA);
 	if (!rcd_buf) {
 		ret = -ENOMEM;
 		goto out_error;
 	}
-
-	/*
-	 * buffer has to start with EBCDIC "V1.0" to show
-	 * support for virtual device SNEQ
-	 */
-	rcd_buf[0] = 0xE5;
-	rcd_buf[1] = 0xF1;
-	rcd_buf[2] = 0x4B;
-	rcd_buf[3] = 0xF0;
-	cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
+	cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* RCD */,
+				   0, /* use rcd_buf as data ara */
+				   device);
 	if (IS_ERR(cqr)) {
-		ret =  PTR_ERR(cqr);
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+			      "Could not allocate RCD request");
+		ret = -ENOMEM;
 		goto out_error;
 	}
+	dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buf, lpm);
 	ret = dasd_sleep_on(cqr);
 	/*
 	 * on success we update the user input parms
@@ -831,7 +908,7 @@
 	if (ret)
 		goto out_error;
 
-	*rcd_buffer_size = ciw->count;
+	*rcd_buffer_size = DASD_ECKD_RCD_DATA_SIZE;
 	*rcd_buffer = rcd_buf;
 	return 0;
 out_error:
@@ -901,18 +978,18 @@
 	void *conf_data;
 	int conf_len, conf_data_saved;
 	int rc;
-	__u8 lpm;
+	__u8 lpm, opm;
 	struct dasd_eckd_private *private;
-	struct dasd_eckd_path *path_data;
+	struct dasd_path *path_data;
 
 	private = (struct dasd_eckd_private *) device->private;
-	path_data = (struct dasd_eckd_path *) &private->path_data;
-	path_data->opm = ccw_device_get_path_mask(device->cdev);
+	path_data = &device->path_data;
+	opm = ccw_device_get_path_mask(device->cdev);
 	lpm = 0x80;
 	conf_data_saved = 0;
 	/* get configuration data per operational path */
 	for (lpm = 0x80; lpm; lpm>>= 1) {
-		if (lpm & path_data->opm){
+		if (lpm & opm) {
 			rc = dasd_eckd_read_conf_lpm(device, &conf_data,
 						     &conf_len, lpm);
 			if (rc && rc != -EOPNOTSUPP) {	/* -EOPNOTSUPP is ok */
@@ -925,6 +1002,8 @@
 				DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
 						"No configuration data "
 						"retrieved");
+				/* no further analysis possible */
+				path_data->opm |= lpm;
 				continue;	/* no error */
 			}
 			/* save first valid configuration data */
@@ -948,6 +1027,7 @@
 				path_data->ppm |= lpm;
 				break;
 			}
+			path_data->opm |= lpm;
 			if (conf_data != private->conf_data)
 				kfree(conf_data);
 		}
@@ -955,6 +1035,140 @@
 	return 0;
 }
 
+static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
+{
+	struct dasd_eckd_private *private;
+	int mdc;
+	u32 fcx_max_data;
+
+	private = (struct dasd_eckd_private *) device->private;
+	if (private->fcx_max_data) {
+		mdc = ccw_device_get_mdc(device->cdev, lpm);
+		if ((mdc < 0)) {
+			dev_warn(&device->cdev->dev,
+				 "Detecting the maximum data size for zHPF "
+				 "requests failed (rc=%d) for a new path %x\n",
+				 mdc, lpm);
+			return mdc;
+		}
+		fcx_max_data = mdc * FCX_MAX_DATA_FACTOR;
+		if (fcx_max_data < private->fcx_max_data) {
+			dev_warn(&device->cdev->dev,
+				 "The maximum data size for zHPF requests %u "
+				 "on a new path %x is below the active maximum "
+				 "%u\n", fcx_max_data, lpm,
+				 private->fcx_max_data);
+			return -EACCES;
+		}
+	}
+	return 0;
+}
+
+static void do_path_verification_work(struct work_struct *work)
+{
+	struct path_verification_work_data *data;
+	struct dasd_device *device;
+	__u8 lpm, opm, npm, ppm, epm;
+	unsigned long flags;
+	int rc;
+
+	data = container_of(work, struct path_verification_work_data, worker);
+	device = data->device;
+
+	opm = 0;
+	npm = 0;
+	ppm = 0;
+	epm = 0;
+	for (lpm = 0x80; lpm; lpm >>= 1) {
+		if (lpm & data->tbvpm) {
+			memset(data->rcd_buffer, 0, sizeof(data->rcd_buffer));
+			memset(&data->cqr, 0, sizeof(data->cqr));
+			data->cqr.cpaddr = &data->ccw;
+			rc = dasd_eckd_read_conf_immediately(device, &data->cqr,
+							     data->rcd_buffer,
+							     lpm);
+			if (!rc) {
+				switch (dasd_eckd_path_access(data->rcd_buffer,
+						     DASD_ECKD_RCD_DATA_SIZE)) {
+				case 0x02:
+					npm |= lpm;
+					break;
+				case 0x03:
+					ppm |= lpm;
+					break;
+				}
+				opm |= lpm;
+			} else if (rc == -EOPNOTSUPP) {
+				DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+				       "path verification: No configuration "
+				       "data retrieved");
+				opm |= lpm;
+			} else if (rc == -EAGAIN) {
+				DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+					"path verification: device is stopped,"
+					" try again later");
+				epm |= lpm;
+			} else {
+				dev_warn(&device->cdev->dev,
+					 "Reading device feature codes failed "
+					 "(rc=%d) for new path %x\n", rc, lpm);
+				continue;
+			}
+			if (verify_fcx_max_data(device, lpm)) {
+				opm &= ~lpm;
+				npm &= ~lpm;
+				ppm &= ~lpm;
+			}
+		}
+	}
+	/*
+	 * There is a small chance that a path is lost again between
+	 * above path verification and the following modification of
+	 * the device opm mask. We could avoid that race here by using
+	 * yet another path mask, but we rather deal with this unlikely
+	 * situation in dasd_start_IO.
+	 */
+	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+	if (!device->path_data.opm && opm) {
+		device->path_data.opm = opm;
+		dasd_generic_path_operational(device);
+	} else
+		device->path_data.opm |= opm;
+	device->path_data.npm |= npm;
+	device->path_data.ppm |= ppm;
+	device->path_data.tbvpm |= epm;
+	spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
+
+	dasd_put_device(device);
+	if (data->isglobal)
+		mutex_unlock(&dasd_path_verification_mutex);
+	else
+		kfree(data);
+}
+
+static int dasd_eckd_verify_path(struct dasd_device *device, __u8 lpm)
+{
+	struct path_verification_work_data *data;
+
+	data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA);
+	if (!data) {
+		if (mutex_trylock(&dasd_path_verification_mutex)) {
+			data = path_verification_worker;
+			data->isglobal = 1;
+		} else
+			return -ENOMEM;
+	} else {
+		memset(data, 0, sizeof(*data));
+		data->isglobal = 0;
+	}
+	INIT_WORK(&data->worker, do_path_verification_work);
+	dasd_get_device(device);
+	data->device = device;
+	data->tbvpm = lpm;
+	schedule_work(&data->worker);
+	return 0;
+}
+
 static int dasd_eckd_read_features(struct dasd_device *device)
 {
 	struct dasd_psf_prssd_data *prssdp;
@@ -1105,6 +1319,37 @@
 			"returned rc=%d", private->uid.ssid, rc);
 }
 
+static u32 get_fcx_max_data(struct dasd_device *device)
+{
+#if defined(CONFIG_64BIT)
+	int tpm, mdc;
+	int fcx_in_css, fcx_in_gneq, fcx_in_features;
+	struct dasd_eckd_private *private;
+
+	if (dasd_nofcx)
+		return 0;
+	/* is transport mode supported? */
+	private = (struct dasd_eckd_private *) device->private;
+	fcx_in_css = css_general_characteristics.fcx;
+	fcx_in_gneq = private->gneq->reserved2[7] & 0x04;
+	fcx_in_features = private->features.feature[40] & 0x80;
+	tpm = fcx_in_css && fcx_in_gneq && fcx_in_features;
+
+	if (!tpm)
+		return 0;
+
+	mdc = ccw_device_get_mdc(device->cdev, 0);
+	if (mdc < 0) {
+		dev_warn(&device->cdev->dev, "Detecting the maximum supported"
+			 " data size for zHPF requests failed\n");
+		return 0;
+	} else
+		return mdc * FCX_MAX_DATA_FACTOR;
+#else
+	return 0;
+#endif
+}
+
 /*
  * Check device characteristics.
  * If the device is accessible using ECKD discipline, the device is enabled.
@@ -1223,6 +1468,8 @@
 	else
 		private->real_cyl = private->rdc_data.no_cyl;
 
+	private->fcx_max_data = get_fcx_max_data(device);
+
 	readonly = dasd_device_is_ro(device);
 	if (readonly)
 		set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
@@ -1404,6 +1651,13 @@
 		dasd_sfree_request(init_cqr, device);
 	}
 
+	if (device->features & DASD_FEATURE_USERAW) {
+		block->bp_block = DASD_RAW_BLOCKSIZE;
+		blk_per_trk = DASD_RAW_BLOCK_PER_TRACK;
+		block->s2b_shift = 3;
+		goto raw;
+	}
+
 	if (status == INIT_CQR_UNFORMATTED) {
 		dev_warn(&device->cdev->dev, "The DASD is not formatted\n");
 		return -EMEDIUMTYPE;
@@ -1441,6 +1695,7 @@
 			dev_warn(&device->cdev->dev,
 				 "Track 0 has no records following the VTOC\n");
 	}
+
 	if (count_area != NULL && count_area->kl == 0) {
 		/* we found notthing violating our disk layout */
 		if (dasd_check_blocksize(count_area->dl) == 0)
@@ -1456,6 +1711,8 @@
 		block->s2b_shift++;
 
 	blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block);
+
+raw:
 	block->blocks = (private->real_cyl *
 			  private->rdc_data.trk_per_cyl *
 			  blk_per_trk);
@@ -1716,6 +1973,7 @@
 	if (cqr->block && (cqr->startdev != cqr->block->base)) {
 		dasd_eckd_reset_ccw_to_base_io(cqr);
 		cqr->startdev = cqr->block->base;
+		cqr->lpm = cqr->block->base->path_data.opm;
 	}
 };
 
@@ -1744,9 +2002,9 @@
 	return dasd_default_erp_postaction;
 }
 
-
-static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
-						   struct irb *irb)
+static void dasd_eckd_check_for_device_change(struct dasd_device *device,
+					      struct dasd_ccw_req *cqr,
+					      struct irb *irb)
 {
 	char mask;
 	char *sense = NULL;
@@ -1770,40 +2028,41 @@
 			/* schedule worker to reload device */
 			dasd_reload_device(device);
 		}
-
 		dasd_generic_handle_state_change(device);
 		return;
 	}
 
-	/* summary unit check */
 	sense = dasd_get_sense(irb);
-	if (sense && (sense[7] == 0x0D) &&
+	if (!sense)
+		return;
+
+	/* summary unit check */
+	if ((sense[7] == 0x0D) &&
 	    (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) {
 		dasd_alias_handle_summary_unit_check(device, irb);
 		return;
 	}
 
 	/* service information message SIM */
-	if (sense && !(sense[27] & DASD_SENSE_BIT_0) &&
+	if (!cqr && !(sense[27] & DASD_SENSE_BIT_0) &&
 	    ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) {
 		dasd_3990_erp_handle_sim(device, sense);
-		dasd_schedule_device_bh(device);
 		return;
 	}
 
-	if ((scsw_cc(&irb->scsw) == 1) && !sense &&
-	    (scsw_fctl(&irb->scsw) == SCSW_FCTL_START_FUNC) &&
-	    (scsw_actl(&irb->scsw) == SCSW_ACTL_START_PEND) &&
-	    (scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND)) {
-		/* fake irb do nothing, they are handled elsewhere */
-		dasd_schedule_device_bh(device);
-		return;
+	/* loss of device reservation is handled via base devices only
+	 * as alias devices may be used with several bases
+	 */
+	if (device->block && (sense[7] == 0x3F) &&
+	    (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
+	    test_bit(DASD_FLAG_IS_RESERVED, &device->flags)) {
+		if (device->features & DASD_FEATURE_FAILONSLCK)
+			set_bit(DASD_FLAG_LOCK_STOLEN, &device->flags);
+		clear_bit(DASD_FLAG_IS_RESERVED, &device->flags);
+		dev_err(&device->cdev->dev,
+			"The device reservation was lost\n");
 	}
-
-	dasd_schedule_device_bh(device);
-	return;
-};
-
+}
 
 static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
 					       struct dasd_device *startdev,
@@ -1984,7 +2243,7 @@
 	cqr->memdev = startdev;
 	cqr->block = block;
 	cqr->expires = startdev->default_expires * HZ;	/* default 5 minutes */
-	cqr->lpm = private->path_data.ppm;
+	cqr->lpm = startdev->path_data.ppm;
 	cqr->retries = 256;
 	cqr->buildclk = get_clock();
 	cqr->status = DASD_CQR_FILLED;
@@ -2161,7 +2420,7 @@
 	cqr->memdev = startdev;
 	cqr->block = block;
 	cqr->expires = startdev->default_expires * HZ;	/* default 5 minutes */
-	cqr->lpm = private->path_data.ppm;
+	cqr->lpm = startdev->path_data.ppm;
 	cqr->retries = 256;
 	cqr->buildclk = get_clock();
 	cqr->status = DASD_CQR_FILLED;
@@ -2326,6 +2585,12 @@
 	struct tidaw *last_tidaw = NULL;
 	int itcw_op;
 	size_t itcw_size;
+	u8 tidaw_flags;
+	unsigned int seg_len, part_len, len_to_track_end;
+	unsigned char new_track;
+	sector_t recid, trkid;
+	unsigned int offs;
+	unsigned int count, count_to_trk_end;
 
 	basedev = block->base;
 	private = (struct dasd_eckd_private *) basedev->private;
@@ -2341,12 +2606,16 @@
 	/* trackbased I/O needs address all memory via TIDAWs,
 	 * not just for 64 bit addresses. This allows us to map
 	 * each segment directly to one tidaw.
+	 * In the case of write requests, additional tidaws may
+	 * be needed when a segment crosses a track boundary.
 	 */
 	trkcount = last_trk - first_trk + 1;
 	ctidaw = 0;
 	rq_for_each_segment(bv, req, iter) {
 		++ctidaw;
 	}
+	if (rq_data_dir(req) == WRITE)
+		ctidaw += (last_trk - first_trk);
 
 	/* Allocate the ccw request. */
 	itcw_size = itcw_calc_size(0, ctidaw, 0);
@@ -2354,15 +2623,6 @@
 	if (IS_ERR(cqr))
 		return cqr;
 
-	cqr->cpmode = 1;
-	cqr->startdev = startdev;
-	cqr->memdev = startdev;
-	cqr->block = block;
-	cqr->expires = 100*HZ;
-	cqr->buildclk = get_clock();
-	cqr->status = DASD_CQR_FILLED;
-	cqr->retries = 10;
-
 	/* transfer length factor: how many bytes to read from the last track */
 	if (first_trk == last_trk)
 		tlf = last_offs - first_offs + 1;
@@ -2371,8 +2631,11 @@
 	tlf *= blksize;
 
 	itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0);
+	if (IS_ERR(itcw)) {
+		dasd_sfree_request(cqr, startdev);
+		return ERR_PTR(-EINVAL);
+	}
 	cqr->cpaddr = itcw_get_tcw(itcw);
-
 	if (prepare_itcw(itcw, first_trk, last_trk,
 			 cmd, basedev, startdev,
 			 first_offs + 1,
@@ -2385,31 +2648,69 @@
 		dasd_sfree_request(cqr, startdev);
 		return ERR_PTR(-EAGAIN);
 	}
-
 	/*
 	 * A tidaw can address 4k of memory, but must not cross page boundaries
 	 * We can let the block layer handle this by setting
 	 * blk_queue_segment_boundary to page boundaries and
 	 * blk_max_segment_size to page size when setting up the request queue.
+	 * For write requests, a TIDAW must not cross track boundaries, because
+	 * we have to set the CBC flag on the last tidaw for each track.
 	 */
-	rq_for_each_segment(bv, req, iter) {
-		dst = page_address(bv->bv_page) + bv->bv_offset;
-		last_tidaw = itcw_add_tidaw(itcw, 0x00, dst, bv->bv_len);
-		if (IS_ERR(last_tidaw))
-			return (struct dasd_ccw_req *)last_tidaw;
+	if (rq_data_dir(req) == WRITE) {
+		new_track = 1;
+		recid = first_rec;
+		rq_for_each_segment(bv, req, iter) {
+			dst = page_address(bv->bv_page) + bv->bv_offset;
+			seg_len = bv->bv_len;
+			while (seg_len) {
+				if (new_track) {
+					trkid = recid;
+					offs = sector_div(trkid, blk_per_trk);
+					count_to_trk_end = blk_per_trk - offs;
+					count = min((last_rec - recid + 1),
+						    (sector_t)count_to_trk_end);
+					len_to_track_end = count * blksize;
+					recid += count;
+					new_track = 0;
+				}
+				part_len = min(seg_len, len_to_track_end);
+				seg_len -= part_len;
+				len_to_track_end -= part_len;
+				/* We need to end the tidaw at track end */
+				if (!len_to_track_end) {
+					new_track = 1;
+					tidaw_flags = TIDAW_FLAGS_INSERT_CBC;
+				} else
+					tidaw_flags = 0;
+				last_tidaw = itcw_add_tidaw(itcw, tidaw_flags,
+							    dst, part_len);
+				if (IS_ERR(last_tidaw))
+					return ERR_PTR(-EINVAL);
+				dst += part_len;
+			}
+		}
+	} else {
+		rq_for_each_segment(bv, req, iter) {
+			dst = page_address(bv->bv_page) + bv->bv_offset;
+			last_tidaw = itcw_add_tidaw(itcw, 0x00,
+						    dst, bv->bv_len);
+			if (IS_ERR(last_tidaw))
+				return ERR_PTR(-EINVAL);
+		}
 	}
-
-	last_tidaw->flags |= 0x80;
+	last_tidaw->flags |= TIDAW_FLAGS_LAST;
+	last_tidaw->flags &= ~TIDAW_FLAGS_INSERT_CBC;
 	itcw_finalize(itcw);
 
 	if (blk_noretry_request(req) ||
 	    block->base->features & DASD_FEATURE_FAILFAST)
 		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+	cqr->cpmode = 1;
 	cqr->startdev = startdev;
 	cqr->memdev = startdev;
 	cqr->block = block;
 	cqr->expires = startdev->default_expires * HZ;	/* default 5 minutes */
-	cqr->lpm = private->path_data.ppm;
+	cqr->lpm = startdev->path_data.ppm;
 	cqr->retries = 256;
 	cqr->buildclk = get_clock();
 	cqr->status = DASD_CQR_FILLED;
@@ -2420,11 +2721,9 @@
 					       struct dasd_block *block,
 					       struct request *req)
 {
-	int tpm, cmdrtd, cmdwtd;
+	int cmdrtd, cmdwtd;
 	int use_prefix;
-#if defined(CONFIG_64BIT)
-	int fcx_in_css, fcx_in_gneq, fcx_in_features;
-#endif
+	int fcx_multitrack;
 	struct dasd_eckd_private *private;
 	struct dasd_device *basedev;
 	sector_t first_rec, last_rec;
@@ -2432,6 +2731,7 @@
 	unsigned int first_offs, last_offs;
 	unsigned int blk_per_trk, blksize;
 	int cdlspecial;
+	unsigned int data_size;
 	struct dasd_ccw_req *cqr;
 
 	basedev = block->base;
@@ -2450,15 +2750,11 @@
 	last_offs = sector_div(last_trk, blk_per_trk);
 	cdlspecial = (private->uses_cdl && first_rec < 2*blk_per_trk);
 
-	/* is transport mode supported? */
-#if defined(CONFIG_64BIT)
-	fcx_in_css = css_general_characteristics.fcx;
-	fcx_in_gneq = private->gneq->reserved2[7] & 0x04;
-	fcx_in_features = private->features.feature[40] & 0x80;
-	tpm = fcx_in_css && fcx_in_gneq && fcx_in_features;
-#else
-	tpm = 0;
-#endif
+	fcx_multitrack = private->features.feature[40] & 0x20;
+	data_size = blk_rq_bytes(req);
+	/* tpm write request add CBC data on each track boundary */
+	if (rq_data_dir(req) == WRITE)
+		data_size += (last_trk - first_trk) * 4;
 
 	/* is read track data and write track data in command mode supported? */
 	cmdrtd = private->features.feature[9] & 0x20;
@@ -2468,13 +2764,15 @@
 	cqr = NULL;
 	if (cdlspecial || dasd_page_cache) {
 		/* do nothing, just fall through to the cmd mode single case */
-	} else if (!dasd_nofcx && tpm && (first_trk == last_trk)) {
+	} else if ((data_size <= private->fcx_max_data)
+		   && (fcx_multitrack || (first_trk == last_trk))) {
 		cqr = dasd_eckd_build_cp_tpm_track(startdev, block, req,
 						    first_rec, last_rec,
 						    first_trk, last_trk,
 						    first_offs, last_offs,
 						    blk_per_trk, blksize);
-		if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN)
+		if (IS_ERR(cqr) && (PTR_ERR(cqr) != -EAGAIN) &&
+		    (PTR_ERR(cqr) != -ENOMEM))
 			cqr = NULL;
 	} else if (use_prefix &&
 		   (((rq_data_dir(req) == READ) && cmdrtd) ||
@@ -2484,7 +2782,8 @@
 						   first_trk, last_trk,
 						   first_offs, last_offs,
 						   blk_per_trk, blksize);
-		if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN)
+		if (IS_ERR(cqr) && (PTR_ERR(cqr) != -EAGAIN) &&
+		    (PTR_ERR(cqr) != -ENOMEM))
 			cqr = NULL;
 	}
 	if (!cqr)
@@ -2496,6 +2795,135 @@
 	return cqr;
 }
 
+static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev,
+					       struct dasd_block *block,
+					       struct request *req)
+{
+	struct dasd_eckd_private *private;
+	unsigned long *idaws;
+	struct dasd_device *basedev;
+	struct dasd_ccw_req *cqr;
+	struct ccw1 *ccw;
+	struct req_iterator iter;
+	struct bio_vec *bv;
+	char *dst;
+	unsigned char cmd;
+	unsigned int trkcount;
+	unsigned int seg_len, len_to_track_end;
+	unsigned int first_offs;
+	unsigned int cidaw, cplength, datasize;
+	sector_t first_trk, last_trk;
+	unsigned int pfx_datasize;
+
+	/*
+	 * raw track access needs to be mutiple of 64k and on 64k boundary
+	 */
+	if ((blk_rq_pos(req) % DASD_RAW_SECTORS_PER_TRACK) != 0) {
+		cqr = ERR_PTR(-EINVAL);
+		goto out;
+	}
+	if (((blk_rq_pos(req) + blk_rq_sectors(req)) %
+	     DASD_RAW_SECTORS_PER_TRACK) != 0) {
+		cqr = ERR_PTR(-EINVAL);
+		goto out;
+	}
+
+	first_trk = blk_rq_pos(req) / DASD_RAW_SECTORS_PER_TRACK;
+	last_trk = (blk_rq_pos(req) + blk_rq_sectors(req) - 1) /
+		DASD_RAW_SECTORS_PER_TRACK;
+	trkcount = last_trk - first_trk + 1;
+	first_offs = 0;
+	basedev = block->base;
+	private = (struct dasd_eckd_private *) basedev->private;
+
+	if (rq_data_dir(req) == READ)
+		cmd = DASD_ECKD_CCW_READ_TRACK;
+	else if (rq_data_dir(req) == WRITE)
+		cmd = DASD_ECKD_CCW_WRITE_FULL_TRACK;
+	else {
+		cqr = ERR_PTR(-EINVAL);
+		goto out;
+	}
+
+	/*
+	 * Raw track based I/O needs IDAWs for each page,
+	 * and not just for 64 bit addresses.
+	 */
+	cidaw = trkcount * DASD_RAW_BLOCK_PER_TRACK;
+
+	/* 1x prefix + one read/write ccw per track */
+	cplength = 1 + trkcount;
+
+	/*
+	 * struct PFX_eckd_data has up to 2 byte as extended parameter
+	 * this is needed for write full track and has to be mentioned
+	 * seperately
+	 * add 8 instead of 2 to keep 8 byte boundary
+	 */
+	pfx_datasize = sizeof(struct PFX_eckd_data) + 8;
+
+	datasize = pfx_datasize + cidaw * sizeof(unsigned long long);
+
+	/* Allocate the ccw request. */
+	cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength,
+				   datasize, startdev);
+	if (IS_ERR(cqr))
+		goto out;
+	ccw = cqr->cpaddr;
+
+	if (prefix_LRE(ccw++, cqr->data, first_trk, last_trk, cmd,
+		       basedev, startdev, 1 /* format */, first_offs + 1,
+		       trkcount, 0, 0) == -EAGAIN) {
+		/* Clock not in sync and XRC is enabled.
+		 * Try again later.
+		 */
+		dasd_sfree_request(cqr, startdev);
+		cqr = ERR_PTR(-EAGAIN);
+		goto out;
+	}
+
+	idaws = (unsigned long *)(cqr->data + pfx_datasize);
+
+	len_to_track_end = 0;
+
+	rq_for_each_segment(bv, req, iter) {
+		dst = page_address(bv->bv_page) + bv->bv_offset;
+		seg_len = bv->bv_len;
+		if (!len_to_track_end) {
+			ccw[-1].flags |= CCW_FLAG_CC;
+			ccw->cmd_code = cmd;
+			/* maximum 3390 track size */
+			ccw->count = 57326;
+			/* 64k map to one track */
+			len_to_track_end = 65536;
+			ccw->cda = (__u32)(addr_t)idaws;
+			ccw->flags |= CCW_FLAG_IDA;
+			ccw->flags |= CCW_FLAG_SLI;
+			ccw++;
+		}
+		len_to_track_end -= seg_len;
+		idaws = idal_create_words(idaws, dst, seg_len);
+	}
+
+	if (blk_noretry_request(req) ||
+	    block->base->features & DASD_FEATURE_FAILFAST)
+		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+	cqr->startdev = startdev;
+	cqr->memdev = startdev;
+	cqr->block = block;
+	cqr->expires = startdev->default_expires * HZ;
+	cqr->lpm = startdev->path_data.ppm;
+	cqr->retries = 256;
+	cqr->buildclk = get_clock();
+	cqr->status = DASD_CQR_FILLED;
+
+	if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN)
+		cqr = NULL;
+out:
+	return cqr;
+}
+
+
 static int
 dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
 {
@@ -2600,7 +3028,10 @@
 
 	spin_lock_irqsave(get_ccwdev_lock(startdev->cdev), flags);
 	private->count++;
-	cqr = dasd_eckd_build_cp(startdev, block, req);
+	if ((base->features & DASD_FEATURE_USERAW))
+		cqr = dasd_raw_build_cp(startdev, block, req);
+	else
+		cqr = dasd_eckd_build_cp(startdev, block, req);
 	if (IS_ERR(cqr))
 		private->count--;
 	spin_unlock_irqrestore(get_ccwdev_lock(startdev->cdev), flags);
@@ -2688,6 +3119,8 @@
 	cqr->status = DASD_CQR_FILLED;
 
 	rc = dasd_sleep_on_immediatly(cqr);
+	if (!rc)
+		clear_bit(DASD_FLAG_IS_RESERVED, &device->flags);
 
 	if (useglobal)
 		mutex_unlock(&dasd_reserve_mutex);
@@ -2741,6 +3174,8 @@
 	cqr->status = DASD_CQR_FILLED;
 
 	rc = dasd_sleep_on_immediatly(cqr);
+	if (!rc)
+		set_bit(DASD_FLAG_IS_RESERVED, &device->flags);
 
 	if (useglobal)
 		mutex_unlock(&dasd_reserve_mutex);
@@ -2793,6 +3228,8 @@
 	cqr->status = DASD_CQR_FILLED;
 
 	rc = dasd_sleep_on_immediatly(cqr);
+	if (!rc)
+		set_bit(DASD_FLAG_IS_RESERVED, &device->flags);
 
 	if (useglobal)
 		mutex_unlock(&dasd_reserve_mutex);
@@ -2845,6 +3282,7 @@
 	cqr->memdev = device;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
 	set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+	set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
 	cqr->retries = 5;
 	cqr->expires = 10 * HZ;
 	cqr->buildclk = get_clock();
@@ -3279,10 +3717,8 @@
 {
 	char *page;
 	int len, sl, sct, residual;
-
 	struct tsb *tsb;
-	u8 *sense;
-
+	u8 *sense, *rcq;
 
 	page = (char *) get_zeroed_page(GFP_ATOMIC);
 	if (page == NULL) {
@@ -3348,12 +3784,15 @@
 		case 2: /* ts_ddpc */
 			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
 			       " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc);
-			len += sprintf(page + len, KERN_ERR PRINTK_HEADER
-			       " tsb->tsa.ddpc.rcq:  ");
-			for (sl = 0; sl < 16; sl++) {
+			for (sl = 0; sl < 2; sl++) {
+				len += sprintf(page + len,
+					       KERN_ERR PRINTK_HEADER
+					       " tsb->tsa.ddpc.rcq %2d-%2d: ",
+					       (8 * sl), ((8 * sl) + 7));
+				rcq = tsb->tsa.ddpc.rcq;
 				for (sct = 0; sct < 8; sct++) {
 					len += sprintf(page + len, " %02x",
-						       tsb->tsa.ddpc.rcq[sl]);
+						       rcq[8 * sl + sct]);
 				}
 				len += sprintf(page + len, "\n");
 			}
@@ -3550,6 +3989,7 @@
 	.set_offline = dasd_generic_set_offline,
 	.set_online  = dasd_eckd_set_online,
 	.notify      = dasd_generic_notify,
+	.path_event  = dasd_generic_path_event,
 	.freeze      = dasd_generic_pm_freeze,
 	.thaw	     = dasd_generic_restore_device,
 	.restore     = dasd_generic_restore_device,
@@ -3573,10 +4013,11 @@
 	.owner = THIS_MODULE,
 	.name = "ECKD",
 	.ebcname = "ECKD",
-	.max_blocks = 240,
+	.max_blocks = 190,
 	.check_device = dasd_eckd_check_characteristics,
 	.uncheck_device = dasd_eckd_uncheck_device,
 	.do_analysis = dasd_eckd_do_analysis,
+	.verify_path = dasd_eckd_verify_path,
 	.ready_to_online = dasd_eckd_ready_to_online,
 	.online_to_ready = dasd_eckd_online_to_ready,
 	.fill_geometry = dasd_eckd_fill_geometry,
@@ -3586,7 +4027,7 @@
 	.format_device = dasd_eckd_format_device,
 	.erp_action = dasd_eckd_erp_action,
 	.erp_postaction = dasd_eckd_erp_postaction,
-	.handle_unsolicited_interrupt = dasd_eckd_handle_unsolicited_interrupt,
+	.check_for_device_change = dasd_eckd_check_for_device_change,
 	.build_cp = dasd_eckd_build_alias_cp,
 	.free_cp = dasd_eckd_free_alias_cp,
 	.dump_sense = dasd_eckd_dump_sense,
@@ -3609,11 +4050,19 @@
 				   GFP_KERNEL | GFP_DMA);
 	if (!dasd_reserve_req)
 		return -ENOMEM;
+	path_verification_worker = kmalloc(sizeof(*path_verification_worker),
+				   GFP_KERNEL | GFP_DMA);
+	if (!path_verification_worker) {
+		kfree(dasd_reserve_req);
+		return -ENOMEM;
+	}
 	ret = ccw_driver_register(&dasd_eckd_driver);
 	if (!ret)
 		wait_for_device_probe();
-	else
+	else {
+		kfree(path_verification_worker);
 		kfree(dasd_reserve_req);
+	}
 	return ret;
 }
 
@@ -3621,6 +4070,7 @@
 dasd_eckd_cleanup(void)
 {
 	ccw_driver_unregister(&dasd_eckd_driver);
+	kfree(path_verification_worker);
 	kfree(dasd_reserve_req);
 }
 
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index 12097c2..4a688a8 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -37,14 +37,17 @@
 #define DASD_ECKD_CCW_WRITE_KD_MT	 0x8d
 #define DASD_ECKD_CCW_READ_KD_MT	 0x8e
 #define DASD_ECKD_CCW_RELEASE		 0x94
+#define DASD_ECKD_CCW_WRITE_FULL_TRACK	 0x95
 #define DASD_ECKD_CCW_READ_CKD_MT	 0x9e
 #define DASD_ECKD_CCW_WRITE_CKD_MT	 0x9d
 #define DASD_ECKD_CCW_WRITE_TRACK_DATA	 0xA5
 #define DASD_ECKD_CCW_READ_TRACK_DATA	 0xA6
 #define DASD_ECKD_CCW_RESERVE		 0xB4
+#define DASD_ECKD_CCW_READ_TRACK	 0xDE
 #define DASD_ECKD_CCW_PFX		 0xE7
 #define DASD_ECKD_CCW_PFX_READ		 0xEA
 #define DASD_ECKD_CCW_RSCK		 0xF9
+#define DASD_ECKD_CCW_RCD		 0xFA
 
 /*
  * Perform Subsystem Function / Sub-Orders
@@ -57,6 +60,11 @@
  */
 #define LV_COMPAT_CYL 0xFFFE
 
+
+#define FCX_MAX_DATA_FACTOR 65536
+#define DASD_ECKD_RCD_DATA_SIZE 256
+
+
 /*****************************************************************************
  * SECTION: Type Definitions
  ****************************************************************************/
@@ -331,12 +339,6 @@
 	__u8 reserved2[22];
 } __attribute__ ((packed));
 
-struct dasd_eckd_path {
-	__u8 opm;
-	__u8 ppm;
-	__u8 npm;
-};
-
 struct dasd_rssd_features {
 	char feature[256];
 } __attribute__((packed));
@@ -442,7 +444,6 @@
 	struct vd_sneq *vdsneq;
 	struct dasd_gneq *gneq;
 
-	struct dasd_eckd_path path_data;
 	struct eckd_count count_area[5];
 	int init_cqr_status;
 	int uses_cdl;
@@ -455,6 +456,8 @@
 	struct alias_pav_group *pavgroup;
 	struct alias_lcu *lcu;
 	int count;
+
+	u32 fcx_max_data;
 };
 
 
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 83b4615..77f778b 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -473,6 +473,7 @@
 	cqr->retries = 255;
 	cqr->expires = 10 * HZ;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+	set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
 
 	ccw = cqr->cpaddr;
 	ccw->cmd_code = DASD_ECKD_CCW_SNSS;
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 7656384..0eafe2e 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -96,7 +96,8 @@
 		DBF_DEV_EVENT(DBF_DEBUG, device,
                              "default ERP called (%i retries left)",
                              cqr->retries);
-		cqr->lpm    = LPM_ANYPATH;
+		if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))
+			cqr->lpm = device->path_data.opm;
 		cqr->status = DASD_CQR_FILLED;
         } else {
 		pr_err("%s: default ERP has run out of retries and failed\n",
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index bec5486e..be89b3a 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -73,6 +73,7 @@
 	.set_offline = dasd_generic_set_offline,
 	.set_online  = dasd_fba_set_online,
 	.notify      = dasd_generic_notify,
+	.path_event  = dasd_generic_path_event,
 	.freeze      = dasd_generic_pm_freeze,
 	.thaw	     = dasd_generic_restore_device,
 	.restore     = dasd_generic_restore_device,
@@ -164,6 +165,7 @@
 	}
 
 	device->default_expires = DASD_EXPIRES;
+	device->path_data.opm = LPM_ANYPATH;
 
 	readonly = dasd_device_is_ro(device);
 	if (readonly)
@@ -231,24 +233,16 @@
 	return NULL;
 }
 
-static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device,
-						   struct irb *irb)
+static void dasd_fba_check_for_device_change(struct dasd_device *device,
+					     struct dasd_ccw_req *cqr,
+					     struct irb *irb)
 {
 	char mask;
 
 	/* first of all check for state change pending interrupt */
 	mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
-	if ((irb->scsw.cmd.dstat & mask) == mask) {
+	if ((irb->scsw.cmd.dstat & mask) == mask)
 		dasd_generic_handle_state_change(device);
-		return;
-	}
-
-	/* check for unsolicited interrupts */
-	DBF_DEV_EVENT(DBF_WARNING, device, "%s",
-		    "unsolicited interrupt received");
-	device->discipline->dump_sense_dbf(device, irb, "unsolicited");
-	dasd_schedule_device_bh(device);
-	return;
 };
 
 static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
@@ -596,13 +590,14 @@
 	.max_blocks = 96,
 	.check_device = dasd_fba_check_characteristics,
 	.do_analysis = dasd_fba_do_analysis,
+	.verify_path = dasd_generic_verify_path,
 	.fill_geometry = dasd_fba_fill_geometry,
 	.start_IO = dasd_start_IO,
 	.term_IO = dasd_term_IO,
 	.handle_terminated_request = dasd_fba_handle_terminated_request,
 	.erp_action = dasd_fba_erp_action,
 	.erp_postaction = dasd_fba_erp_postaction,
-	.handle_unsolicited_interrupt = dasd_fba_handle_unsolicited_interrupt,
+	.check_for_device_change = dasd_fba_check_for_device_change,
 	.build_cp = dasd_fba_build_cp,
 	.free_cp = dasd_fba_free_cp,
 	.dump_sense = dasd_fba_dump_sense,
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 500678d..df9f699 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -231,6 +231,11 @@
 /* per dasd_ccw_req flags */
 #define DASD_CQR_FLAGS_USE_ERP   0	/* use ERP for this request */
 #define DASD_CQR_FLAGS_FAILFAST  1	/* FAILFAST */
+#define DASD_CQR_VERIFY_PATH	 2	/* path verification request */
+#define DASD_CQR_ALLOW_SLOCK	 3	/* Try this request even when lock was
+					 * stolen. Should not be combined with
+					 * DASD_CQR_FLAGS_USE_ERP
+					 */
 
 /* Signature for error recovery functions. */
 typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
@@ -287,6 +292,14 @@
 	int (*do_analysis) (struct dasd_block *);
 
 	/*
+	 * This function is called, when new paths become available.
+	 * Disciplins may use this callback to do necessary setup work,
+	 * e.g. verify that new path is compatible with the current
+	 * configuration.
+	 */
+	int (*verify_path)(struct dasd_device *, __u8);
+
+	/*
 	 * Last things to do when a device is set online, and first things
 	 * when it is set offline.
 	 */
@@ -325,9 +338,9 @@
 	void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *,
 			    struct irb *);
 	void (*dump_sense_dbf) (struct dasd_device *, struct irb *, char *);
-
-	void (*handle_unsolicited_interrupt) (struct dasd_device *,
-					      struct irb *);
+	void (*check_for_device_change) (struct dasd_device *,
+					 struct dasd_ccw_req *,
+					 struct irb *);
 
         /* i/o control functions. */
 	int (*fill_geometry) (struct dasd_block *, struct hd_geometry *);
@@ -362,6 +375,13 @@
 #define DASD_EER_STATECHANGE 3
 #define DASD_EER_PPRCSUSPEND 4
 
+struct dasd_path {
+	__u8 opm;
+	__u8 tbvpm;
+	__u8 ppm;
+	__u8 npm;
+};
+
 struct dasd_device {
 	/* Block device stuff. */
 	struct dasd_block *block;
@@ -377,6 +397,7 @@
 	struct dasd_discipline *discipline;
 	struct dasd_discipline *base_discipline;
 	char *private;
+	struct dasd_path path_data;
 
 	/* Device state and target state. */
 	int state, target;
@@ -456,6 +477,9 @@
 					 * confuse this with the user specified
 					 * read-only feature.
 					 */
+#define DASD_FLAG_IS_RESERVED	7	/* The device is reserved */
+#define DASD_FLAG_LOCK_STOLEN	8	/* The device lock was stolen */
+
 
 void dasd_put_device_wake(struct dasd_device *);
 
@@ -620,10 +644,15 @@
 int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
 int dasd_generic_set_offline (struct ccw_device *cdev);
 int dasd_generic_notify(struct ccw_device *, int);
+int dasd_generic_last_path_gone(struct dasd_device *);
+int dasd_generic_path_operational(struct dasd_device *);
+
 void dasd_generic_handle_state_change(struct dasd_device *);
 int dasd_generic_pm_freeze(struct ccw_device *);
 int dasd_generic_restore_device(struct ccw_device *);
 enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *);
+void dasd_generic_path_event(struct ccw_device *, int *);
+int dasd_generic_verify_path(struct dasd_device *, __u8);
 
 int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int);
 char *dasd_get_sense(struct irb *);
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index 40834f1..dcee3c5 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -2,76 +2,85 @@
 	depends on S390
 
 config TN3270
-	tristate "Support for locally attached 3270 terminals"
+	def_tristate y
+	prompt "Support for locally attached 3270 terminals"
 	depends on CCW
 	help
 	  Include support for IBM 3270 terminals.
 
 config TN3270_TTY
-	tristate "Support for tty input/output on 3270 terminals"
+	def_tristate y
+	prompt "Support for tty input/output on 3270 terminals"
 	depends on TN3270
 	help
 	  Include support for using an IBM 3270 terminal as a Linux tty.
 
 config TN3270_FS
-	tristate "Support for fullscreen applications on 3270 terminals"
+	def_tristate m
+	prompt "Support for fullscreen applications on 3270 terminals"
 	depends on TN3270
 	help
 	  Include support for fullscreen applications on an IBM 3270 terminal.
 
 config TN3270_CONSOLE
-	bool "Support for console on 3270 terminal"
+	def_bool y
+	prompt "Support for console on 3270 terminal"
 	depends on TN3270=y && TN3270_TTY=y
 	help
 	  Include support for using an IBM 3270 terminal as a Linux system
 	  console.  Available only if 3270 support is compiled in statically.
 
 config TN3215
-	bool "Support for 3215 line mode terminal"
+	def_bool y
+	prompt "Support for 3215 line mode terminal"
 	depends on CCW
 	help
 	  Include support for IBM 3215 line-mode terminals.
 
 config TN3215_CONSOLE
-	bool "Support for console on 3215 line mode terminal"
+	def_bool y
+	prompt "Support for console on 3215 line mode terminal"
 	depends on TN3215
 	help
 	  Include support for using an IBM 3215 line-mode terminal as a
 	  Linux system console.
 
 config CCW_CONSOLE
-	bool
-	depends on TN3215_CONSOLE || TN3270_CONSOLE
-	default y
+	def_bool y if TN3215_CONSOLE || TN3270_CONSOLE
 
 config SCLP_TTY
-	bool "Support for SCLP line mode terminal"
+	def_bool y
+	prompt "Support for SCLP line mode terminal"
 	depends on S390
 	help
 	  Include support for IBM SCLP line-mode terminals.
 
 config SCLP_CONSOLE
-	bool "Support for console on SCLP line mode terminal"
+	def_bool y
+	prompt "Support for console on SCLP line mode terminal"
 	depends on SCLP_TTY
 	help
 	  Include support for using an IBM HWC line-mode terminal as the Linux
 	  system console.
 
 config SCLP_VT220_TTY
-	bool "Support for SCLP VT220-compatible terminal"
+	def_bool y
+	prompt "Support for SCLP VT220-compatible terminal"
 	depends on S390
 	help
 	  Include support for an IBM SCLP VT220-compatible terminal.
 
 config SCLP_VT220_CONSOLE
-	bool "Support for console on SCLP VT220-compatible terminal"
+	def_bool y
+	prompt "Support for console on SCLP VT220-compatible terminal"
 	depends on SCLP_VT220_TTY
 	help
 	  Include support for using an IBM SCLP VT220-compatible terminal as a
 	  Linux system console.
 
 config SCLP_CPI
-	tristate "Control-Program Identification"
+	def_tristate m
+	prompt "Control-Program Identification"
 	depends on S390
 	help
 	  This option enables the hardware console interface for system
@@ -83,7 +92,8 @@
 	  need this feature and intend to run your kernel in LPAR.
 
 config SCLP_ASYNC
-	tristate "Support for Call Home via Asynchronous SCLP Records"
+	def_tristate m
+	prompt "Support for Call Home via Asynchronous SCLP Records"
 	depends on S390
 	help
 	  This option enables the call home function, which is able to inform
@@ -93,7 +103,8 @@
 	  need this feature and intend to run your kernel in LPAR.
 
 config S390_TAPE
-	tristate "S/390 tape device support"
+	def_tristate m
+	prompt "S/390 tape device support"
 	depends on CCW
 	help
 	  Select this option if you want to access channel-attached tape
@@ -109,7 +120,8 @@
 	depends on S390_TAPE
 
 config S390_TAPE_BLOCK
-	bool "Support for tape block devices"
+	def_bool y
+	prompt "Support for tape block devices"
 	depends on S390_TAPE && BLOCK
 	help
 	  Select this option if you want to access your channel-attached tape
@@ -123,7 +135,8 @@
 	depends on S390_TAPE
 
 config S390_TAPE_34XX
-	tristate "Support for 3480/3490 tape hardware"
+	def_tristate m
+	prompt "Support for 3480/3490 tape hardware"
 	depends on S390_TAPE
 	help
 	  Select this option if you want to access IBM 3480/3490 magnetic
@@ -131,7 +144,8 @@
 	  It is safe to say "Y" here.
 
 config S390_TAPE_3590
-	tristate "Support for 3590 tape hardware"
+	def_tristate m
+	prompt "Support for 3590 tape hardware"
 	depends on S390_TAPE
 	help
 	  Select this option if you want to access IBM 3590 magnetic
@@ -139,7 +153,8 @@
 	  It is safe to say "Y" here.
 
 config VMLOGRDR
-	tristate "Support for the z/VM recording system services (VM only)"
+	def_tristate m
+	prompt "Support for the z/VM recording system services (VM only)"
 	depends on IUCV
 	help
 	  Select this option if you want to be able to receive records collected
@@ -148,29 +163,31 @@
 	  This driver depends on the IUCV support driver.
 
 config VMCP
-	bool "Support for the z/VM CP interface"
+	def_bool y
+	prompt "Support for the z/VM CP interface"
 	depends on S390
 	help
 	  Select this option if you want to be able to interact with the control
 	  program on z/VM
 
 config MONREADER
-	tristate "API for reading z/VM monitor service records"
+	def_tristate m
+	prompt "API for reading z/VM monitor service records"
 	depends on IUCV
 	help
 	  Character device driver for reading z/VM monitor service records
 
 config MONWRITER
-	tristate "API for writing z/VM monitor service records"
+	def_tristate m
+	prompt "API for writing z/VM monitor service records"
 	depends on S390
-	default "m"
 	help
 	  Character device driver for writing z/VM monitor service records
 
 config S390_VMUR
-	tristate "z/VM unit record device driver"
+	def_tristate m
+	prompt "z/VM unit record device driver"
 	depends on S390
-	default "m"
 	help
 	  Character device driver for z/VM reader, puncher and printer.
 
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 59ec073..3fb4335 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -9,6 +9,7 @@
  *	      Dan Morrison, IBM Corporation <dmorriso@cse.buffalo.edu>
  */
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kdev_t.h>
@@ -361,6 +362,7 @@
 	int cstat, dstat;
 	int count;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_C15]++;
 	raw = dev_get_drvdata(&cdev->dev);
 	req = (struct raw3215_req *) intparm;
 	cstat = irb->scsw.cmd.cstat;
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 2a4c566..96ba2fd 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -7,6 +7,7 @@
  *     Copyright IBM Corp. 2003, 2009
  */
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -329,6 +330,7 @@
 	struct raw3270_request *rq;
 	int rc;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_C70]++;
 	rp = dev_get_drvdata(&cdev->dev);
 	if (!rp)
 		return;
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 35cc468..b76c61f 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -7,6 +7,7 @@
  *	      Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/spinlock.h>
@@ -18,16 +19,14 @@
 #include <linux/suspend.h>
 #include <linux/completion.h>
 #include <linux/platform_device.h>
-#include <asm/types.h>
 #include <asm/s390_ext.h>
+#include <asm/types.h>
+#include <asm/irq.h>
 
 #include "sclp.h"
 
 #define SCLP_HEADER		"sclp: "
 
-/* Structure for register_early_external_interrupt. */
-static ext_int_info_t ext_int_info_hwc;
-
 /* Lock to protect internal data consistency. */
 static DEFINE_SPINLOCK(sclp_lock);
 
@@ -402,6 +401,7 @@
 	u32 finished_sccb;
 	u32 evbuf_pending;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
 	spin_lock(&sclp_lock);
 	finished_sccb = param32 & 0xfffffff8;
 	evbuf_pending = param32 & 0x3;
@@ -824,6 +824,7 @@
 {
 	u32 finished_sccb;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
 	finished_sccb = param32 & 0xfffffff8;
 	/* Is this the interrupt we are waiting for? */
 	if (finished_sccb == 0)
@@ -866,8 +867,7 @@
 
 	spin_lock_irqsave(&sclp_lock, flags);
 	/* Prepare init mask command */
-	rc = register_early_external_interrupt(0x2401, sclp_check_handler,
-					       &ext_int_info_hwc);
+	rc = register_external_interrupt(0x2401, sclp_check_handler);
 	if (rc) {
 		spin_unlock_irqrestore(&sclp_lock, flags);
 		return rc;
@@ -900,8 +900,7 @@
 		} else
 			rc = -EBUSY;
 	}
-	unregister_early_external_interrupt(0x2401, sclp_check_handler,
-					    &ext_int_info_hwc);
+	unregister_external_interrupt(0x2401, sclp_check_handler);
 	spin_unlock_irqrestore(&sclp_lock, flags);
 	return rc;
 }
@@ -1064,8 +1063,7 @@
 	if (rc)
 		goto fail_init_state_uninitialized;
 	/* Register interrupt handler */
-	rc = register_early_external_interrupt(0x2401, sclp_interrupt_handler,
-					       &ext_int_info_hwc);
+	rc = register_external_interrupt(0x2401, sclp_interrupt_handler);
 	if (rc)
 		goto fail_unregister_reboot_notifier;
 	sclp_init_state = sclp_init_state_initialized;
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index b497afe..16e232a 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -33,6 +33,7 @@
 	int cpu;
 	struct sys_device *sysdev;
 
+	s390_adjust_jiffies();
 	pr_warning("cpu capability changed.\n");
 	get_online_cpus();
 	for_each_online_cpu(cpu) {
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index deff2c3..fbe361f 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -24,6 +24,8 @@
 #include "tape_std.h"
 #include "tape_3590.h"
 
+static struct workqueue_struct *tape_3590_wq;
+
 /*
  * Pointer to debug area.
  */
@@ -613,7 +615,7 @@
 	p->device = tape_get_device(device);
 	p->op = op;
 
-	schedule_work(&p->work);
+	queue_work(tape_3590_wq, &p->work);
 	return 0;
 }
 
@@ -1629,7 +1631,7 @@
 static void
 tape_3590_cleanup_device(struct tape_device *device)
 {
-	flush_scheduled_work();
+	flush_workqueue(tape_3590_wq);
 	tape_std_unassign(device);
 
 	kfree(device->discdata);
@@ -1733,11 +1735,17 @@
 #endif
 
 	DBF_EVENT(3, "3590 init\n");
+
+	tape_3590_wq = alloc_workqueue("tape_3590", 0, 0);
+	if (!tape_3590_wq)
+		return -ENOMEM;
+
 	/* Register driver for 3590 tapes. */
 	rc = ccw_driver_register(&tape_3590_driver);
-	if (rc)
+	if (rc) {
+		destroy_workqueue(tape_3590_wq);
 		DBF_EVENT(3, "3590 init failed\n");
-	else
+	} else
 		DBF_EVENT(3, "3590 registered\n");
 	return rc;
 }
@@ -1746,7 +1754,7 @@
 tape_3590_exit(void)
 {
 	ccw_driver_unregister(&tape_3590_driver);
-
+	destroy_workqueue(tape_3590_wq);
 	debug_unregister(TAPE_DBF_AREA);
 }
 
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index f0fa9ca..55d2d0f 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -264,7 +264,7 @@
 void
 tapeblock_cleanup_device(struct tape_device *device)
 {
-	flush_scheduled_work();
+	flush_work_sync(&device->blk_data.requeue_task);
 	tape_put_device(device);
 
 	if (!device->blk_data.disk) {
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index b3a3e8e..7978a0a 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -14,6 +14,7 @@
 #define KMSG_COMPONENT "tape"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/init.h>	     // for kernel parameters
 #include <linux/kmod.h>	     // for requesting modules
@@ -1114,6 +1115,7 @@
 	struct tape_request *request;
 	int rc;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_TAP]++;
 	device = dev_get_drvdata(&cdev->dev);
 	if (device == NULL) {
 		return;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index f7e4ae6..caef175 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -11,6 +11,7 @@
 #define KMSG_COMPONENT "vmur"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
 
@@ -302,6 +303,7 @@
 {
 	struct urdev *urd;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_VMR]++;
 	TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n",
 	      intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
 	      irb->scsw.cmd.count);
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 97b25d6..2864581 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -67,6 +67,27 @@
 }
 
 /*
+ * Remove references from ccw devices to ccw group device and from
+ * ccw group device to ccw devices.
+ */
+static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev)
+{
+	struct ccw_device *cdev;
+	int i;
+
+	for (i = 0; i < gdev->count; i++) {
+		cdev = gdev->cdev[i];
+		if (!cdev)
+			continue;
+		spin_lock_irq(cdev->ccwlock);
+		dev_set_drvdata(&cdev->dev, NULL);
+		spin_unlock_irq(cdev->ccwlock);
+		gdev->cdev[i] = NULL;
+		put_device(&cdev->dev);
+	}
+}
+
+/*
  * Provide an 'ungroup' attribute so the user can remove group devices no
  * longer needed or accidentially created. Saves memory :)
  */
@@ -78,6 +99,7 @@
 	if (device_is_registered(&gdev->dev)) {
 		__ccwgroup_remove_symlinks(gdev);
 		device_unregister(dev);
+		__ccwgroup_remove_cdev_refs(gdev);
 	}
 	mutex_unlock(&gdev->reg_mutex);
 }
@@ -116,21 +138,7 @@
 static void
 ccwgroup_release (struct device *dev)
 {
-	struct ccwgroup_device *gdev;
-	int i;
-
-	gdev = to_ccwgroupdev(dev);
-
-	for (i = 0; i < gdev->count; i++) {
-		if (gdev->cdev[i]) {
-			spin_lock_irq(gdev->cdev[i]->ccwlock);
-			if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
-				dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
-			spin_unlock_irq(gdev->cdev[i]->ccwlock);
-			put_device(&gdev->cdev[i]->dev);
-		}
-	}
-	kfree(gdev);
+	kfree(to_ccwgroupdev(dev));
 }
 
 static int
@@ -639,6 +647,7 @@
 		mutex_lock(&gdev->reg_mutex);
 		__ccwgroup_remove_symlinks(gdev);
 		device_unregister(dev);
+		__ccwgroup_remove_cdev_refs(gdev);
 		mutex_unlock(&gdev->reg_mutex);
 		put_device(dev);
 	}
@@ -660,25 +669,6 @@
 	return 0;
 }
 
-static struct ccwgroup_device *
-__ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
-{
-	struct ccwgroup_device *gdev;
-
-	gdev = dev_get_drvdata(&cdev->dev);
-	if (gdev) {
-		if (get_device(&gdev->dev)) {
-			mutex_lock(&gdev->reg_mutex);
-			if (device_is_registered(&gdev->dev))
-				return gdev;
-			mutex_unlock(&gdev->reg_mutex);
-			put_device(&gdev->dev);
-		}
-		return NULL;
-	}
-	return NULL;
-}
-
 /**
  * ccwgroup_remove_ccwdev() - remove function for slave devices
  * @cdev: ccw device to be removed
@@ -694,13 +684,25 @@
 	/* Ignore offlining errors, device is gone anyway. */
 	ccw_device_set_offline(cdev);
 	/* If one of its devices is gone, the whole group is done for. */
-	gdev = __ccwgroup_get_gdev_by_cdev(cdev);
-	if (gdev) {
+	spin_lock_irq(cdev->ccwlock);
+	gdev = dev_get_drvdata(&cdev->dev);
+	if (!gdev) {
+		spin_unlock_irq(cdev->ccwlock);
+		return;
+	}
+	/* Get ccwgroup device reference for local processing. */
+	get_device(&gdev->dev);
+	spin_unlock_irq(cdev->ccwlock);
+	/* Unregister group device. */
+	mutex_lock(&gdev->reg_mutex);
+	if (device_is_registered(&gdev->dev)) {
 		__ccwgroup_remove_symlinks(gdev);
 		device_unregister(&gdev->dev);
-		mutex_unlock(&gdev->reg_mutex);
-		put_device(&gdev->dev);
+		__ccwgroup_remove_cdev_refs(gdev);
 	}
+	mutex_unlock(&gdev->reg_mutex);
+	/* Release ccwgroup device reference for local processing. */
+	put_device(&gdev->dev);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 1aaddea..0689fcf 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -695,6 +695,25 @@
 	return ret;
 }
 
+int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
+					  struct channel_path_desc_fmt1 *desc)
+{
+	struct chsc_response_struct *chsc_resp;
+	struct chsc_scpd *scpd_area;
+	int ret;
+
+	spin_lock_irq(&chsc_page_lock);
+	scpd_area = chsc_page;
+	ret = chsc_determine_channel_path_desc(chpid, 0, 0, 1, 0, scpd_area);
+	if (ret)
+		goto out;
+	chsc_resp = (void *)&scpd_area->response;
+	memcpy(desc, &chsc_resp->data, sizeof(*desc));
+out:
+	spin_unlock_irq(&chsc_page_lock);
+	return ret;
+}
+
 static void
 chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
 			  struct cmg_chars *chars)
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 6693f5e..3f15b2a 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -35,6 +35,22 @@
 	u8 chpp;
 } __attribute__ ((packed));
 
+struct channel_path_desc_fmt1 {
+	u8 flags;
+	u8 lsn;
+	u8 desc;
+	u8 chpid;
+	u32:24;
+	u8 chpp;
+	u32 unused[3];
+	u16 mdc;
+	u16:13;
+	u8 r:1;
+	u8 s:1;
+	u8 f:1;
+	u32 zeros[2];
+} __attribute__ ((packed));
+
 struct channel_path;
 
 struct css_chsc_char {
@@ -92,6 +108,8 @@
 				     int c, int m, void *page);
 int chsc_determine_base_channel_path_desc(struct chp_id chpid,
 					  struct channel_path_desc *desc);
+int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
+					  struct channel_path_desc_fmt1 *desc);
 void chsc_chp_online(struct chp_id chpid);
 void chsc_chp_offline(struct chp_id chpid);
 int chsc_get_channel_measurement_chars(struct channel_path *chp);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index f4e6cf3..430f875 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -619,7 +619,7 @@
 	s390_idle_check(regs, S390_lowcore.int_clock,
 			S390_lowcore.async_enter_timer);
 	irq_enter();
-	__get_cpu_var(s390_idle).nohz_delay = 1;
+	__this_cpu_write(s390_idle.nohz_delay, 1);
 	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
 		/* Serve timer interrupts first. */
 		clock_comparator_work();
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 825951b..24d8e97 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -618,6 +618,7 @@
 static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
 {
 	struct subchannel_id mchk_schid;
+	struct subchannel *sch;
 
 	if (overflow) {
 		css_schedule_eval_all();
@@ -637,6 +638,13 @@
 	if (crw1)
 		mchk_schid.ssid = (crw1->rsid >> 4) & 3;
 
+	if (crw0->erc == CRW_ERC_PMOD) {
+		sch = get_subchannel_by_schid(mchk_schid);
+		if (sch) {
+			css_update_ssd_info(sch);
+			put_device(&sch->dev);
+		}
+	}
 	/*
 	 * Since we are always presented with IPI in the CRW, we have to
 	 * use stsch() to find out if the subchannel in question has come
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 6da8454..651976b 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -687,6 +687,46 @@
 EXPORT_SYMBOL(ccw_device_tm_start_timeout);
 
 /**
+ * ccw_device_get_mdc - accumulate max data count
+ * @cdev: ccw device for which the max data count is accumulated
+ * @mask: mask of paths to use
+ *
+ * Return the number of 64K-bytes blocks all paths at least support
+ * for a transport command. Return values <= 0 indicate failures.
+ */
+int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
+{
+	struct subchannel *sch = to_subchannel(cdev->dev.parent);
+	struct channel_path_desc_fmt1 desc;
+	struct chp_id chpid;
+	int mdc = 0, ret, i;
+
+	/* Adjust requested path mask to excluded varied off paths. */
+	if (mask)
+		mask &= sch->lpm;
+	else
+		mask = sch->lpm;
+
+	chp_id_init(&chpid);
+	for (i = 0; i < 8; i++) {
+		if (!(mask & (0x80 >> i)))
+			continue;
+		chpid.id = sch->schib.pmcw.chpid[i];
+		ret = chsc_determine_fmt1_channel_path_desc(chpid, &desc);
+		if (ret)
+			return ret;
+		if (!desc.f)
+			return 0;
+		if (!desc.r)
+			mdc = 1;
+		mdc = mdc ? min(mdc, (int)desc.mdc) : desc.mdc;
+	}
+
+	return mdc;
+}
+EXPORT_SYMBOL(ccw_device_get_mdc);
+
+/**
  * ccw_device_tm_intrg - perform interrogate function
  * @cdev: ccw device on which to perform the interrogate function
  *
diff --git a/drivers/s390/cio/itcw.c b/drivers/s390/cio/itcw.c
index a0ae295..358ee16 100644
--- a/drivers/s390/cio/itcw.c
+++ b/drivers/s390/cio/itcw.c
@@ -93,6 +93,7 @@
 size_t itcw_calc_size(int intrg, int max_tidaws, int intrg_max_tidaws)
 {
 	size_t len;
+	int cross_count;
 
 	/* Main data. */
 	len = sizeof(struct itcw);
@@ -105,12 +106,27 @@
 		       /* TSB */ sizeof(struct tsb) +
 		       /* TIDAL */ intrg_max_tidaws * sizeof(struct tidaw);
 	}
+
 	/* Maximum required alignment padding. */
 	len += /* Initial TCW */ 63 + /* Interrogate TCCB */ 7;
-	/* Maximum padding for structures that may not cross 4k boundary. */
-	if ((max_tidaws > 0) || (intrg_max_tidaws > 0))
-		len += max(max_tidaws, intrg_max_tidaws) *
-		       sizeof(struct tidaw) - 1;
+
+	/* TIDAW lists may not cross a 4k boundary. To cross a
+	 * boundary we need to add a TTIC TIDAW. We need to reserve
+	 * one additional TIDAW for a TTIC that we may need to add due
+	 * to the placement of the data chunk in memory, and a further
+	 * TIDAW for each page boundary that the TIDAW list may cross
+	 * due to it's own size.
+	 */
+	if (max_tidaws) {
+		cross_count = 1 + ((max_tidaws * sizeof(struct tidaw) - 1)
+				   >> PAGE_SHIFT);
+		len += cross_count * sizeof(struct tidaw);
+	}
+	if (intrg_max_tidaws) {
+		cross_count = 1 + ((intrg_max_tidaws * sizeof(struct tidaw) - 1)
+				   >> PAGE_SHIFT);
+		len += cross_count * sizeof(struct tidaw);
+	}
 	return len;
 }
 EXPORT_SYMBOL(itcw_calc_size);
@@ -165,6 +181,7 @@
 	void *chunk;
 	addr_t start;
 	addr_t end;
+	int cross_count;
 
 	/* Check for 2G limit. */
 	start = (addr_t) buffer;
@@ -177,8 +194,17 @@
 	if (IS_ERR(chunk))
 		return chunk;
 	itcw = chunk;
-	itcw->max_tidaws = max_tidaws;
-	itcw->intrg_max_tidaws = intrg_max_tidaws;
+	/* allow for TTIC tidaws that may be needed to cross a page boundary */
+	cross_count = 0;
+	if (max_tidaws)
+		cross_count = 1 + ((max_tidaws * sizeof(struct tidaw) - 1)
+				   >> PAGE_SHIFT);
+	itcw->max_tidaws = max_tidaws + cross_count;
+	cross_count = 0;
+	if (intrg_max_tidaws)
+		cross_count = 1 + ((intrg_max_tidaws * sizeof(struct tidaw) - 1)
+				   >> PAGE_SHIFT);
+	itcw->intrg_max_tidaws = intrg_max_tidaws + cross_count;
 	/* Main TCW. */
 	chunk = fit_chunk(&start, end, sizeof(struct tcw), 64, 0);
 	if (IS_ERR(chunk))
@@ -198,7 +224,7 @@
 	/* Data TIDAL. */
 	if (max_tidaws > 0) {
 		chunk = fit_chunk(&start, end, sizeof(struct tidaw) *
-				  max_tidaws, 16, 1);
+				  itcw->max_tidaws, 16, 0);
 		if (IS_ERR(chunk))
 			return chunk;
 		tcw_set_data(itcw->tcw, chunk, 1);
@@ -206,7 +232,7 @@
 	/* Interrogate data TIDAL. */
 	if (intrg && (intrg_max_tidaws > 0)) {
 		chunk = fit_chunk(&start, end, sizeof(struct tidaw) *
-				  intrg_max_tidaws, 16, 1);
+				  itcw->intrg_max_tidaws, 16, 0);
 		if (IS_ERR(chunk))
 			return chunk;
 		tcw_set_data(itcw->intrg_tcw, chunk, 1);
@@ -283,13 +309,29 @@
  * the new tidaw on success or -%ENOSPC if the new tidaw would exceed the
  * available space.
  *
- * Note: the tidaw-list is assumed to be contiguous with no ttics. The
- * last-tidaw flag for the last tidaw in the list will be set by itcw_finalize.
+ * Note: TTIC tidaws are automatically added when needed, so explicitly calling
+ * this interface with the TTIC flag is not supported. The last-tidaw flag
+ * for the last tidaw in the list will be set by itcw_finalize.
  */
 struct tidaw *itcw_add_tidaw(struct itcw *itcw, u8 flags, void *addr, u32 count)
 {
+	struct tidaw *following;
+
 	if (itcw->num_tidaws >= itcw->max_tidaws)
 		return ERR_PTR(-ENOSPC);
+	/*
+	 * Is the tidaw, which follows the one we are about to fill, on the next
+	 * page? Then we have to insert a TTIC tidaw first, that points to the
+	 * tidaw on the new page.
+	 */
+	following = ((struct tidaw *) tcw_get_data(itcw->tcw))
+		+ itcw->num_tidaws + 1;
+	if (itcw->num_tidaws && !((unsigned long) following & ~PAGE_MASK)) {
+		tcw_add_tidaw(itcw->tcw, itcw->num_tidaws++,
+			      TIDAW_FLAGS_TTIC, following, 0);
+		if (itcw->num_tidaws >= itcw->max_tidaws)
+			return ERR_PTR(-ENOSPC);
+	}
 	return tcw_add_tidaw(itcw->tcw, itcw->num_tidaws++, flags, addr, count);
 }
 EXPORT_SYMBOL(itcw_add_tidaw);
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 0f4ef87..7bc643f 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -91,6 +91,12 @@
 #define AC1_SC_QEBSM_AVAILABLE		0x02	/* available for subchannel */
 #define AC1_SC_QEBSM_ENABLED		0x01	/* enabled for subchannel */
 
+/* SIGA flags */
+#define QDIO_SIGA_WRITE		0x00
+#define QDIO_SIGA_READ		0x01
+#define QDIO_SIGA_SYNC		0x02
+#define QDIO_SIGA_QEBSM_FLAG	0x80
+
 #ifdef CONFIG_64BIT
 static inline int do_sqbs(u64 token, unsigned char state, int queue,
 			  int *start, int *count)
@@ -142,10 +148,9 @@
 	u8 input:1;
 	u8 output:1;
 	u8 sync:1;
-	u8 no_sync_ti:1;
-	u8 no_sync_out_ti:1;
-	u8 no_sync_out_pci:1;
-	u8:2;
+	u8 sync_after_ai:1;
+	u8 sync_out_after_pci:1;
+	u8:3;
 } __attribute__ ((packed));
 
 struct chsc_ssqd_area {
@@ -202,6 +207,7 @@
 	unsigned int inbound_queue_full;
 	unsigned int outbound_call;
 	unsigned int outbound_handler;
+	unsigned int outbound_queue_full;
 	unsigned int fast_requeue;
 	unsigned int target_full;
 	unsigned int eqbs;
@@ -245,10 +251,10 @@
 struct qdio_output_q {
 	/* PCIs are enabled for the queue */
 	int pci_out_enabled;
-	/* IQDIO: output multiple buffers (enhanced SIGA) */
-	int use_enh_siga;
 	/* timer to check for more outbound work */
 	struct timer_list timer;
+	/* used SBALs before tasklet schedule */
+	int scan_threshold;
 };
 
 /*
@@ -383,12 +389,13 @@
 	(q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)
 #define is_qebsm(q)			(q->irq_ptr->sch_token != 0)
 
-#define need_siga_sync_thinint(q)	(!q->irq_ptr->siga_flag.no_sync_ti)
-#define need_siga_sync_out_thinint(q)	(!q->irq_ptr->siga_flag.no_sync_out_ti)
 #define need_siga_in(q)			(q->irq_ptr->siga_flag.input)
 #define need_siga_out(q)		(q->irq_ptr->siga_flag.output)
-#define need_siga_sync(q)		(q->irq_ptr->siga_flag.sync)
-#define siga_syncs_out_pci(q)		(q->irq_ptr->siga_flag.no_sync_out_pci)
+#define need_siga_sync(q)		(unlikely(q->irq_ptr->siga_flag.sync))
+#define need_siga_sync_after_ai(q)	\
+	(unlikely(q->irq_ptr->siga_flag.sync_after_ai))
+#define need_siga_sync_out_after_pci(q)	\
+	(unlikely(q->irq_ptr->siga_flag.sync_out_after_pci))
 
 #define for_each_input_queue(irq_ptr, q, i)	\
 	for (i = 0, q = irq_ptr->input_qs[0];	\
@@ -423,9 +430,9 @@
 
 extern struct indicator_t *q_indicators;
 
-static inline int shared_ind(struct qdio_irq *irq_ptr)
+static inline int shared_ind(u32 *dsci)
 {
-	return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+	return dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
 }
 
 /* prototypes for thin interrupt */
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 28868e7..f8b03a6 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -151,6 +151,7 @@
 	"Inbound queue full",
 	"Outbound calls",
 	"Outbound handler",
+	"Outbound queue full",
 	"Outbound fast_requeue",
 	"Outbound target_full",
 	"QEBSM eqbs",
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 5fcfa7f..e9fff2b 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -14,6 +14,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
+#include <linux/kernel_stat.h>
 #include <asm/atomic.h>
 #include <asm/debug.h>
 #include <asm/qdio.h>
@@ -29,11 +30,12 @@
 MODULE_DESCRIPTION("QDIO base support");
 MODULE_LICENSE("GPL");
 
-static inline int do_siga_sync(struct subchannel_id schid,
-			       unsigned int out_mask, unsigned int in_mask)
+static inline int do_siga_sync(unsigned long schid,
+			       unsigned int out_mask, unsigned int in_mask,
+			       unsigned int fc)
 {
-	register unsigned long __fc asm ("0") = 2;
-	register struct subchannel_id __schid asm ("1") = schid;
+	register unsigned long __fc asm ("0") = fc;
+	register unsigned long __schid asm ("1") = schid;
 	register unsigned long out asm ("2") = out_mask;
 	register unsigned long in asm ("3") = in_mask;
 	int cc;
@@ -47,10 +49,11 @@
 	return cc;
 }
 
-static inline int do_siga_input(struct subchannel_id schid, unsigned int mask)
+static inline int do_siga_input(unsigned long schid, unsigned int mask,
+				unsigned int fc)
 {
-	register unsigned long __fc asm ("0") = 1;
-	register struct subchannel_id __schid asm ("1") = schid;
+	register unsigned long __fc asm ("0") = fc;
+	register unsigned long __schid asm ("1") = schid;
 	register unsigned long __mask asm ("2") = mask;
 	int cc;
 
@@ -279,16 +282,20 @@
 static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
 			  unsigned int input)
 {
+	unsigned long schid = *((u32 *) &q->irq_ptr->schid);
+	unsigned int fc = QDIO_SIGA_SYNC;
 	int cc;
 
-	if (!need_siga_sync(q))
-		return 0;
-
 	DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr);
 	qperf_inc(q, siga_sync);
 
-	cc = do_siga_sync(q->irq_ptr->schid, output, input);
-	if (cc)
+	if (is_qebsm(q)) {
+		schid = q->irq_ptr->sch_token;
+		fc |= QDIO_SIGA_QEBSM_FLAG;
+	}
+
+	cc = do_siga_sync(schid, output, input, fc);
+	if (unlikely(cc))
 		DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc);
 	return cc;
 }
@@ -301,38 +308,22 @@
 		return qdio_siga_sync(q, q->mask, 0);
 }
 
-static inline int qdio_siga_sync_out(struct qdio_q *q)
-{
-	return qdio_siga_sync(q, ~0U, 0);
-}
-
-static inline int qdio_siga_sync_all(struct qdio_q *q)
-{
-	return qdio_siga_sync(q, ~0U, ~0U);
-}
-
 static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit)
 {
-	unsigned long schid;
-	unsigned int fc = 0;
+	unsigned long schid = *((u32 *) &q->irq_ptr->schid);
+	unsigned int fc = QDIO_SIGA_WRITE;
 	u64 start_time = 0;
 	int cc;
 
-	if (q->u.out.use_enh_siga)
-		fc = 3;
-
 	if (is_qebsm(q)) {
 		schid = q->irq_ptr->sch_token;
-		fc |= 0x80;
+		fc |= QDIO_SIGA_QEBSM_FLAG;
 	}
-	else
-		schid = *((u32 *)&q->irq_ptr->schid);
-
 again:
 	cc = do_siga_output(schid, q->mask, busy_bit, fc);
 
 	/* hipersocket busy condition */
-	if (*busy_bit) {
+	if (unlikely(*busy_bit)) {
 		WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2);
 
 		if (!start_time) {
@@ -347,32 +338,41 @@
 
 static inline int qdio_siga_input(struct qdio_q *q)
 {
+	unsigned long schid = *((u32 *) &q->irq_ptr->schid);
+	unsigned int fc = QDIO_SIGA_READ;
 	int cc;
 
 	DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr);
 	qperf_inc(q, siga_read);
 
-	cc = do_siga_input(q->irq_ptr->schid, q->mask);
-	if (cc)
+	if (is_qebsm(q)) {
+		schid = q->irq_ptr->sch_token;
+		fc |= QDIO_SIGA_QEBSM_FLAG;
+	}
+
+	cc = do_siga_input(schid, q->mask, fc);
+	if (unlikely(cc))
 		DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc);
 	return cc;
 }
 
-static inline void qdio_sync_after_thinint(struct qdio_q *q)
+#define qdio_siga_sync_out(q) qdio_siga_sync(q, ~0U, 0)
+#define qdio_siga_sync_all(q) qdio_siga_sync(q, ~0U, ~0U)
+
+static inline void qdio_sync_queues(struct qdio_q *q)
 {
-	if (pci_out_supported(q)) {
-		if (need_siga_sync_thinint(q))
-			qdio_siga_sync_all(q);
-		else if (need_siga_sync_out_thinint(q))
-			qdio_siga_sync_out(q);
-	} else
+	/* PCI capable outbound queues will also be scanned so sync them too */
+	if (pci_out_supported(q))
+		qdio_siga_sync_all(q);
+	else
 		qdio_siga_sync_q(q);
 }
 
 int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
 			unsigned char *state)
 {
-	qdio_siga_sync_q(q);
+	if (need_siga_sync(q))
+		qdio_siga_sync_q(q);
 	return get_buf_states(q, bufnr, state, 1, 0);
 }
 
@@ -549,7 +549,8 @@
 	if (!atomic_read(&q->nr_buf_used))
 		return 1;
 
-	qdio_siga_sync_q(q);
+	if (need_siga_sync(q))
+		qdio_siga_sync_q(q);
 	get_buf_state(q, q->first_to_check, &state, 0);
 
 	if (state == SLSB_P_INPUT_PRIMED || state == SLSB_P_INPUT_ERROR)
@@ -644,9 +645,12 @@
 	int count, stop;
 	unsigned char state;
 
-	if (((queue_type(q) != QDIO_IQDIO_QFMT) && !pci_out_supported(q)) ||
-	    (queue_type(q) == QDIO_IQDIO_QFMT && multicast_outbound(q)))
-		qdio_siga_sync_q(q);
+	if (need_siga_sync(q))
+		if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
+		    !pci_out_supported(q)) ||
+		    (queue_type(q) == QDIO_IQDIO_QFMT &&
+		    multicast_outbound(q)))
+			qdio_siga_sync_q(q);
 
 	/*
 	 * Don't check 128 buffers, as otherwise qdio_inbound_q_moved
@@ -818,7 +822,8 @@
 static void __tiqdio_inbound_processing(struct qdio_q *q)
 {
 	qperf_inc(q, tasklet_inbound);
-	qdio_sync_after_thinint(q);
+	if (need_siga_sync(q) && need_siga_sync_after_ai(q))
+		qdio_sync_queues(q);
 
 	/*
 	 * The interrupt could be caused by a PCI request. Check the
@@ -898,16 +903,14 @@
 			tasklet_schedule(&q->tasklet);
 	}
 
-	if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
+	if (!pci_out_supported(q))
 		return;
 
 	for_each_output_queue(irq_ptr, q, i) {
 		if (qdio_outbound_q_done(q))
 			continue;
-
-		if (!siga_syncs_out_pci(q))
+		if (need_siga_sync(q) && need_siga_sync_out_after_pci(q))
 			qdio_siga_sync_q(q);
-
 		tasklet_schedule(&q->tasklet);
 	}
 }
@@ -970,6 +973,7 @@
 		return;
 	}
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_QDI]++;
 	if (irq_ptr->perf_stat_enabled)
 		irq_ptr->perf_stat.qdio_int++;
 
@@ -1273,7 +1277,6 @@
 	}
 
 	qdio_setup_ssqd_info(irq_ptr);
-	DBF_EVENT("qDmmwc:%2x", irq_ptr->ssqd_desc.mmwc);
 	DBF_EVENT("qib ac:%4x", irq_ptr->qib.ac);
 
 	/* qebsm is now setup if available, initialize buffer states */
@@ -1445,52 +1448,38 @@
 	used = atomic_add_return(count, &q->nr_buf_used);
 	BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q);
 
+	if (used == QDIO_MAX_BUFFERS_PER_Q)
+		qperf_inc(q, outbound_queue_full);
+
 	if (callflags & QDIO_FLAG_PCI_OUT) {
 		q->u.out.pci_out_enabled = 1;
 		qperf_inc(q, pci_request_int);
-	}
-	else
+	} else
 		q->u.out.pci_out_enabled = 0;
 
 	if (queue_type(q) == QDIO_IQDIO_QFMT) {
-		if (multicast_outbound(q))
+		/* One SIGA-W per buffer required for unicast HiperSockets. */
+		WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
+
+		rc = qdio_kick_outbound_q(q);
+	} else if (need_siga_sync(q)) {
+		rc = qdio_siga_sync_q(q);
+	} else {
+		/* try to fast requeue buffers */
+		get_buf_state(q, prev_buf(bufnr), &state, 0);
+		if (state != SLSB_CU_OUTPUT_PRIMED)
 			rc = qdio_kick_outbound_q(q);
 		else
-			if ((q->irq_ptr->ssqd_desc.mmwc > 1) &&
-			    (count > 1) &&
-			    (count <= q->irq_ptr->ssqd_desc.mmwc)) {
-				/* exploit enhanced SIGA */
-				q->u.out.use_enh_siga = 1;
-				rc = qdio_kick_outbound_q(q);
-			} else {
-				/*
-				* One siga-w per buffer required for unicast
-				* HiperSockets.
-				*/
-				q->u.out.use_enh_siga = 0;
-				while (count--) {
-					rc = qdio_kick_outbound_q(q);
-					if (rc)
-						goto out;
-				}
-			}
-		goto out;
+			qperf_inc(q, fast_requeue);
 	}
 
-	if (need_siga_sync(q)) {
-		qdio_siga_sync_q(q);
-		goto out;
-	}
-
-	/* try to fast requeue buffers */
-	get_buf_state(q, prev_buf(bufnr), &state, 0);
-	if (state != SLSB_CU_OUTPUT_PRIMED)
-		rc = qdio_kick_outbound_q(q);
+	/* in case of SIGA errors we must process the error immediately */
+	if (used >= q->u.out.scan_threshold || rc)
+		tasklet_schedule(&q->tasklet);
 	else
-		qperf_inc(q, fast_requeue);
-
-out:
-	tasklet_schedule(&q->tasklet);
+		/* free the SBALs in case of no further traffic */
+		if (!timer_pending(&q->u.out.timer))
+			mod_timer(&q->u.out.timer, jiffies + HZ);
 	return rc;
 }
 
@@ -1550,7 +1539,7 @@
 
 	WARN_ON(queue_irqs_enabled(q));
 
-	if (!shared_ind(q->irq_ptr))
+	if (!shared_ind(q->irq_ptr->dsci))
 		xchg(q->irq_ptr->dsci, 0);
 
 	qdio_stop_polling(q);
@@ -1560,7 +1549,7 @@
 	 * We need to check again to not lose initiative after
 	 * resetting the ACK state.
 	 */
-	if (!shared_ind(q->irq_ptr) && *q->irq_ptr->dsci)
+	if (!shared_ind(q->irq_ptr->dsci) && *q->irq_ptr->dsci)
 		goto rescan;
 	if (!qdio_inbound_q_done(q))
 		goto rescan;
@@ -1600,12 +1589,14 @@
 	q = irq_ptr->input_qs[nr];
 	WARN_ON(queue_irqs_enabled(q));
 
-	qdio_sync_after_thinint(q);
-
 	/*
-	 * The interrupt could be caused by a PCI request. Check the
-	 * PCI capable outbound queues.
+	 * Cannot rely on automatic sync after interrupt since queues may
+	 * also be examined without interrupt.
 	 */
+	if (need_siga_sync(q))
+		qdio_sync_queues(q);
+
+	/* check the PCI capable outbound queues. */
 	qdio_check_outbound_after_thinint(q);
 
 	if (!qdio_inbound_q_moved(q))
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index a13cf7e..89107d0 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -178,6 +178,7 @@
 		setup_queues_misc(q, irq_ptr, qdio_init->output_handler, i);
 
 		q->is_input_q = 0;
+		q->u.out.scan_threshold = qdio_init->scan_threshold;
 		setup_storage_lists(q, irq_ptr, output_sbal_array, i);
 		output_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
 
@@ -196,14 +197,10 @@
 		irq_ptr->siga_flag.output = 1;
 	if (qdioac & AC1_SIGA_SYNC_NEEDED)
 		irq_ptr->siga_flag.sync = 1;
-	if (qdioac & AC1_AUTOMATIC_SYNC_ON_THININT)
-		irq_ptr->siga_flag.no_sync_ti = 1;
-	if (qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI)
-		irq_ptr->siga_flag.no_sync_out_pci = 1;
-
-	if (irq_ptr->siga_flag.no_sync_out_pci &&
-	    irq_ptr->siga_flag.no_sync_ti)
-		irq_ptr->siga_flag.no_sync_out_ti = 1;
+	if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_THININT))
+		irq_ptr->siga_flag.sync_after_ai = 1;
+	if (!(qdioac & AC1_AUTOMATIC_SYNC_ON_OUT_PCI))
+		irq_ptr->siga_flag.sync_out_after_pci = 1;
 }
 
 static void check_and_setup_qebsm(struct qdio_irq *irq_ptr,
@@ -451,7 +448,7 @@
 	char s[80];
 
 	snprintf(s, 80, "qdio: %s %s on SC %x using "
-		 "AI:%d QEBSM:%d PCI:%d TDD:%d SIGA:%s%s%s%s%s%s\n",
+		 "AI:%d QEBSM:%d PCI:%d TDD:%d SIGA:%s%s%s%s%s\n",
 		 dev_name(&cdev->dev),
 		 (irq_ptr->qib.qfmt == QDIO_QETH_QFMT) ? "OSA" :
 			((irq_ptr->qib.qfmt == QDIO_ZFCP_QFMT) ? "ZFCP" : "HS"),
@@ -463,9 +460,8 @@
 		 (irq_ptr->siga_flag.input) ? "R" : " ",
 		 (irq_ptr->siga_flag.output) ? "W" : " ",
 		 (irq_ptr->siga_flag.sync) ? "S" : " ",
-		 (!irq_ptr->siga_flag.no_sync_ti) ? "A" : " ",
-		 (!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " ",
-		 (!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " ");
+		 (irq_ptr->siga_flag.sync_after_ai) ? "A" : " ",
+		 (irq_ptr->siga_flag.sync_out_after_pci) ? "P" : " ");
 	printk(KERN_INFO "%s", s);
 }
 
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 5d9c666..5c4e741 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -8,6 +8,7 @@
  */
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/kernel_stat.h>
 #include <asm/atomic.h>
 #include <asm/debug.h>
 #include <asm/qdio.h>
@@ -35,22 +36,8 @@
 
 struct indicator_t *q_indicators;
 
-static int css_qdio_omit_svs;
-
 static u64 last_ai_time;
 
-static inline unsigned long do_clear_global_summary(void)
-{
-	register unsigned long __fn asm("1") = 3;
-	register unsigned long __tmp asm("2");
-	register unsigned long __time asm("3");
-
-	asm volatile(
-		"	.insn	rre,0xb2650000,2,0"
-		: "+d" (__fn), "=d" (__tmp), "=d" (__time));
-	return __time;
-}
-
 /* returns addr for the device state change indicator */
 static u32 *get_indicator(void)
 {
@@ -83,10 +70,6 @@
 	struct qdio_q *q;
 	int i;
 
-	/* No TDD facility? If we must use SIGA-s we can also omit SVS. */
-	if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync)
-		css_qdio_omit_svs = 1;
-
 	mutex_lock(&tiq_list_lock);
 	for_each_input_queue(irq_ptr, q, i)
 		list_add_rcu(&q->entry, &tiq_list);
@@ -112,9 +95,9 @@
 	}
 }
 
-static inline int shared_ind_used(void)
+static inline u32 shared_ind_set(void)
 {
-	return atomic_read(&q_indicators[TIQDIO_SHARED_IND].count);
+	return q_indicators[TIQDIO_SHARED_IND].ind;
 }
 
 /**
@@ -124,20 +107,11 @@
  */
 static void tiqdio_thinint_handler(void *alsi, void *data)
 {
+	u32 si_used = shared_ind_set();
 	struct qdio_q *q;
 
 	last_ai_time = S390_lowcore.int_clock;
-
-	/*
-	 * SVS only when needed: issue SVS to benefit from iqdio interrupt
-	 * avoidance (SVS clears adapter interrupt suppression overwrite).
-	 */
-	if (!css_qdio_omit_svs)
-		do_clear_global_summary();
-
-	/* reset local summary indicator */
-	if (shared_ind_used())
-		xchg(tiqdio_alsi, 0);
+	kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++;
 
 	/* protect tiq_list entries, only changed in activate or shutdown */
 	rcu_read_lock();
@@ -146,7 +120,10 @@
 	list_for_each_entry_rcu(q, &tiq_list, entry) {
 
 		/* only process queues from changed sets */
-		if (!*q->irq_ptr->dsci)
+		if (unlikely(shared_ind(q->irq_ptr->dsci))) {
+			if (!si_used)
+				continue;
+		} else if (!*q->irq_ptr->dsci)
 			continue;
 
 		if (q->u.in.queue_start_poll) {
@@ -162,7 +139,7 @@
 						 q->irq_ptr->int_parm);
 		} else {
 			/* only clear it if the indicator is non-shared */
-			if (!shared_ind(q->irq_ptr))
+			if (!shared_ind(q->irq_ptr->dsci))
 				xchg(q->irq_ptr->dsci, 0);
 			/*
 			 * Call inbound processing but not directly
@@ -178,13 +155,8 @@
 	 * If the shared indicator was used clear it now after all queues
 	 * were processed.
 	 */
-	if (shared_ind_used()) {
+	if (si_used && shared_ind_set())
 		xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
-
-		/* prevent racing */
-		if (*tiqdio_alsi)
-			xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7);
-	}
 }
 
 static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset)
@@ -269,12 +241,6 @@
 {
 	if (!is_thinint_irq(irq_ptr))
 		return 0;
-
-	/* Check for aif time delay disablement. If installed,
-	 * omit SVS even under LPAR
-	 */
-	if (css_general_characteristics.aif_tdd)
-		css_qdio_omit_svs = 1;
 	return set_subchannel_ind(irq_ptr, 0);
 }
 
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 8fd8c62..67302b9 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -27,6 +27,7 @@
 #define KMSG_COMPONENT "ap"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -154,7 +155,7 @@
  */
 static int ap_interrupts_available(void)
 {
-	return test_facility(1) && test_facility(2);
+	return test_facility(2) && test_facility(65);
 }
 
 /**
@@ -221,6 +222,69 @@
 }
 #endif
 
+static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid,
+								  int *support)
+{
+	register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
+	register struct ap_queue_status reg1 asm ("1");
+	register unsigned long reg2 asm ("2") = 0UL;
+
+	asm volatile(
+		".long 0xb2af0000\n"
+		"0: la    %1,0\n"
+		"1:\n"
+		EX_TABLE(0b, 1b)
+		: "+d" (reg0), "=d" (reg1), "=d" (reg2)
+		:
+		: "cc");
+
+	if (reg2 & 0x6000000000000000ULL)
+		*support = 1;
+	else
+		*support = 0;
+
+	return reg1;
+}
+
+/**
+ * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
+ * support.
+ * @qid: The AP queue number
+ *
+ * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ */
+int ap_4096_commands_available(ap_qid_t qid)
+{
+	struct ap_queue_status status;
+	int i, support = 0;
+	status = __ap_4096_commands_available(qid, &support);
+
+	for (i = 0; i < AP_MAX_RESET; i++) {
+		switch (status.response_code) {
+		case AP_RESPONSE_NORMAL:
+			return support;
+		case AP_RESPONSE_RESET_IN_PROGRESS:
+		case AP_RESPONSE_BUSY:
+			break;
+		case AP_RESPONSE_Q_NOT_AVAIL:
+		case AP_RESPONSE_DECONFIGURED:
+		case AP_RESPONSE_CHECKSTOPPED:
+		case AP_RESPONSE_INVALID_ADDRESS:
+			return 0;
+		case AP_RESPONSE_OTHERWISE_CHANGED:
+			break;
+		default:
+			break;
+		}
+		if (i < AP_MAX_RESET - 1) {
+			udelay(5);
+			status = __ap_4096_commands_available(qid, &support);
+		}
+	}
+	return support;
+}
+EXPORT_SYMBOL(ap_4096_commands_available);
+
 /**
  * ap_queue_enable_interruption(): Enable interruption on an AP.
  * @qid: The AP queue number
@@ -1042,6 +1106,7 @@
 
 static void ap_interrupt_handler(void *unused1, void *unused2)
 {
+	kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
 	tasklet_schedule(&ap_tasklet);
 }
 
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 4785d07..08b9738 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -196,4 +196,6 @@
 int ap_module_init(void);
 void ap_module_exit(void);
 
+int ap_4096_commands_available(ap_qid_t qid);
+
 #endif /* _AP_BUS_H_ */
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 7fca9c1..8e65447 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -396,8 +396,15 @@
 			if (copied == 0) {
 				unsigned int len;
 				spin_unlock_bh(&zcrypt_device_lock);
-				/* len is max 256 / 2 - 120 = 8 */
-				len = crt->inputdatalength / 2 - 120;
+				/* len is max 256 / 2 - 120 = 8
+				 * For bigger device just assume len of leading
+				 * 0s is 8 as stated in the requirements for
+				 * ica_rsa_modexpo_crt struct in zcrypt.h.
+				 */
+				if (crt->inputdatalength <= 256)
+					len = crt->inputdatalength / 2 - 120;
+				else
+					len = 8;
 				if (len > sizeof(z1))
 					return -EFAULT;
 				z1 = z2 = z3 = 0;
@@ -405,6 +412,7 @@
 				    copy_from_user(&z2, crt->bp_key, len) ||
 				    copy_from_user(&z3, crt->u_mult_inv, len))
 					return -EFAULT;
+				z1 = z2 = z3 = 0;
 				copied = 1;
 				/*
 				 * We have to restart device lookup -
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 8e7ffbf..88ebd11 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -109,6 +109,7 @@
 	int request_count;		/* # current requests. */
 
 	struct ap_message reply;	/* Per-device reply structure. */
+	int max_exp_bit_length;
 };
 
 struct zcrypt_device *zcrypt_device_alloc(size_t);
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 9c409ef..2176d00 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -41,7 +41,7 @@
 #define CEX2A_MIN_MOD_SIZE	  1	/*    8 bits	*/
 #define CEX2A_MAX_MOD_SIZE	256	/* 2048 bits	*/
 #define CEX3A_MIN_MOD_SIZE	CEX2A_MIN_MOD_SIZE
-#define CEX3A_MAX_MOD_SIZE	CEX2A_MAX_MOD_SIZE
+#define CEX3A_MAX_MOD_SIZE	512	/* 4096 bits	*/
 
 #define CEX2A_SPEED_RATING	970
 #define CEX3A_SPEED_RATING	900 /* Fixme: Needs finetuning */
@@ -49,8 +49,10 @@
 #define CEX2A_MAX_MESSAGE_SIZE	0x390	/* sizeof(struct type50_crb2_msg)    */
 #define CEX2A_MAX_RESPONSE_SIZE 0x110	/* max outputdatalength + type80_hdr */
 
-#define CEX3A_MAX_MESSAGE_SIZE	CEX2A_MAX_MESSAGE_SIZE
-#define CEX3A_MAX_RESPONSE_SIZE	CEX2A_MAX_RESPONSE_SIZE
+#define CEX3A_MAX_RESPONSE_SIZE	0x210	/* 512 bit modulus
+					 * (max outputdatalength) +
+					 * type80_hdr*/
+#define CEX3A_MAX_MESSAGE_SIZE	sizeof(struct type50_crb3_msg)
 
 #define CEX2A_CLEANUP_TIME	(15*HZ)
 #define CEX3A_CLEANUP_TIME	CEX2A_CLEANUP_TIME
@@ -110,7 +112,7 @@
 		mod = meb1->modulus + sizeof(meb1->modulus) - mod_len;
 		exp = meb1->exponent + sizeof(meb1->exponent) - mod_len;
 		inp = meb1->message + sizeof(meb1->message) - mod_len;
-	} else {
+	} else if (mod_len <= 256) {
 		struct type50_meb2_msg *meb2 = ap_msg->message;
 		memset(meb2, 0, sizeof(*meb2));
 		ap_msg->length = sizeof(*meb2);
@@ -120,6 +122,17 @@
 		mod = meb2->modulus + sizeof(meb2->modulus) - mod_len;
 		exp = meb2->exponent + sizeof(meb2->exponent) - mod_len;
 		inp = meb2->message + sizeof(meb2->message) - mod_len;
+	} else {
+		/* mod_len > 256 = 4096 bit RSA Key */
+		struct type50_meb3_msg *meb3 = ap_msg->message;
+		memset(meb3, 0, sizeof(*meb3));
+		ap_msg->length = sizeof(*meb3);
+		meb3->header.msg_type_code = TYPE50_TYPE_CODE;
+		meb3->header.msg_len = sizeof(*meb3);
+		meb3->keyblock_type = TYPE50_MEB3_FMT;
+		mod = meb3->modulus + sizeof(meb3->modulus) - mod_len;
+		exp = meb3->exponent + sizeof(meb3->exponent) - mod_len;
+		inp = meb3->message + sizeof(meb3->message) - mod_len;
 	}
 
 	if (copy_from_user(mod, mex->n_modulus, mod_len) ||
@@ -142,7 +155,7 @@
 				       struct ap_message *ap_msg,
 				       struct ica_rsa_modexpo_crt *crt)
 {
-	int mod_len, short_len, long_len, long_offset;
+	int mod_len, short_len, long_len, long_offset, limit;
 	unsigned char *p, *q, *dp, *dq, *u, *inp;
 
 	mod_len = crt->inputdatalength;
@@ -152,14 +165,20 @@
 	/*
 	 * CEX2A cannot handle p, dp, or U > 128 bytes.
 	 * If we have one of these, we need to do extra checking.
+	 * For CEX3A the limit is 256 bytes.
 	 */
-	if (long_len > 128) {
+	if (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE)
+		limit = 256;
+	else
+		limit = 128;
+
+	if (long_len > limit) {
 		/*
 		 * zcrypt_rsa_crt already checked for the leading
 		 * zeroes of np_prime, bp_key and u_mult_inc.
 		 */
-		long_offset = long_len - 128;
-		long_len = 128;
+		long_offset = long_len - limit;
+		long_len = limit;
 	} else
 		long_offset = 0;
 
@@ -180,7 +199,7 @@
 		dq = crb1->dq + sizeof(crb1->dq) - short_len;
 		u = crb1->u + sizeof(crb1->u) - long_len;
 		inp = crb1->message + sizeof(crb1->message) - mod_len;
-	} else {
+	} else if (long_len <= 128) {
 		struct type50_crb2_msg *crb2 = ap_msg->message;
 		memset(crb2, 0, sizeof(*crb2));
 		ap_msg->length = sizeof(*crb2);
@@ -193,6 +212,20 @@
 		dq = crb2->dq + sizeof(crb2->dq) - short_len;
 		u = crb2->u + sizeof(crb2->u) - long_len;
 		inp = crb2->message + sizeof(crb2->message) - mod_len;
+	} else {
+		/* long_len >= 256 */
+		struct type50_crb3_msg *crb3 = ap_msg->message;
+		memset(crb3, 0, sizeof(*crb3));
+		ap_msg->length = sizeof(*crb3);
+		crb3->header.msg_type_code = TYPE50_TYPE_CODE;
+		crb3->header.msg_len = sizeof(*crb3);
+		crb3->keyblock_type = TYPE50_CRB3_FMT;
+		p = crb3->p + sizeof(crb3->p) - long_len;
+		q = crb3->q + sizeof(crb3->q) - short_len;
+		dp = crb3->dp + sizeof(crb3->dp) - long_len;
+		dq = crb3->dq + sizeof(crb3->dq) - short_len;
+		u = crb3->u + sizeof(crb3->u) - long_len;
+		inp = crb3->message + sizeof(crb3->message) - mod_len;
 	}
 
 	if (copy_from_user(p, crt->np_prime + long_offset, long_len) ||
@@ -203,7 +236,6 @@
 	    copy_from_user(inp, crt->inputdata, mod_len))
 		return -EFAULT;
 
-
 	return 0;
 }
 
@@ -230,7 +262,10 @@
 		zdev->online = 0;
 		return -EAGAIN;	/* repeat the request on a different device. */
 	}
-	BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE);
+	if (zdev->user_space_type == ZCRYPT_CEX2A)
+		BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE);
+	else
+		BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE);
 	data = reply->message + t80h->len - outputdatalength;
 	if (copy_to_user(outputdata, data, outputdatalength))
 		return -EFAULT;
@@ -282,7 +317,10 @@
 	}
 	t80h = reply->message;
 	if (t80h->type == TYPE80_RSP_CODE) {
-		length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len);
+		if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A)
+			length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len);
+		else
+			length = min(CEX3A_MAX_RESPONSE_SIZE, (int) t80h->len);
 		memcpy(msg->message, reply->message, length);
 	} else
 		memcpy(msg->message, reply->message, sizeof error_reply);
@@ -307,7 +345,10 @@
 	int rc;
 
 	ap_init_message(&ap_msg);
-	ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	if (zdev->user_space_type == ZCRYPT_CEX2A)
+		ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	else
+		ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 		return -ENOMEM;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
@@ -345,7 +386,10 @@
 	int rc;
 
 	ap_init_message(&ap_msg);
-	ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	if (zdev->user_space_type == ZCRYPT_CEX2A)
+		ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+	else
+		ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 		return -ENOMEM;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
@@ -397,6 +441,7 @@
 		zdev->max_mod_size = CEX2A_MAX_MOD_SIZE;
 		zdev->short_crt = 1;
 		zdev->speed_rating = CEX2A_SPEED_RATING;
+		zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE;
 		break;
 	case AP_DEVICE_TYPE_CEX3A:
 		zdev = zcrypt_device_alloc(CEX3A_MAX_RESPONSE_SIZE);
@@ -404,8 +449,13 @@
 			return -ENOMEM;
 		zdev->user_space_type = ZCRYPT_CEX3A;
 		zdev->type_string = "CEX3A";
-		zdev->min_mod_size = CEX3A_MIN_MOD_SIZE;
-		zdev->max_mod_size = CEX3A_MAX_MOD_SIZE;
+		zdev->min_mod_size = CEX2A_MIN_MOD_SIZE;
+		zdev->max_mod_size = CEX2A_MAX_MOD_SIZE;
+		zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE;
+		if (ap_4096_commands_available(ap_dev->qid)) {
+			zdev->max_mod_size = CEX3A_MAX_MOD_SIZE;
+			zdev->max_exp_bit_length = CEX3A_MAX_MOD_SIZE;
+		}
 		zdev->short_crt = 1;
 		zdev->speed_rating = CEX3A_SPEED_RATING;
 		break;
diff --git a/drivers/s390/crypto/zcrypt_cex2a.h b/drivers/s390/crypto/zcrypt_cex2a.h
index 8f69d1d..0350665 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.h
+++ b/drivers/s390/crypto/zcrypt_cex2a.h
@@ -51,8 +51,10 @@
 
 #define TYPE50_MEB1_FMT		0x0001
 #define TYPE50_MEB2_FMT		0x0002
+#define TYPE50_MEB3_FMT		0x0003
 #define TYPE50_CRB1_FMT		0x0011
 #define TYPE50_CRB2_FMT		0x0012
+#define TYPE50_CRB3_FMT		0x0013
 
 /* Mod-Exp, with a small modulus */
 struct type50_meb1_msg {
@@ -74,6 +76,16 @@
 	unsigned char	message[256];
 } __attribute__((packed));
 
+/* Mod-Exp, with a larger modulus */
+struct type50_meb3_msg {
+	struct type50_hdr header;
+	unsigned short	keyblock_type;	/* 0x0003 */
+	unsigned char	reserved[6];
+	unsigned char	exponent[512];
+	unsigned char	modulus[512];
+	unsigned char	message[512];
+} __attribute__((packed));
+
 /* CRT, with a small modulus */
 struct type50_crb1_msg {
 	struct type50_hdr header;
@@ -100,6 +112,19 @@
 	unsigned char	message[256];
 } __attribute__((packed));
 
+/* CRT, with a larger modulus */
+struct type50_crb3_msg {
+	struct type50_hdr header;
+	unsigned short	keyblock_type;	/* 0x0013 */
+	unsigned char	reserved[6];
+	unsigned char	p[256];
+	unsigned char	q[256];
+	unsigned char	dp[256];
+	unsigned char	dq[256];
+	unsigned char	u[256];
+	unsigned char	message[512];
+} __attribute__((packed));
+
 /**
  * The type 80 response family is associated with a CEX2A card.
  *
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 09e934b..1afb69c 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -373,6 +373,7 @@
 	zdev->min_mod_size = PCICA_MIN_MOD_SIZE;
 	zdev->max_mod_size = PCICA_MAX_MOD_SIZE;
 	zdev->speed_rating = PCICA_SPEED_RATING;
+	zdev->max_exp_bit_length = PCICA_MAX_MOD_SIZE;
 	ap_dev->reply = &zdev->reply;
 	ap_dev->private = zdev;
 	rc = zcrypt_device_register(zdev);
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index 9dec5c7..aa4c050 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -579,6 +579,7 @@
 	zdev->min_mod_size = PCICC_MIN_MOD_SIZE;
 	zdev->max_mod_size = PCICC_MAX_MOD_SIZE;
 	zdev->speed_rating = PCICC_SPEED_RATING;
+	zdev->max_exp_bit_length = PCICC_MAX_MOD_SIZE;
 	ap_dev->reply = &zdev->reply;
 	ap_dev->private = zdev;
 	rc = zcrypt_device_register(zdev);
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 510fab4..4f85eb7 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -45,12 +45,12 @@
 #define PCIXCC_MIN_MOD_SIZE_OLD	 64	/*  512 bits	*/
 #define PCIXCC_MAX_MOD_SIZE	256	/* 2048 bits	*/
 #define CEX3C_MIN_MOD_SIZE	PCIXCC_MIN_MOD_SIZE
-#define CEX3C_MAX_MOD_SIZE	PCIXCC_MAX_MOD_SIZE
+#define CEX3C_MAX_MOD_SIZE	512	/* 4096 bits	*/
 
 #define PCIXCC_MCL2_SPEED_RATING	7870
 #define PCIXCC_MCL3_SPEED_RATING	7870
 #define CEX2C_SPEED_RATING		7000
-#define CEX3C_SPEED_RATING		6500	/* FIXME: needs finetuning */
+#define CEX3C_SPEED_RATING		6500
 
 #define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c  /* max size type6 v2 crt message */
 #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply	    */
@@ -567,6 +567,15 @@
 	case TYPE88_RSP_CODE:
 		return convert_error(zdev, reply);
 	case TYPE86_RSP_CODE:
+		if (msg->cprbx.ccp_rtcode &&
+		   (msg->cprbx.ccp_rscode == 0x14f) &&
+		   (outputdatalength > 256)) {
+			if (zdev->max_exp_bit_length <= 17) {
+				zdev->max_exp_bit_length = 17;
+				return -EAGAIN;
+			} else
+				return -EINVAL;
+		}
 		if (msg->hdr.reply_code)
 			return convert_error(zdev, reply);
 		if (msg->cprbx.cprb_ver_id == 0x02)
@@ -1052,11 +1061,13 @@
 			zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
 			zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
 			zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
+			zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
 		} else {
 			zdev->type_string = "PCIXCC_MCL3";
 			zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
 			zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
 			zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
+			zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
 		}
 		break;
 	case AP_DEVICE_TYPE_CEX2C:
@@ -1065,6 +1076,7 @@
 		zdev->speed_rating = CEX2C_SPEED_RATING;
 		zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
 		zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
+		zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
 		break;
 	case AP_DEVICE_TYPE_CEX3C:
 		zdev->user_space_type = ZCRYPT_CEX3C;
@@ -1072,6 +1084,7 @@
 		zdev->speed_rating = CEX3C_SPEED_RATING;
 		zdev->min_mod_size = CEX3C_MIN_MOD_SIZE;
 		zdev->max_mod_size = CEX3C_MAX_MOD_SIZE;
+		zdev->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
 		break;
 	default:
 		goto out_free;
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 375aeea..414427d 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -10,6 +10,7 @@
  *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
  */
 
+#include <linux/kernel_stat.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/err.h>
@@ -25,6 +26,7 @@
 #include <asm/kvm_virtio.h>
 #include <asm/setup.h>
 #include <asm/s390_ext.h>
+#include <asm/irq.h>
 
 #define VIRTIO_SUBCODE_64 0x0D00
 
@@ -379,6 +381,7 @@
 	u16 subcode;
 	u32 param;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
 	subcode = ext_int_code >> 16;
 	if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
 		return;
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 456b187..fa80ba1 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -2,7 +2,8 @@
 	depends on NETDEVICES && S390
 
 config LCS
-	tristate "Lan Channel Station Interface"
+	def_tristate m
+	prompt "Lan Channel Station Interface"
 	depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
 	help
 	   Select this option if you want to use LCS networking on IBM System z.
@@ -12,7 +13,8 @@
 	   If you do not know what it is, it's safe to choose Y.
 
 config CTCM
-	tristate "CTC and MPC SNA device support"
+	def_tristate m
+	prompt "CTC and MPC SNA device support"
 	depends on CCW && NETDEVICES
 	help
 	  Select this option if you want to use channel-to-channel
@@ -26,7 +28,8 @@
 	  If you do not need any channel-to-channel connection, choose N.
 
 config NETIUCV
-	tristate "IUCV network device support (VM only)"
+	def_tristate m
+	prompt "IUCV network device support (VM only)"
 	depends on IUCV && NETDEVICES
 	help
 	  Select this option if you want to use inter-user communication
@@ -37,14 +40,16 @@
 	  The module name is netiucv. If unsure, choose Y.
 
 config SMSGIUCV
-	tristate "IUCV special message support (VM only)"
+	def_tristate m
+	prompt "IUCV special message support (VM only)"
 	depends on IUCV
 	help
 	  Select this option if you want to be able to receive SMSG messages
 	  from other VM guest systems.
 
 config SMSGIUCV_EVENT
-	tristate "Deliver IUCV special messages as uevents (VM only)"
+	def_tristate m
+	prompt "Deliver IUCV special messages as uevents (VM only)"
 	depends on SMSGIUCV
 	help
 	  Select this option to deliver CP special messages (SMSGs) as
@@ -54,7 +59,8 @@
 	  To compile as a module, choose M. The module name is "smsgiucv_app".
 
 config CLAW
-	tristate "CLAW device support"
+	def_tristate m
+	prompt "CLAW device support"
 	depends on CCW && NETDEVICES
 	help
 	  This driver supports channel attached CLAW devices.
@@ -64,7 +70,8 @@
 	  To compile into the kernel, choose Y.
 
 config QETH
-	tristate "Gigabit Ethernet device support"
+	def_tristate y
+	prompt "Gigabit Ethernet device support"
 	depends on CCW && NETDEVICES && IP_MULTICAST && QDIO
 	help
 	  This driver supports the IBM System z OSA Express adapters
@@ -78,25 +85,25 @@
 	  The module name is qeth.
 
 config QETH_L2
-        tristate "qeth layer 2 device support"
-        depends on QETH
-        help
-          Select this option to be able to run qeth devices in layer 2 mode.
-          To compile as a module, choose M. The module name is qeth_l2.
-          If unsure, choose y.
+	def_tristate y
+	prompt "qeth layer 2 device support"
+	depends on QETH
+	help
+	  Select this option to be able to run qeth devices in layer 2 mode.
+	  To compile as a module, choose M. The module name is qeth_l2.
+	  If unsure, choose y.
 
 config QETH_L3
-        tristate "qeth layer 3 device support"
-        depends on QETH
-        help
-          Select this option to be able to run qeth devices in layer 3 mode.
-          To compile as a module choose M. The module name is qeth_l3.
-          If unsure, choose Y.
+	def_tristate y
+	prompt "qeth layer 3 device support"
+	depends on QETH
+	help
+	  Select this option to be able to run qeth devices in layer 3 mode.
+	  To compile as a module choose M. The module name is qeth_l3.
+	  If unsure, choose Y.
 
 config QETH_IPV6
-        bool
-        depends on (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y')
-        default y
+	def_bool y if (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y')
 
 config CCWGROUP
 	tristate
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 8e4153d..ce3a5c1 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -63,6 +63,7 @@
 
 #define KMSG_COMPONENT "claw"
 
+#include <linux/kernel_stat.h>
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 #include <asm/debug.h>
@@ -640,6 +641,7 @@
         struct claw_env  *p_env;
         struct chbk *p_ch_r=NULL;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_CLW]++;
 	CLAW_DBF_TEXT(4, trace, "clawirq");
         /* Bypass all 'unsolicited interrupts' */
 	privptr = dev_get_drvdata(&cdev->dev);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 2c7d2d9..4c28459 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -24,6 +24,7 @@
 #define KMSG_COMPONENT "ctcm"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -1204,6 +1205,7 @@
 	int cstat;
 	int dstat;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_CTC]++;
 	CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
 		"Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev));
 
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index c9f13b9..09e7a05 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -26,6 +26,7 @@
 #define KMSG_COMPONENT		"lcs"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
@@ -1398,6 +1399,7 @@
 	int rc, index;
 	int cstat, dstat;
 
+	kstat_cpu(smp_processor_id()).irqs[IOINT_LCS]++;
 	if (lcs_check_irb_error(cdev, irb))
 		return;
 
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index b7d9dc0..29f848b 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -3831,6 +3831,8 @@
 	init_data.int_parm               = (unsigned long) card;
 	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
 	init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+	init_data.scan_threshold =
+		(card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32;
 
 	if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
 		QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 044fb22..51c666f 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -45,8 +45,8 @@
 module_param_named(device, init_device, charp, 0400);
 MODULE_PARM_DESC(device, "specify initial device");
 
-static struct kmem_cache *zfcp_cache_hw_align(const char *name,
-					      unsigned long size)
+static struct kmem_cache * __init zfcp_cache_hw_align(const char *name,
+						      unsigned long size)
 {
 	return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL);
 }
@@ -311,8 +311,7 @@
 		if (zfcp_fsf_status_read(adapter->qdio)) {
 			if (atomic_read(&adapter->stat_miss) >=
 			    adapter->stat_read_buf_num) {
-				zfcp_erp_adapter_reopen(adapter, 0, "axsref1",
-							NULL);
+				zfcp_erp_adapter_reopen(adapter, 0, "axsref1");
 				return 1;
 			}
 			break;
@@ -459,7 +458,7 @@
 	sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
 
 	zfcp_erp_thread_kill(adapter);
-	zfcp_dbf_adapter_unregister(adapter->dbf);
+	zfcp_dbf_adapter_unregister(adapter);
 	zfcp_qdio_destroy(adapter->qdio);
 
 	zfcp_ccw_adapter_put(adapter); /* final put to release */
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 0833c2b..4f7852d 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -48,7 +48,7 @@
 
 	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
-				"ccresu2", NULL);
+				"ccresu2");
 	zfcp_erp_wait(adapter);
 	flush_work(&adapter->scan_work);
 
@@ -182,7 +182,7 @@
 	if (!adapter)
 		return 0;
 
-	zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
+	zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1");
 	zfcp_erp_wait(adapter);
 
 	zfcp_ccw_adapter_put(adapter);
@@ -207,24 +207,24 @@
 	switch (event) {
 	case CIO_GONE:
 		dev_warn(&cdev->dev, "The FCP device has been detached\n");
-		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL);
+		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
 		break;
 	case CIO_NO_PATH:
 		dev_warn(&cdev->dev,
 			 "The CHPID for the FCP device is offline\n");
-		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL);
+		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
 		break;
 	case CIO_OPER:
 		dev_info(&cdev->dev, "The FCP device is operational again\n");
 		zfcp_erp_set_adapter_status(adapter,
 					    ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
-					"ccnoti4", NULL);
+					"ccnoti4");
 		break;
 	case CIO_BOXED:
 		dev_warn(&cdev->dev, "The FCP device did not respond within "
 				     "the specified time\n");
-		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL);
+		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5");
 		break;
 	}
 
@@ -243,7 +243,7 @@
 	if (!adapter)
 		return;
 
-	zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
+	zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1");
 	zfcp_erp_wait(adapter);
 	zfcp_erp_thread_kill(adapter);
 
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index d692e229..46342fe 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -288,7 +288,7 @@
 		    (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
 			zfcp_erp_port_reopen(port,
 					     ZFCP_STATUS_COMMON_ERP_FAILED,
-					     "cfaac_1", NULL);
+					     "cfaac_1");
 	}
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
@@ -299,7 +299,7 @@
 		    (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
 			zfcp_erp_lun_reopen(sdev,
 					    ZFCP_STATUS_COMMON_ERP_FAILED,
-					    "cfaac_2", NULL);
+					    "cfaac_2");
 	}
 }
 
@@ -426,7 +426,7 @@
 			zfcp_scsi_dev_lun(sdev),
 			(unsigned long long)zfcp_sdev->port->wwpn);
 		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
-		zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6", NULL);
+		zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6");
 		return -EACCES;
 	}
 
@@ -437,7 +437,7 @@
 			zfcp_scsi_dev_lun(sdev),
 			(unsigned long long)zfcp_sdev->port->wwpn);
 		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
-		zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8", NULL);
+		zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8");
 		return -EACCES;
 	}
 
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 2cdd6b2..96d1462 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -3,7 +3,7 @@
  *
  * Debug traces for zfcp.
  *
- * Copyright IBM Corporation 2002, 2009
+ * Copyright IBM Corporation 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -22,980 +22,392 @@
 MODULE_PARM_DESC(dbfsize,
 		 "number of pages for each debug feature area (default 4)");
 
-static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
-			     int level, char *from, int from_len)
+static inline unsigned int zfcp_dbf_plen(unsigned int offset)
 {
-	int offset;
-	struct zfcp_dbf_dump *dump = to;
-	int room = to_len - sizeof(*dump);
+	return sizeof(struct zfcp_dbf_pay) + offset - ZFCP_DBF_PAY_MAX_REC;
+}
 
-	for (offset = 0; offset < from_len; offset += dump->size) {
-		memset(to, 0, to_len);
-		strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
-		dump->total_size = from_len;
-		dump->offset = offset;
-		dump->size = min(from_len - offset, room);
-		memcpy(dump->data, from + offset, dump->size);
-		debug_event(dbf, level, dump, dump->size + sizeof(*dump));
+static inline
+void zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area,
+		       u64 req_id)
+{
+	struct zfcp_dbf_pay *pl = &dbf->pay_buf;
+	u16 offset = 0, rec_length;
+
+	spin_lock(&dbf->pay_lock);
+	memset(pl, 0, sizeof(*pl));
+	pl->fsf_req_id = req_id;
+	memcpy(pl->area, area, ZFCP_DBF_TAG_LEN);
+
+	while (offset < length) {
+		rec_length = min((u16) ZFCP_DBF_PAY_MAX_REC,
+				 (u16) (length - offset));
+		memcpy(pl->data, data + offset, rec_length);
+		debug_event(dbf->pay, 1, pl, zfcp_dbf_plen(rec_length));
+
+		offset += rec_length;
+		pl->counter++;
 	}
+
+	spin_unlock(&dbf->pay_lock);
 }
 
-static void zfcp_dbf_tag(char **p, const char *label, const char *tag)
+/**
+ * zfcp_dbf_hba_fsf_res - trace event for fsf responses
+ * @tag: tag indicating which kind of unsolicited status has been received
+ * @req: request for which a response was received
+ */
+void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req)
 {
-	int i;
-
-	*p += sprintf(*p, "%-24s", label);
-	for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++)
-		*p += sprintf(*p, "%c", tag[i]);
-	*p += sprintf(*p, "\n");
-}
-
-static void zfcp_dbf_outs(char **buf, const char *s1, const char *s2)
-{
-	*buf += sprintf(*buf, "%-24s%s\n", s1, s2);
-}
-
-static void zfcp_dbf_out(char **buf, const char *s, const char *format, ...)
-{
-	va_list arg;
-
-	*buf += sprintf(*buf, "%-24s", s);
-	va_start(arg, format);
-	*buf += vsprintf(*buf, format, arg);
-	va_end(arg);
-	*buf += sprintf(*buf, "\n");
-}
-
-static void zfcp_dbf_outd(char **p, const char *label, char *buffer,
-			  int buflen, int offset, int total_size)
-{
-	if (!offset)
-		*p += sprintf(*p, "%-24s  ", label);
-	while (buflen--) {
-		if (offset > 0) {
-			if ((offset % 32) == 0)
-				*p += sprintf(*p, "\n%-24c  ", ' ');
-			else if ((offset % 4) == 0)
-				*p += sprintf(*p, " ");
-		}
-		*p += sprintf(*p, "%02x", *buffer++);
-		if (++offset == total_size) {
-			*p += sprintf(*p, "\n");
-			break;
-		}
-	}
-	if (!total_size)
-		*p += sprintf(*p, "\n");
-}
-
-static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
-				int area, debug_entry_t *entry, char *out_buf)
-{
-	struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
-	struct timespec t;
-	char *p = out_buf;
-
-	if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
-		stck_to_timespec(entry->id.stck, &t);
-		zfcp_dbf_out(&p, "timestamp", "%011lu:%06lu",
-			     t.tv_sec, t.tv_nsec);
-		zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid);
-	} else	{
-		zfcp_dbf_outd(&p, "", dump->data, dump->size, dump->offset,
-			      dump->total_size);
-		if ((dump->offset + dump->size) == dump->total_size)
-			p += sprintf(p, "\n");
-	}
-	return p - out_buf;
-}
-
-void _zfcp_dbf_hba_fsf_response(const char *tag2, int level,
-				struct zfcp_fsf_req *fsf_req,
-				struct zfcp_dbf *dbf)
-{
-	struct fsf_qtcb *qtcb = fsf_req->qtcb;
-	union fsf_prot_status_qual *prot_status_qual =
-					&qtcb->prefix.prot_status_qual;
-	union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual;
-	struct scsi_cmnd *scsi_cmnd;
-	struct zfcp_port *port;
-	struct zfcp_unit *unit;
-	struct zfcp_send_els *send_els;
-	struct zfcp_dbf_hba_record *rec = &dbf->hba_buf;
-	struct zfcp_dbf_hba_record_response *response = &rec->u.response;
+	struct zfcp_dbf *dbf = req->adapter->dbf;
+	struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix;
+	struct fsf_qtcb_header *q_head = &req->qtcb->header;
+	struct zfcp_dbf_hba *rec = &dbf->hba_buf;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dbf->hba_lock, flags);
 	memset(rec, 0, sizeof(*rec));
-	strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
-	strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
 
-	response->fsf_command = fsf_req->fsf_command;
-	response->fsf_reqid = fsf_req->req_id;
-	response->fsf_seqno = fsf_req->seq_no;
-	response->fsf_issued = fsf_req->issued;
-	response->fsf_prot_status = qtcb->prefix.prot_status;
-	response->fsf_status = qtcb->header.fsf_status;
-	memcpy(response->fsf_prot_status_qual,
-	       prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE);
-	memcpy(response->fsf_status_qual,
-	       fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE);
-	response->fsf_req_status = fsf_req->status;
-	response->sbal_first = fsf_req->qdio_req.sbal_first;
-	response->sbal_last = fsf_req->qdio_req.sbal_last;
-	response->sbal_response = fsf_req->qdio_req.sbal_response;
-	response->pool = fsf_req->pool != NULL;
-	response->erp_action = (unsigned long)fsf_req->erp_action;
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->id = ZFCP_DBF_HBA_RES;
+	rec->fsf_req_id = req->req_id;
+	rec->fsf_req_status = req->status;
+	rec->fsf_cmd = req->fsf_command;
+	rec->fsf_seq_no = req->seq_no;
+	rec->u.res.req_issued = req->issued;
+	rec->u.res.prot_status = q_pref->prot_status;
+	rec->u.res.fsf_status = q_head->fsf_status;
 
-	switch (fsf_req->fsf_command) {
-	case FSF_QTCB_FCP_CMND:
-		if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
-			break;
-		scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
-		if (scsi_cmnd) {
-			response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
-			response->u.fcp.data_dir =
-				qtcb->bottom.io.data_direction;
-		}
-		break;
+	memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual,
+	       FSF_PROT_STATUS_QUAL_SIZE);
+	memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual,
+	       FSF_STATUS_QUALIFIER_SIZE);
 
-	case FSF_QTCB_OPEN_PORT_WITH_DID:
-	case FSF_QTCB_CLOSE_PORT:
-	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
-		port = (struct zfcp_port *)fsf_req->data;
-		response->u.port.wwpn = port->wwpn;
-		response->u.port.d_id = port->d_id;
-		response->u.port.port_handle = qtcb->header.port_handle;
-		break;
-
-	case FSF_QTCB_OPEN_LUN:
-	case FSF_QTCB_CLOSE_LUN:
-		unit = (struct zfcp_unit *)fsf_req->data;
-		port = unit->port;
-		response->u.unit.wwpn = port->wwpn;
-		response->u.unit.fcp_lun = unit->fcp_lun;
-		response->u.unit.port_handle = qtcb->header.port_handle;
-		response->u.unit.lun_handle = qtcb->header.lun_handle;
-		break;
-
-	case FSF_QTCB_SEND_ELS:
-		send_els = (struct zfcp_send_els *)fsf_req->data;
-		response->u.els.d_id = ntoh24(qtcb->bottom.support.d_id);
-		break;
-
-	case FSF_QTCB_ABORT_FCP_CMND:
-	case FSF_QTCB_SEND_GENERIC:
-	case FSF_QTCB_EXCHANGE_CONFIG_DATA:
-	case FSF_QTCB_EXCHANGE_PORT_DATA:
-	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
-	case FSF_QTCB_UPLOAD_CONTROL_FILE:
-		break;
+	if (req->fsf_command != FSF_QTCB_FCP_CMND) {
+		rec->pl_len = q_head->log_length;
+		zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start,
+				  rec->pl_len, "fsf_res", req->req_id);
 	}
 
-	debug_event(dbf->hba, level, rec, sizeof(*rec));
-
-	/* have fcp channel microcode fixed to use as little as possible */
-	if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) {
-		/* adjust length skipping trailing zeros */
-		char *buf = (char *)qtcb + qtcb->header.log_start;
-		int len = qtcb->header.log_length;
-		for (; len && !buf[len - 1]; len--);
-		zfcp_dbf_hexdump(dbf->hba, rec, sizeof(*rec), level, buf,
-				 len);
-	}
-
+	debug_event(dbf->hba, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
 
-void _zfcp_dbf_hba_fsf_unsol(const char *tag, int level, struct zfcp_dbf *dbf,
-			     struct fsf_status_read_buffer *status_buffer)
+/**
+ * zfcp_dbf_hba_fsf_uss - trace event for an unsolicited status buffer
+ * @tag: tag indicating which kind of unsolicited status has been received
+ * @req: request providing the unsolicited status
+ */
+void zfcp_dbf_hba_fsf_uss(char *tag, struct zfcp_fsf_req *req)
 {
-	struct zfcp_dbf_hba_record *rec = &dbf->hba_buf;
+	struct zfcp_dbf *dbf = req->adapter->dbf;
+	struct fsf_status_read_buffer *srb = req->data;
+	struct zfcp_dbf_hba *rec = &dbf->hba_buf;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dbf->hba_lock, flags);
 	memset(rec, 0, sizeof(*rec));
-	strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
-	strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
 
-	rec->u.status.failed = atomic_read(&dbf->adapter->stat_miss);
-	if (status_buffer != NULL) {
-		rec->u.status.status_type = status_buffer->status_type;
-		rec->u.status.status_subtype = status_buffer->status_subtype;
-		memcpy(&rec->u.status.queue_designator,
-		       &status_buffer->queue_designator,
-		       sizeof(struct fsf_queue_designator));
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->id = ZFCP_DBF_HBA_USS;
+	rec->fsf_req_id = req->req_id;
+	rec->fsf_req_status = req->status;
+	rec->fsf_cmd = req->fsf_command;
 
-		switch (status_buffer->status_type) {
-		case FSF_STATUS_READ_SENSE_DATA_AVAIL:
-			rec->u.status.payload_size =
-			    ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL;
-			break;
+	if (!srb)
+		goto log;
 
-		case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
-			rec->u.status.payload_size =
-			    ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
-			break;
+	rec->u.uss.status_type = srb->status_type;
+	rec->u.uss.status_subtype = srb->status_subtype;
+	rec->u.uss.d_id = ntoh24(srb->d_id);
+	rec->u.uss.lun = srb->fcp_lun;
+	memcpy(&rec->u.uss.queue_designator, &srb->queue_designator,
+	       sizeof(rec->u.uss.queue_designator));
 
-		case FSF_STATUS_READ_LINK_DOWN:
-			switch (status_buffer->status_subtype) {
-			case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
-			case FSF_STATUS_READ_SUB_FDISC_FAILED:
-				rec->u.status.payload_size =
-					sizeof(struct fsf_link_down_info);
-			}
-			break;
+	/* status read buffer payload length */
+	rec->pl_len = (!srb->length) ? 0 : srb->length -
+			offsetof(struct fsf_status_read_buffer, payload);
 
-		case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
-			rec->u.status.payload_size =
-			    ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
-			break;
-		}
-		memcpy(&rec->u.status.payload,
-		       &status_buffer->payload, rec->u.status.payload_size);
-	}
-
-	debug_event(dbf->hba, level, rec, sizeof(*rec));
+	if (rec->pl_len)
+		zfcp_dbf_pl_write(dbf, srb->payload.data, rec->pl_len,
+				  "fsf_uss", req->req_id);
+log:
+	debug_event(dbf->hba, 2, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
 
 /**
- * zfcp_dbf_hba_qdio - trace event for QDIO related failure
- * @qdio: qdio structure affected by this QDIO related event
- * @qdio_error: as passed by qdio module
- * @sbal_index: first buffer with error condition, as passed by qdio module
- * @sbal_count: number of buffers affected, as passed by qdio module
+ * zfcp_dbf_hba_bit_err - trace event for bit error conditions
+ * @tag: tag indicating which kind of unsolicited status has been received
+ * @req: request which caused the bit_error condition
  */
-void zfcp_dbf_hba_qdio(struct zfcp_dbf *dbf, unsigned int qdio_error,
-		       int sbal_index, int sbal_count)
+void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req)
 {
-	struct zfcp_dbf_hba_record *r = &dbf->hba_buf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dbf->hba_lock, flags);
-	memset(r, 0, sizeof(*r));
-	strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE);
-	r->u.qdio.qdio_error = qdio_error;
-	r->u.qdio.sbal_index = sbal_index;
-	r->u.qdio.sbal_count = sbal_count;
-	debug_event(dbf->hba, 0, r, sizeof(*r));
-	spin_unlock_irqrestore(&dbf->hba_lock, flags);
-}
-
-/**
- * zfcp_dbf_hba_berr - trace event for bit error threshold
- * @dbf: dbf structure affected by this QDIO related event
- * @req: fsf request
- */
-void zfcp_dbf_hba_berr(struct zfcp_dbf *dbf, struct zfcp_fsf_req *req)
-{
-	struct zfcp_dbf_hba_record *r = &dbf->hba_buf;
+	struct zfcp_dbf *dbf = req->adapter->dbf;
+	struct zfcp_dbf_hba *rec = &dbf->hba_buf;
 	struct fsf_status_read_buffer *sr_buf = req->data;
-	struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dbf->hba_lock, flags);
-	memset(r, 0, sizeof(*r));
-	strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE);
-	memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload));
-	debug_event(dbf->hba, 0, r, sizeof(*r));
+	memset(rec, 0, sizeof(*rec));
+
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->id = ZFCP_DBF_HBA_BIT;
+	rec->fsf_req_id = req->req_id;
+	rec->fsf_req_status = req->status;
+	rec->fsf_cmd = req->fsf_command;
+	memcpy(&rec->u.be, &sr_buf->payload.bit_error,
+	       sizeof(struct fsf_bit_error_payload));
+
+	debug_event(dbf->hba, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
-static void zfcp_dbf_hba_view_response(char **p,
-				       struct zfcp_dbf_hba_record_response *r)
+
+static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
+				struct zfcp_adapter *adapter,
+				struct zfcp_port *port,
+				struct scsi_device *sdev)
 {
-	struct timespec t;
-
-	zfcp_dbf_out(p, "fsf_command", "0x%08x", r->fsf_command);
-	zfcp_dbf_out(p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
-	zfcp_dbf_out(p, "fsf_seqno", "0x%08x", r->fsf_seqno);
-	stck_to_timespec(r->fsf_issued, &t);
-	zfcp_dbf_out(p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
-	zfcp_dbf_out(p, "fsf_prot_status", "0x%08x", r->fsf_prot_status);
-	zfcp_dbf_out(p, "fsf_status", "0x%08x", r->fsf_status);
-	zfcp_dbf_outd(p, "fsf_prot_status_qual", r->fsf_prot_status_qual,
-		      FSF_PROT_STATUS_QUAL_SIZE, 0, FSF_PROT_STATUS_QUAL_SIZE);
-	zfcp_dbf_outd(p, "fsf_status_qual", r->fsf_status_qual,
-		      FSF_STATUS_QUALIFIER_SIZE, 0, FSF_STATUS_QUALIFIER_SIZE);
-	zfcp_dbf_out(p, "fsf_req_status", "0x%08x", r->fsf_req_status);
-	zfcp_dbf_out(p, "sbal_first", "0x%02x", r->sbal_first);
-	zfcp_dbf_out(p, "sbal_last", "0x%02x", r->sbal_last);
-	zfcp_dbf_out(p, "sbal_response", "0x%02x", r->sbal_response);
-	zfcp_dbf_out(p, "pool", "0x%02x", r->pool);
-
-	switch (r->fsf_command) {
-	case FSF_QTCB_FCP_CMND:
-		if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
-			break;
-		zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir);
-		zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
-		*p += sprintf(*p, "\n");
-		break;
-
-	case FSF_QTCB_OPEN_PORT_WITH_DID:
-	case FSF_QTCB_CLOSE_PORT:
-	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
-		zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.port.wwpn);
-		zfcp_dbf_out(p, "d_id", "0x%06x", r->u.port.d_id);
-		zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.port.port_handle);
-		break;
-
-	case FSF_QTCB_OPEN_LUN:
-	case FSF_QTCB_CLOSE_LUN:
-		zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.unit.wwpn);
-		zfcp_dbf_out(p, "fcp_lun", "0x%016Lx", r->u.unit.fcp_lun);
-		zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.unit.port_handle);
-		zfcp_dbf_out(p, "lun_handle", "0x%08x", r->u.unit.lun_handle);
-		break;
-
-	case FSF_QTCB_SEND_ELS:
-		zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id);
-		break;
-
-	case FSF_QTCB_ABORT_FCP_CMND:
-	case FSF_QTCB_SEND_GENERIC:
-	case FSF_QTCB_EXCHANGE_CONFIG_DATA:
-	case FSF_QTCB_EXCHANGE_PORT_DATA:
-	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
-	case FSF_QTCB_UPLOAD_CONTROL_FILE:
-		break;
+	rec->adapter_status = atomic_read(&adapter->status);
+	if (port) {
+		rec->port_status = atomic_read(&port->status);
+		rec->wwpn = port->wwpn;
+		rec->d_id = port->d_id;
+	}
+	if (sdev) {
+		rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status);
+		rec->lun = zfcp_scsi_dev_lun(sdev);
 	}
 }
 
-static void zfcp_dbf_hba_view_status(char **p,
-				     struct zfcp_dbf_hba_record_status *r)
-{
-	zfcp_dbf_out(p, "failed", "0x%02x", r->failed);
-	zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type);
-	zfcp_dbf_out(p, "status_subtype", "0x%08x", r->status_subtype);
-	zfcp_dbf_outd(p, "queue_designator", (char *)&r->queue_designator,
-		      sizeof(struct fsf_queue_designator), 0,
-		      sizeof(struct fsf_queue_designator));
-	zfcp_dbf_outd(p, "payload", (char *)&r->payload, r->payload_size, 0,
-		      r->payload_size);
-}
-
-static void zfcp_dbf_hba_view_qdio(char **p, struct zfcp_dbf_hba_record_qdio *r)
-{
-	zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error);
-	zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index);
-	zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
-}
-
-static void zfcp_dbf_hba_view_berr(char **p, struct fsf_bit_error_payload *r)
-{
-	zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count);
-	zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count);
-	zfcp_dbf_out(p, "loss_of_sig_err", "%d", r->loss_of_signal_error_count);
-	zfcp_dbf_out(p, "prim_seq_err", "%d",
-		     r->primitive_sequence_error_count);
-	zfcp_dbf_out(p, "inval_trans_word_err", "%d",
-		     r->invalid_transmission_word_error_count);
-	zfcp_dbf_out(p, "CRC_errors", "%d", r->crc_error_count);
-	zfcp_dbf_out(p, "prim_seq_event_to", "%d",
-		     r->primitive_sequence_event_timeout_count);
-	zfcp_dbf_out(p, "elast_buf_overrun_err", "%d",
-		     r->elastic_buffer_overrun_error_count);
-	zfcp_dbf_out(p, "adv_rec_buf2buf_cred", "%d",
-		     r->advertised_receive_b2b_credit);
-	zfcp_dbf_out(p, "curr_rec_buf2buf_cred", "%d",
-		     r->current_receive_b2b_credit);
-	zfcp_dbf_out(p, "adv_trans_buf2buf_cred", "%d",
-		     r->advertised_transmit_b2b_credit);
-	zfcp_dbf_out(p, "curr_trans_buf2buf_cred", "%d",
-		     r->current_transmit_b2b_credit);
-}
-
-static int zfcp_dbf_hba_view_format(debug_info_t *id, struct debug_view *view,
-				    char *out_buf, const char *in_buf)
-{
-	struct zfcp_dbf_hba_record *r = (struct zfcp_dbf_hba_record *)in_buf;
-	char *p = out_buf;
-
-	if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
-		return 0;
-
-	zfcp_dbf_tag(&p, "tag", r->tag);
-	if (isalpha(r->tag2[0]))
-		zfcp_dbf_tag(&p, "tag2", r->tag2);
-
-	if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
-		zfcp_dbf_hba_view_response(&p, &r->u.response);
-	else if (strncmp(r->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
-		zfcp_dbf_hba_view_status(&p, &r->u.status);
-	else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
-		zfcp_dbf_hba_view_qdio(&p, &r->u.qdio);
-	else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0)
-		zfcp_dbf_hba_view_berr(&p, &r->u.berr);
-
-	if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0)
-		p += sprintf(p, "\n");
-	return p - out_buf;
-}
-
-static struct debug_view zfcp_dbf_hba_view = {
-	.name = "structured",
-	.header_proc = zfcp_dbf_view_header,
-	.format_proc = zfcp_dbf_hba_view_format,
-};
-
-static const char *zfcp_dbf_rec_tags[] = {
-	[ZFCP_REC_DBF_ID_THREAD] = "thread",
-	[ZFCP_REC_DBF_ID_TARGET] = "target",
-	[ZFCP_REC_DBF_ID_TRIGGER] = "trigger",
-	[ZFCP_REC_DBF_ID_ACTION] = "action",
-};
-
-static int zfcp_dbf_rec_view_format(debug_info_t *id, struct debug_view *view,
-				    char *buf, const char *_rec)
-{
-	struct zfcp_dbf_rec_record *r = (struct zfcp_dbf_rec_record *)_rec;
-	char *p = buf;
-	char hint[ZFCP_DBF_ID_SIZE + 1];
-
-	memcpy(hint, r->id2, ZFCP_DBF_ID_SIZE);
-	hint[ZFCP_DBF_ID_SIZE] = 0;
-	zfcp_dbf_outs(&p, "tag", zfcp_dbf_rec_tags[r->id]);
-	zfcp_dbf_outs(&p, "hint", hint);
-	switch (r->id) {
-	case ZFCP_REC_DBF_ID_THREAD:
-		zfcp_dbf_out(&p, "total", "%d", r->u.thread.total);
-		zfcp_dbf_out(&p, "ready", "%d", r->u.thread.ready);
-		zfcp_dbf_out(&p, "running", "%d", r->u.thread.running);
-		break;
-	case ZFCP_REC_DBF_ID_TARGET:
-		zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.target.ref);
-		zfcp_dbf_out(&p, "status", "0x%08x", r->u.target.status);
-		zfcp_dbf_out(&p, "erp_count", "%d", r->u.target.erp_count);
-		zfcp_dbf_out(&p, "d_id", "0x%06x", r->u.target.d_id);
-		zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.target.wwpn);
-		zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.target.fcp_lun);
-		break;
-	case ZFCP_REC_DBF_ID_TRIGGER:
-		zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.trigger.ref);
-		zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.trigger.action);
-		zfcp_dbf_out(&p, "requested", "%d", r->u.trigger.want);
-		zfcp_dbf_out(&p, "executed", "%d", r->u.trigger.need);
-		zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.trigger.wwpn);
-		zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun);
-		zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as);
-		zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps);
-		zfcp_dbf_out(&p, "lun_status", "0x%08x", r->u.trigger.ls);
-		break;
-	case ZFCP_REC_DBF_ID_ACTION:
-		zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
-		zfcp_dbf_out(&p, "fsf_req", "0x%016Lx", r->u.action.fsf_req);
-		zfcp_dbf_out(&p, "status", "0x%08Lx", r->u.action.status);
-		zfcp_dbf_out(&p, "step", "0x%08Lx", r->u.action.step);
-		break;
-	}
-	p += sprintf(p, "\n");
-	return p - buf;
-}
-
-static struct debug_view zfcp_dbf_rec_view = {
-	.name = "structured",
-	.header_proc = zfcp_dbf_view_header,
-	.format_proc = zfcp_dbf_rec_view_format,
-};
-
 /**
- * zfcp_dbf_rec_thread - trace event related to recovery thread operation
- * @id2: identifier for event
- * @dbf: reference to dbf structure
- * This function assumes that the caller is holding erp_lock.
+ * zfcp_dbf_rec_trig - trace event related to triggered recovery
+ * @tag: identifier for event
+ * @adapter: adapter on which the erp_action should run
+ * @port: remote port involved in the erp_action
+ * @sdev: scsi device involved in the erp_action
+ * @want: wanted erp_action
+ * @need: required erp_action
+ *
+ * The adapter->erp_lock has to be held.
  */
-void zfcp_dbf_rec_thread(char *id2, struct zfcp_dbf *dbf)
+void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter,
+		       struct zfcp_port *port, struct scsi_device *sdev,
+		       u8 want, u8 need)
 {
-	struct zfcp_adapter *adapter = dbf->adapter;
-	struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
-	unsigned long flags = 0;
+	struct zfcp_dbf *dbf = adapter->dbf;
+	struct zfcp_dbf_rec *rec = &dbf->rec_buf;
 	struct list_head *entry;
-	unsigned ready = 0, running = 0, total;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dbf->rec_lock, flags);
+	memset(rec, 0, sizeof(*rec));
+
+	rec->id = ZFCP_DBF_REC_TRIG;
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	zfcp_dbf_set_common(rec, adapter, port, sdev);
 
 	list_for_each(entry, &adapter->erp_ready_head)
-		ready++;
+		rec->u.trig.ready++;
+
 	list_for_each(entry, &adapter->erp_running_head)
-		running++;
-	total = adapter->erp_total_count;
+		rec->u.trig.running++;
 
-	spin_lock_irqsave(&dbf->rec_lock, flags);
-	memset(r, 0, sizeof(*r));
-	r->id = ZFCP_REC_DBF_ID_THREAD;
-	memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
-	r->u.thread.total = total;
-	r->u.thread.ready = ready;
-	r->u.thread.running = running;
-	debug_event(dbf->rec, 6, r, sizeof(*r));
+	rec->u.trig.want = want;
+	rec->u.trig.need = need;
+
+	debug_event(dbf->rec, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
+
 /**
- * zfcp_dbf_rec_thread - trace event related to recovery thread operation
- * @id2: identifier for event
- * @adapter: adapter
- * This function assumes that the caller does not hold erp_lock.
+ * zfcp_dbf_rec_run - trace event related to running recovery
+ * @tag: identifier for event
+ * @erp: erp_action running
  */
-void zfcp_dbf_rec_thread_lock(char *id2, struct zfcp_dbf *dbf)
+void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
 {
-	struct zfcp_adapter *adapter = dbf->adapter;
-	unsigned long flags;
-
-	read_lock_irqsave(&adapter->erp_lock, flags);
-	zfcp_dbf_rec_thread(id2, dbf);
-	read_unlock_irqrestore(&adapter->erp_lock, flags);
-}
-
-static void zfcp_dbf_rec_target(char *id2, void *ref, struct zfcp_dbf *dbf,
-				atomic_t *status, atomic_t *erp_count, u64 wwpn,
-				u32 d_id, u64 fcp_lun)
-{
-	struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
+	struct zfcp_dbf *dbf = erp->adapter->dbf;
+	struct zfcp_dbf_rec *rec = &dbf->rec_buf;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dbf->rec_lock, flags);
-	memset(r, 0, sizeof(*r));
-	r->id = ZFCP_REC_DBF_ID_TARGET;
-	memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
-	r->u.target.ref = (unsigned long)ref;
-	r->u.target.status = atomic_read(status);
-	r->u.target.wwpn = wwpn;
-	r->u.target.d_id = d_id;
-	r->u.target.fcp_lun = fcp_lun;
-	r->u.target.erp_count = atomic_read(erp_count);
-	debug_event(dbf->rec, 3, r, sizeof(*r));
+	memset(rec, 0, sizeof(*rec));
+
+	rec->id = ZFCP_DBF_REC_RUN;
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	zfcp_dbf_set_common(rec, erp->adapter, erp->port, erp->sdev);
+
+	rec->u.run.fsf_req_id = erp->fsf_req_id;
+	rec->u.run.rec_status = erp->status;
+	rec->u.run.rec_step = erp->step;
+	rec->u.run.rec_action = erp->action;
+
+	if (erp->sdev)
+		rec->u.run.rec_count =
+			atomic_read(&sdev_to_zfcp(erp->sdev)->erp_counter);
+	else if (erp->port)
+		rec->u.run.rec_count = atomic_read(&erp->port->erp_counter);
+	else
+		rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter);
+
+	debug_event(dbf->rec, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
-/**
- * zfcp_dbf_rec_adapter - trace event for adapter state change
- * @id: identifier for trigger of state change
- * @ref: additional reference (e.g. request)
- * @dbf: reference to dbf structure
- */
-void zfcp_dbf_rec_adapter(char *id, void *ref, struct zfcp_dbf *dbf)
+static inline
+void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len,
+		  u64 req_id, u32 d_id)
 {
-	struct zfcp_adapter *adapter = dbf->adapter;
-
-	zfcp_dbf_rec_target(id, ref, dbf, &adapter->status,
-			    &adapter->erp_counter, 0, 0,
-			    ZFCP_DBF_INVALID_LUN);
-}
-
-/**
- * zfcp_dbf_rec_port - trace event for port state change
- * @id: identifier for trigger of state change
- * @ref: additional reference (e.g. request)
- * @port: port
- */
-void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port)
-{
-	struct zfcp_dbf *dbf = port->adapter->dbf;
-
-	zfcp_dbf_rec_target(id, ref, dbf, &port->status,
-			    &port->erp_counter, port->wwpn, port->d_id,
-			    ZFCP_DBF_INVALID_LUN);
-}
-
-/**
- * zfcp_dbf_rec_lun - trace event for LUN state change
- * @id: identifier for trigger of state change
- * @ref: additional reference (e.g. request)
- * @sdev: SCSI device
- */
-void zfcp_dbf_rec_lun(char *id, void *ref, struct scsi_device *sdev)
-{
-	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
-	struct zfcp_port *port = zfcp_sdev->port;
-	struct zfcp_dbf *dbf = port->adapter->dbf;
-
-	zfcp_dbf_rec_target(id, ref, dbf, &zfcp_sdev->status,
-			    &zfcp_sdev->erp_counter, port->wwpn, port->d_id,
-			    zfcp_scsi_dev_lun(sdev));
-}
-
-/**
- * zfcp_dbf_rec_trigger - trace event for triggered error recovery
- * @id2: identifier for error recovery trigger
- * @ref: additional reference (e.g. request)
- * @want: originally requested error recovery action
- * @need: error recovery action actually initiated
- * @action: address of error recovery action struct
- * @adapter: adapter
- * @port: port
- * @sdev: SCSI device
- */
-void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
-			  struct zfcp_adapter *adapter, struct zfcp_port *port,
-			  struct scsi_device *sdev)
-{
-	struct zfcp_dbf *dbf = adapter->dbf;
-	struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dbf->rec_lock, flags);
-	memset(r, 0, sizeof(*r));
-	r->id = ZFCP_REC_DBF_ID_TRIGGER;
-	memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
-	r->u.trigger.ref = (unsigned long)ref;
-	r->u.trigger.want = want;
-	r->u.trigger.need = need;
-	r->u.trigger.action = (unsigned long)action;
-	r->u.trigger.as = atomic_read(&adapter->status);
-	if (port) {
-		r->u.trigger.ps = atomic_read(&port->status);
-		r->u.trigger.wwpn = port->wwpn;
-	}
-	if (sdev)
-		r->u.trigger.ls = atomic_read(&sdev_to_zfcp(sdev)->status);
-	r->u.trigger.fcp_lun = sdev ? zfcp_scsi_dev_lun(sdev) :
-				      ZFCP_DBF_INVALID_LUN;
-	debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
-	spin_unlock_irqrestore(&dbf->rec_lock, flags);
-}
-
-/**
- * zfcp_dbf_rec_action - trace event showing progress of recovery action
- * @id2: identifier
- * @erp_action: error recovery action struct pointer
- */
-void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action)
-{
-	struct zfcp_dbf *dbf = erp_action->adapter->dbf;
-	struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dbf->rec_lock, flags);
-	memset(r, 0, sizeof(*r));
-	r->id = ZFCP_REC_DBF_ID_ACTION;
-	memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
-	r->u.action.action = (unsigned long)erp_action;
-	r->u.action.status = erp_action->status;
-	r->u.action.step = erp_action->step;
-	r->u.action.fsf_req = erp_action->fsf_req_id;
-	debug_event(dbf->rec, 5, r, sizeof(*r));
-	spin_unlock_irqrestore(&dbf->rec_lock, flags);
-}
-
-/**
- * zfcp_dbf_san_ct_request - trace event for issued CT request
- * @fsf_req: request containing issued CT data
- * @d_id: destination id where ct request is sent to
- */
-void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req, u32 d_id)
-{
-	struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data;
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-	struct zfcp_dbf *dbf = adapter->dbf;
-	struct fc_ct_hdr *hdr = sg_virt(ct->req);
-	struct zfcp_dbf_san_record *r = &dbf->san_buf;
-	struct zfcp_dbf_san_record_ct_request *oct = &r->u.ct_req;
-	int level = 3;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dbf->san_lock, flags);
-	memset(r, 0, sizeof(*r));
-	strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE);
-	r->fsf_reqid = fsf_req->req_id;
-	r->fsf_seqno = fsf_req->seq_no;
-	oct->d_id = d_id;
-	oct->cmd_req_code = hdr->ct_cmd;
-	oct->revision = hdr->ct_rev;
-	oct->gs_type = hdr->ct_fs_type;
-	oct->gs_subtype = hdr->ct_fs_subtype;
-	oct->options = hdr->ct_options;
-	oct->max_res_size = hdr->ct_mr_size;
-	oct->len = min((int)ct->req->length - (int)sizeof(struct fc_ct_hdr),
-		       ZFCP_DBF_SAN_MAX_PAYLOAD);
-	debug_event(dbf->san, level, r, sizeof(*r));
-	zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
-			 (void *)hdr + sizeof(struct fc_ct_hdr), oct->len);
-	spin_unlock_irqrestore(&dbf->san_lock, flags);
-}
-
-/**
- * zfcp_dbf_san_ct_response - trace event for completion of CT request
- * @fsf_req: request containing CT response
- */
-void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req)
-{
-	struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data;
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-	struct fc_ct_hdr *hdr = sg_virt(ct->resp);
-	struct zfcp_dbf *dbf = adapter->dbf;
-	struct zfcp_dbf_san_record *r = &dbf->san_buf;
-	struct zfcp_dbf_san_record_ct_response *rct = &r->u.ct_resp;
-	int level = 3;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dbf->san_lock, flags);
-	memset(r, 0, sizeof(*r));
-	strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
-	r->fsf_reqid = fsf_req->req_id;
-	r->fsf_seqno = fsf_req->seq_no;
-	rct->cmd_rsp_code = hdr->ct_cmd;
-	rct->revision = hdr->ct_rev;
-	rct->reason_code = hdr->ct_reason;
-	rct->expl = hdr->ct_explan;
-	rct->vendor_unique = hdr->ct_vendor;
-	rct->max_res_size = hdr->ct_mr_size;
-	rct->len = min((int)ct->resp->length - (int)sizeof(struct fc_ct_hdr),
-		       ZFCP_DBF_SAN_MAX_PAYLOAD);
-	debug_event(dbf->san, level, r, sizeof(*r));
-	zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
-			 (void *)hdr + sizeof(struct fc_ct_hdr), rct->len);
-	spin_unlock_irqrestore(&dbf->san_lock, flags);
-}
-
-static void zfcp_dbf_san_els(const char *tag, int level,
-			     struct zfcp_fsf_req *fsf_req, u32 d_id,
-			     void *buffer, int buflen)
-{
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-	struct zfcp_dbf *dbf = adapter->dbf;
-	struct zfcp_dbf_san_record *rec = &dbf->san_buf;
+	struct zfcp_dbf_san *rec = &dbf->san_buf;
+	u16 rec_len;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dbf->san_lock, flags);
 	memset(rec, 0, sizeof(*rec));
-	strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
-	rec->fsf_reqid = fsf_req->req_id;
-	rec->fsf_seqno = fsf_req->seq_no;
-	rec->u.els.d_id = d_id;
-	debug_event(dbf->san, level, rec, sizeof(*rec));
-	zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level,
-			 buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD));
+
+	rec->id = id;
+	rec->fsf_req_id = req_id;
+	rec->d_id = d_id;
+	rec_len = min(len, (u16)ZFCP_DBF_SAN_MAX_PAYLOAD);
+	memcpy(rec->payload, data, rec_len);
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+
+	debug_event(dbf->san, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->san_lock, flags);
 }
 
 /**
- * zfcp_dbf_san_els_request - trace event for issued ELS
- * @fsf_req: request containing issued ELS
+ * zfcp_dbf_san_req - trace event for issued SAN request
+ * @tag: indentifier for event
+ * @fsf_req: request containing issued CT data
+ * d_id: destination ID
  */
-void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id)
 {
-	struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data;
-	u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id);
+	struct zfcp_dbf *dbf = fsf->adapter->dbf;
+	struct zfcp_fsf_ct_els *ct_els = fsf->data;
+	u16 length;
 
-	zfcp_dbf_san_els("oels", 2, fsf_req, d_id,
-			 sg_virt(els->req), els->req->length);
+	length = (u16)(ct_els->req->length + FC_CT_HDR_LEN);
+	zfcp_dbf_san(tag, dbf, sg_virt(ct_els->req), ZFCP_DBF_SAN_REQ, length,
+		     fsf->req_id, d_id);
 }
 
 /**
- * zfcp_dbf_san_els_response - trace event for completed ELS
- * @fsf_req: request containing ELS response
+ * zfcp_dbf_san_res - trace event for received SAN request
+ * @tag: indentifier for event
+ * @fsf_req: request containing issued CT data
  */
-void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf)
 {
-	struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data;
-	u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id);
+	struct zfcp_dbf *dbf = fsf->adapter->dbf;
+	struct zfcp_fsf_ct_els *ct_els = fsf->data;
+	u16 length;
 
-	zfcp_dbf_san_els("rels", 2, fsf_req, d_id,
-			       sg_virt(els->resp), els->resp->length);
+	length = (u16)(ct_els->resp->length + FC_CT_HDR_LEN);
+	zfcp_dbf_san(tag, dbf, sg_virt(ct_els->resp), ZFCP_DBF_SAN_RES, length,
+		     fsf->req_id, 0);
 }
 
 /**
- * zfcp_dbf_san_incoming_els - trace event for incomig ELS
- * @fsf_req: request containing unsolicited status buffer with incoming ELS
+ * zfcp_dbf_san_in_els - trace event for incoming ELS
+ * @tag: indentifier for event
+ * @fsf_req: request containing issued CT data
  */
-void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req)
+void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf)
 {
-	struct fsf_status_read_buffer *buf =
-			(struct fsf_status_read_buffer *)fsf_req->data;
-	int length = (int)buf->length -
-		     (int)((void *)&buf->payload - (void *)buf);
+	struct zfcp_dbf *dbf = fsf->adapter->dbf;
+	struct fsf_status_read_buffer *srb =
+		(struct fsf_status_read_buffer *) fsf->data;
+	u16 length;
 
-	zfcp_dbf_san_els("iels", 1, fsf_req, ntoh24(buf->d_id),
-			       (void *)buf->payload.data, length);
+	length = (u16)(srb->length -
+			offsetof(struct fsf_status_read_buffer, payload));
+	zfcp_dbf_san(tag, dbf, srb->payload.data, ZFCP_DBF_SAN_ELS, length,
+		     fsf->req_id, ntoh24(srb->d_id));
 }
 
-static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view,
-				    char *out_buf, const char *in_buf)
+/**
+ * zfcp_dbf_scsi - trace event for scsi commands
+ * @tag: identifier for event
+ * @sc: pointer to struct scsi_cmnd
+ * @fsf: pointer to struct zfcp_fsf_req
+ */
+void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf)
 {
-	struct zfcp_dbf_san_record *r = (struct zfcp_dbf_san_record *)in_buf;
-	char *p = out_buf;
-
-	if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
-		return 0;
-
-	zfcp_dbf_tag(&p, "tag", r->tag);
-	zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
-	zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
-
-	if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
-		struct zfcp_dbf_san_record_ct_request *ct = &r->u.ct_req;
-		zfcp_dbf_out(&p, "d_id", "0x%06x", ct->d_id);
-		zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code);
-		zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
-		zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type);
-		zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype);
-		zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
-		zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
-	} else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
-		struct zfcp_dbf_san_record_ct_response *ct = &r->u.ct_resp;
-		zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code);
-		zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
-		zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
-		zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
-		zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
-		zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
-	} else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
-		   strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
-		   strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
-		struct zfcp_dbf_san_record_els *els = &r->u.els;
-		zfcp_dbf_out(&p, "d_id", "0x%06x", els->d_id);
-	}
-	return p - out_buf;
-}
-
-static struct debug_view zfcp_dbf_san_view = {
-	.name = "structured",
-	.header_proc = zfcp_dbf_view_header,
-	.format_proc = zfcp_dbf_san_view_format,
-};
-
-void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
-		    struct zfcp_dbf *dbf, struct scsi_cmnd *scsi_cmnd,
-		    struct zfcp_fsf_req *fsf_req, unsigned long old_req_id)
-{
-	struct zfcp_dbf_scsi_record *rec = &dbf->scsi_buf;
-	struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
-	unsigned long flags;
+	struct zfcp_adapter *adapter =
+		(struct zfcp_adapter *) sc->device->host->hostdata[0];
+	struct zfcp_dbf *dbf = adapter->dbf;
+	struct zfcp_dbf_scsi *rec = &dbf->scsi_buf;
 	struct fcp_resp_with_ext *fcp_rsp;
-	struct fcp_resp_rsp_info *fcp_rsp_info = NULL;
-	char *fcp_sns_info = NULL;
-	int offset = 0, buflen = 0;
+	struct fcp_resp_rsp_info *fcp_rsp_info;
+	unsigned long flags;
 
 	spin_lock_irqsave(&dbf->scsi_lock, flags);
-	do {
-		memset(rec, 0, sizeof(*rec));
-		if (offset == 0) {
-			strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
-			strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
-			if (scsi_cmnd != NULL) {
-				if (scsi_cmnd->device) {
-					rec->scsi_id = scsi_cmnd->device->id;
-					rec->scsi_lun = scsi_cmnd->device->lun;
-				}
-				rec->scsi_result = scsi_cmnd->result;
-				rec->scsi_cmnd = (unsigned long)scsi_cmnd;
-				memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
-					min((int)scsi_cmnd->cmd_len,
-						ZFCP_DBF_SCSI_OPCODE));
-				rec->scsi_retries = scsi_cmnd->retries;
-				rec->scsi_allowed = scsi_cmnd->allowed;
-			}
-			if (fsf_req != NULL) {
-				fcp_rsp = (struct fcp_resp_with_ext *)
-					&(fsf_req->qtcb->bottom.io.fcp_rsp);
-				fcp_rsp_info = (struct fcp_resp_rsp_info *)
-					&fcp_rsp[1];
-				fcp_sns_info = (char *) &fcp_rsp[1];
-				if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL)
-					fcp_sns_info += fcp_rsp->ext.fr_sns_len;
+	memset(rec, 0, sizeof(*rec));
 
-				rec->rsp_validity = fcp_rsp->resp.fr_flags;
-				rec->rsp_scsi_status = fcp_rsp->resp.fr_status;
-				rec->rsp_resid = fcp_rsp->ext.fr_resid;
-				if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL)
-					rec->rsp_code = fcp_rsp_info->rsp_code;
-				if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) {
-					buflen = min(fcp_rsp->ext.fr_sns_len,
-					   (u32)ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
-					rec->sns_info_len = buflen;
-					memcpy(rec->sns_info, fcp_sns_info,
-					       min(buflen,
-						   ZFCP_DBF_SCSI_FCP_SNS_INFO));
-					offset += min(buflen,
-						      ZFCP_DBF_SCSI_FCP_SNS_INFO);
-				}
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->id = ZFCP_DBF_SCSI_CMND;
+	rec->scsi_result = sc->result;
+	rec->scsi_retries = sc->retries;
+	rec->scsi_allowed = sc->allowed;
+	rec->scsi_id = sc->device->id;
+	rec->scsi_lun = sc->device->lun;
+	rec->host_scribble = (unsigned long)sc->host_scribble;
 
-				rec->fsf_reqid = fsf_req->req_id;
-				rec->fsf_seqno = fsf_req->seq_no;
-				rec->fsf_issued = fsf_req->issued;
-			}
-			rec->old_fsf_reqid = old_req_id;
-		} else {
-			strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
-			dump->total_size = buflen;
-			dump->offset = offset;
-			dump->size = min(buflen - offset,
-					 (int)sizeof(struct
-						     zfcp_dbf_scsi_record) -
-					 (int)sizeof(struct zfcp_dbf_dump));
-			memcpy(dump->data, fcp_sns_info + offset, dump->size);
-			offset += dump->size;
+	memcpy(rec->scsi_opcode, sc->cmnd,
+	       min((int)sc->cmd_len, ZFCP_DBF_SCSI_OPCODE));
+
+	if (fsf) {
+		rec->fsf_req_id = fsf->req_id;
+		fcp_rsp = (struct fcp_resp_with_ext *)
+				&(fsf->qtcb->bottom.io.fcp_rsp);
+		memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT);
+		if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) {
+			fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+			rec->fcp_rsp_info = fcp_rsp_info->rsp_code;
 		}
-		debug_event(dbf->scsi, level, rec, sizeof(*rec));
-	} while (offset < buflen);
+		if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) {
+			rec->pl_len = min((u16)SCSI_SENSE_BUFFERSIZE,
+					  (u16)ZFCP_DBF_PAY_MAX_REC);
+			zfcp_dbf_pl_write(dbf, sc->sense_buffer, rec->pl_len,
+					  "fcp_sns", fsf->req_id);
+		}
+	}
+
+	debug_event(dbf->scsi, 1, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->scsi_lock, flags);
 }
 
-static int zfcp_dbf_scsi_view_format(debug_info_t *id, struct debug_view *view,
-				     char *out_buf, const char *in_buf)
-{
-	struct zfcp_dbf_scsi_record *r = (struct zfcp_dbf_scsi_record *)in_buf;
-	struct timespec t;
-	char *p = out_buf;
-
-	if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
-		return 0;
-
-	zfcp_dbf_tag(&p, "tag", r->tag);
-	zfcp_dbf_tag(&p, "tag2", r->tag2);
-	zfcp_dbf_out(&p, "scsi_id", "0x%08x", r->scsi_id);
-	zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun);
-	zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result);
-	zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd);
-	zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE,
-		      0, ZFCP_DBF_SCSI_OPCODE);
-	zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries);
-	zfcp_dbf_out(&p, "scsi_allowed", "0x%02x", r->scsi_allowed);
-	if (strncmp(r->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0)
-		zfcp_dbf_out(&p, "old_fsf_reqid", "0x%0Lx", r->old_fsf_reqid);
-	zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
-	zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
-	stck_to_timespec(r->fsf_issued, &t);
-	zfcp_dbf_out(&p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
-
-	if (strncmp(r->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
-		zfcp_dbf_out(&p, "fcp_rsp_validity", "0x%02x", r->rsp_validity);
-		zfcp_dbf_out(&p, "fcp_rsp_scsi_status", "0x%02x",
-			     r->rsp_scsi_status);
-		zfcp_dbf_out(&p, "fcp_rsp_resid", "0x%08x", r->rsp_resid);
-		zfcp_dbf_out(&p, "fcp_rsp_code", "0x%08x", r->rsp_code);
-		zfcp_dbf_out(&p, "fcp_sns_info_len", "0x%08x", r->sns_info_len);
-		zfcp_dbf_outd(&p, "fcp_sns_info", r->sns_info,
-			      min((int)r->sns_info_len,
-			      ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
-			      r->sns_info_len);
-	}
-	p += sprintf(p, "\n");
-	return p - out_buf;
-}
-
-static struct debug_view zfcp_dbf_scsi_view = {
-	.name = "structured",
-	.header_proc = zfcp_dbf_view_header,
-	.format_proc = zfcp_dbf_scsi_view_format,
-};
-
-static debug_info_t *zfcp_dbf_reg(const char *name, int level,
-				  struct debug_view *view, int size)
+static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size)
 {
 	struct debug_info *d;
 
-	d = debug_register(name, dbfsize, level, size);
+	d = debug_register(name, size, 1, rec_size);
 	if (!d)
 		return NULL;
 
 	debug_register_view(d, &debug_hex_ascii_view);
-	debug_register_view(d, view);
-	debug_set_level(d, level);
+	debug_set_level(d, 3);
 
 	return d;
 }
 
+static void zfcp_dbf_unregister(struct zfcp_dbf *dbf)
+{
+	if (!dbf)
+		return;
+
+	debug_unregister(dbf->scsi);
+	debug_unregister(dbf->san);
+	debug_unregister(dbf->hba);
+	debug_unregister(dbf->pay);
+	debug_unregister(dbf->rec);
+	kfree(dbf);
+}
+
 /**
  * zfcp_adapter_debug_register - registers debug feature for an adapter
  * @adapter: pointer to adapter for which debug features should be registered
@@ -1003,69 +415,66 @@
  */
 int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter)
 {
-	char dbf_name[DEBUG_MAX_NAME_LEN];
+	char name[DEBUG_MAX_NAME_LEN];
 	struct zfcp_dbf *dbf;
 
 	dbf = kzalloc(sizeof(struct zfcp_dbf), GFP_KERNEL);
 	if (!dbf)
 		return -ENOMEM;
 
-	dbf->adapter = adapter;
-
+	spin_lock_init(&dbf->pay_lock);
 	spin_lock_init(&dbf->hba_lock);
 	spin_lock_init(&dbf->san_lock);
 	spin_lock_init(&dbf->scsi_lock);
 	spin_lock_init(&dbf->rec_lock);
 
 	/* debug feature area which records recovery activity */
-	sprintf(dbf_name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev));
-	dbf->rec = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_rec_view,
-				sizeof(struct zfcp_dbf_rec_record));
+	sprintf(name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev));
+	dbf->rec = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_rec));
 	if (!dbf->rec)
 		goto err_out;
 
 	/* debug feature area which records HBA (FSF and QDIO) conditions */
-	sprintf(dbf_name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev));
-	dbf->hba = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_hba_view,
-				sizeof(struct zfcp_dbf_hba_record));
+	sprintf(name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev));
+	dbf->hba = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_hba));
 	if (!dbf->hba)
 		goto err_out;
 
+	/* debug feature area which records payload info */
+	sprintf(name, "zfcp_%s_pay", dev_name(&adapter->ccw_device->dev));
+	dbf->pay = zfcp_dbf_reg(name, dbfsize * 2, sizeof(struct zfcp_dbf_pay));
+	if (!dbf->pay)
+		goto err_out;
+
 	/* debug feature area which records SAN command failures and recovery */
-	sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev));
-	dbf->san = zfcp_dbf_reg(dbf_name, 6, &zfcp_dbf_san_view,
-				sizeof(struct zfcp_dbf_san_record));
+	sprintf(name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev));
+	dbf->san = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_san));
 	if (!dbf->san)
 		goto err_out;
 
 	/* debug feature area which records SCSI command failures and recovery */
-	sprintf(dbf_name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev));
-	dbf->scsi = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_scsi_view,
-				 sizeof(struct zfcp_dbf_scsi_record));
+	sprintf(name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev));
+	dbf->scsi = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_scsi));
 	if (!dbf->scsi)
 		goto err_out;
 
 	adapter->dbf = dbf;
-	return 0;
 
+	return 0;
 err_out:
-	zfcp_dbf_adapter_unregister(dbf);
+	zfcp_dbf_unregister(dbf);
 	return -ENOMEM;
 }
 
 /**
  * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
- * @dbf: pointer to dbf for which debug features should be unregistered
+ * @adapter: pointer to adapter for which debug features should be unregistered
  */
-void zfcp_dbf_adapter_unregister(struct zfcp_dbf *dbf)
+void zfcp_dbf_adapter_unregister(struct zfcp_adapter *adapter)
 {
-	if (!dbf)
-		return;
-	debug_unregister(dbf->scsi);
-	debug_unregister(dbf->san);
-	debug_unregister(dbf->hba);
-	debug_unregister(dbf->rec);
-	dbf->adapter->dbf = NULL;
-	kfree(dbf);
+	struct zfcp_dbf *dbf = adapter->dbf;
+
+	adapter->dbf = NULL;
+	zfcp_dbf_unregister(dbf);
 }
 
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 04081b1..714f087 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -1,22 +1,8 @@
 /*
- * This file is part of the zfcp device driver for
- * FCP adapters for IBM System z9 and zSeries.
+ * zfcp device driver
+ * debug feature declarations
  *
- * Copyright IBM Corp. 2008, 2009
- *
- * This program is free software; you can redistribute 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.
+ * Copyright IBM Corp. 2008, 2010
  */
 
 #ifndef ZFCP_DBF_H
@@ -27,322 +13,350 @@
 #include "zfcp_fsf.h"
 #include "zfcp_def.h"
 
-#define ZFCP_DBF_TAG_SIZE      4
-#define ZFCP_DBF_ID_SIZE       7
+#define ZFCP_DBF_TAG_LEN       7
 
 #define ZFCP_DBF_INVALID_LUN	0xFFFFFFFFFFFFFFFFull
 
-struct zfcp_dbf_dump {
-	u8 tag[ZFCP_DBF_TAG_SIZE];
-	u32 total_size;		/* size of total dump data */
-	u32 offset;		/* how much data has being already dumped */
-	u32 size;		/* how much data comes with this record */
-	u8 data[];		/* dump data */
-} __attribute__ ((packed));
-
-struct zfcp_dbf_rec_record_thread {
-	u32 total;
+/**
+ * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action
+ * @ready: number of ready recovery actions
+ * @running: number of running recovery actions
+ * @want: wanted recovery action
+ * @need: needed recovery action
+ */
+struct zfcp_dbf_rec_trigger {
 	u32 ready;
 	u32 running;
-};
-
-struct zfcp_dbf_rec_record_target {
-	u64 ref;
-	u32 status;
-	u32 d_id;
-	u64 wwpn;
-	u64 fcp_lun;
-	u32 erp_count;
-};
-
-struct zfcp_dbf_rec_record_trigger {
 	u8 want;
 	u8 need;
-	u32 as;
-	u32 ps;
-	u32 ls;
-	u64 ref;
-	u64 action;
-	u64 wwpn;
-	u64 fcp_lun;
+} __packed;
+
+/**
+ * struct zfcp_dbf_rec_running - trace record for running recovery
+ * @fsf_req_id: request id for fsf requests
+ * @rec_status: status of the fsf request
+ * @rec_step: current step of the recovery action
+ * rec_count: recovery counter
+ */
+struct zfcp_dbf_rec_running {
+	u64 fsf_req_id;
+	u32 rec_status;
+	u16 rec_step;
+	u8 rec_action;
+	u8 rec_count;
+} __packed;
+
+/**
+ * enum zfcp_dbf_rec_id - recovery trace record id
+ * @ZFCP_DBF_REC_TRIG: triggered recovery identifier
+ * @ZFCP_DBF_REC_RUN: running recovery identifier
+ */
+enum zfcp_dbf_rec_id {
+	ZFCP_DBF_REC_TRIG	= 1,
+	ZFCP_DBF_REC_RUN	= 2,
 };
 
-struct zfcp_dbf_rec_record_action {
-	u32 status;
-	u32 step;
-	u64 action;
-	u64 fsf_req;
-};
-
-struct zfcp_dbf_rec_record {
+/**
+ * struct zfcp_dbf_rec - trace record for error recovery actions
+ * @id: unique number of recovery record type
+ * @tag: identifier string specifying the location of initiation
+ * @lun: logical unit number
+ * @wwpn: word wide port number
+ * @d_id: destination ID
+ * @adapter_status: current status of the adapter
+ * @port_status: current status of the port
+ * @lun_status: current status of the lun
+ * @u.trig: structure zfcp_dbf_rec_trigger
+ * @u.run: structure zfcp_dbf_rec_running
+ */
+struct zfcp_dbf_rec {
 	u8 id;
-	char id2[7];
+	char tag[ZFCP_DBF_TAG_LEN];
+	u64 lun;
+	u64 wwpn;
+	u32 d_id;
+	u32 adapter_status;
+	u32 port_status;
+	u32 lun_status;
 	union {
-		struct zfcp_dbf_rec_record_action action;
-		struct zfcp_dbf_rec_record_thread thread;
-		struct zfcp_dbf_rec_record_target target;
-		struct zfcp_dbf_rec_record_trigger trigger;
+		struct zfcp_dbf_rec_trigger trig;
+		struct zfcp_dbf_rec_running run;
 	} u;
+} __packed;
+
+/**
+ * enum zfcp_dbf_san_id - SAN trace record identifier
+ * @ZFCP_DBF_SAN_REQ: request trace record id
+ * @ZFCP_DBF_SAN_RES: response trace record id
+ * @ZFCP_DBF_SAN_ELS: extended link service record id
+ */
+enum zfcp_dbf_san_id {
+	ZFCP_DBF_SAN_REQ	= 1,
+	ZFCP_DBF_SAN_RES	= 2,
+	ZFCP_DBF_SAN_ELS	= 3,
 };
 
-enum {
-	ZFCP_REC_DBF_ID_ACTION,
-	ZFCP_REC_DBF_ID_THREAD,
-	ZFCP_REC_DBF_ID_TARGET,
-	ZFCP_REC_DBF_ID_TRIGGER,
-};
+/** struct zfcp_dbf_san - trace record for SAN requests and responses
+ * @id: unique number of recovery record type
+ * @tag: identifier string specifying the location of initiation
+ * @fsf_req_id: request id for fsf requests
+ * @payload: unformatted information related to request/response
+ * @d_id: destination id
+ */
+struct zfcp_dbf_san {
+	u8 id;
+	char tag[ZFCP_DBF_TAG_LEN];
+	u64 fsf_req_id;
+	u32 d_id;
+#define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32)
+	char payload[ZFCP_DBF_SAN_MAX_PAYLOAD];
+} __packed;
 
-struct zfcp_dbf_hba_record_response {
-	u32 fsf_command;
-	u64 fsf_reqid;
-	u32 fsf_seqno;
-	u64 fsf_issued;
-	u32 fsf_prot_status;
+/**
+ * struct zfcp_dbf_hba_res - trace record for hba responses
+ * @req_issued: timestamp when request was issued
+ * @prot_status: protocol status
+ * @prot_status_qual: protocol status qualifier
+ * @fsf_status: fsf status
+ * @fsf_status_qual: fsf status qualifier
+ */
+struct zfcp_dbf_hba_res {
+	u64 req_issued;
+	u32 prot_status;
+	u8  prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
 	u32 fsf_status;
-	u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
-	u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
-	u32 fsf_req_status;
-	u8 sbal_first;
-	u8 sbal_last;
-	u8 sbal_response;
-	u8 pool;
-	u64 erp_action;
-	union {
-		struct {
-			u64 cmnd;
-			u32 data_dir;
-		} fcp;
-		struct {
-			u64 wwpn;
-			u32 d_id;
-			u32 port_handle;
-		} port;
-		struct {
-			u64 wwpn;
-			u64 fcp_lun;
-			u32 port_handle;
-			u32 lun_handle;
-		} unit;
-		struct {
-			u32 d_id;
-		} els;
-	} u;
-} __attribute__ ((packed));
+	u8  fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+} __packed;
 
-struct zfcp_dbf_hba_record_status {
-	u8 failed;
+/**
+ * struct zfcp_dbf_hba_uss - trace record for unsolicited status
+ * @status_type: type of unsolicited status
+ * @status_subtype: subtype of unsolicited status
+ * @d_id: destination ID
+ * @lun: logical unit number
+ * @queue_designator: queue designator
+ */
+struct zfcp_dbf_hba_uss {
 	u32 status_type;
 	u32 status_subtype;
-	struct fsf_queue_designator
-	 queue_designator;
-	u32 payload_size;
-#define ZFCP_DBF_UNSOL_PAYLOAD				80
-#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL		32
-#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD	56
-#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT	2 * sizeof(u32)
-	u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
-} __attribute__ ((packed));
-
-struct zfcp_dbf_hba_record_qdio {
-	u32 qdio_error;
-	u8 sbal_index;
-	u8 sbal_count;
-} __attribute__ ((packed));
-
-struct zfcp_dbf_hba_record {
-	u8 tag[ZFCP_DBF_TAG_SIZE];
-	u8 tag2[ZFCP_DBF_TAG_SIZE];
-	union {
-		struct zfcp_dbf_hba_record_response response;
-		struct zfcp_dbf_hba_record_status status;
-		struct zfcp_dbf_hba_record_qdio qdio;
-		struct fsf_bit_error_payload berr;
-	} u;
-} __attribute__ ((packed));
-
-struct zfcp_dbf_san_record_ct_request {
-	u16 cmd_req_code;
-	u8 revision;
-	u8 gs_type;
-	u8 gs_subtype;
-	u8 options;
-	u16 max_res_size;
-	u32 len;
 	u32 d_id;
-} __attribute__ ((packed));
+	u64 lun;
+	u64 queue_designator;
+} __packed;
 
-struct zfcp_dbf_san_record_ct_response {
-	u16 cmd_rsp_code;
-	u8 revision;
-	u8 reason_code;
-	u8 expl;
-	u8 vendor_unique;
-	u16 max_res_size;
-	u32 len;
-} __attribute__ ((packed));
+/**
+ * enum zfcp_dbf_hba_id - HBA trace record identifier
+ * @ZFCP_DBF_HBA_RES: response trace record
+ * @ZFCP_DBF_HBA_USS: unsolicited status trace record
+ * @ZFCP_DBF_HBA_BIT: bit error trace record
+ */
+enum zfcp_dbf_hba_id {
+	ZFCP_DBF_HBA_RES	= 1,
+	ZFCP_DBF_HBA_USS	= 2,
+	ZFCP_DBF_HBA_BIT	= 3,
+};
 
-struct zfcp_dbf_san_record_els {
-	u32 d_id;
-} __attribute__ ((packed));
-
-struct zfcp_dbf_san_record {
-	u8 tag[ZFCP_DBF_TAG_SIZE];
-	u64 fsf_reqid;
-	u32 fsf_seqno;
+/**
+ * struct zfcp_dbf_hba - common trace record for HBA records
+ * @id: unique number of recovery record type
+ * @tag: identifier string specifying the location of initiation
+ * @fsf_req_id: request id for fsf requests
+ * @fsf_req_status: status of fsf request
+ * @fsf_cmd: fsf command
+ * @fsf_seq_no: fsf sequence number
+ * @pl_len: length of payload stored as zfcp_dbf_pay
+ * @u: record type specific data
+ */
+struct zfcp_dbf_hba {
+	u8 id;
+	char tag[ZFCP_DBF_TAG_LEN];
+	u64 fsf_req_id;
+	u32 fsf_req_status;
+	u32 fsf_cmd;
+	u32 fsf_seq_no;
+	u16 pl_len;
 	union {
-		struct zfcp_dbf_san_record_ct_request ct_req;
-		struct zfcp_dbf_san_record_ct_response ct_resp;
-		struct zfcp_dbf_san_record_els els;
+		struct zfcp_dbf_hba_res res;
+		struct zfcp_dbf_hba_uss uss;
+		struct fsf_bit_error_payload be;
 	} u;
-} __attribute__ ((packed));
+} __packed;
 
-#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024
+/**
+ * enum zfcp_dbf_scsi_id - scsi trace record identifier
+ * @ZFCP_DBF_SCSI_CMND: scsi command trace record
+ */
+enum zfcp_dbf_scsi_id {
+	ZFCP_DBF_SCSI_CMND	= 1,
+};
 
-struct zfcp_dbf_scsi_record {
-	u8 tag[ZFCP_DBF_TAG_SIZE];
-	u8 tag2[ZFCP_DBF_TAG_SIZE];
+/**
+ * struct zfcp_dbf_scsi - common trace record for SCSI records
+ * @id: unique number of recovery record type
+ * @tag: identifier string specifying the location of initiation
+ * @scsi_id: scsi device id
+ * @scsi_lun: scsi device logical unit number
+ * @scsi_result: scsi result
+ * @scsi_retries: current retry number of scsi request
+ * @scsi_allowed: allowed retries
+ * @fcp_rsp_info: FCP response info
+ * @scsi_opcode: scsi opcode
+ * @fsf_req_id: request id of fsf request
+ * @host_scribble: LLD specific data attached to SCSI request
+ * @pl_len: length of paload stored as zfcp_dbf_pay
+ * @fsf_rsp: response for fsf request
+ */
+struct zfcp_dbf_scsi {
+	u8 id;
+	char tag[ZFCP_DBF_TAG_LEN];
 	u32 scsi_id;
 	u32 scsi_lun;
 	u32 scsi_result;
-	u64 scsi_cmnd;
-#define ZFCP_DBF_SCSI_OPCODE	16
-	u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
 	u8 scsi_retries;
 	u8 scsi_allowed;
-	u64 fsf_reqid;
-	u32 fsf_seqno;
-	u64 fsf_issued;
-	u64 old_fsf_reqid;
-	u8 rsp_validity;
-	u8 rsp_scsi_status;
-	u32 rsp_resid;
-	u8 rsp_code;
-#define ZFCP_DBF_SCSI_FCP_SNS_INFO	16
-#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO	256
-	u32 sns_info_len;
-	u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
-} __attribute__ ((packed));
+	u8 fcp_rsp_info;
+#define ZFCP_DBF_SCSI_OPCODE	16
+	u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
+	u64 fsf_req_id;
+	u64 host_scribble;
+	u16 pl_len;
+	struct fcp_resp_with_ext fcp_rsp;
+} __packed;
 
+/**
+ * struct zfcp_dbf_pay - trace record for unformatted payload information
+ * @area: area this record is originated from
+ * @counter: ascending record number
+ * @fsf_req_id: request id of fsf request
+ * @data: unformatted data
+ */
+struct zfcp_dbf_pay {
+	u8 counter;
+	char area[ZFCP_DBF_TAG_LEN];
+	u64 fsf_req_id;
+#define ZFCP_DBF_PAY_MAX_REC 0x100
+	char data[ZFCP_DBF_PAY_MAX_REC];
+} __packed;
+
+/**
+ * struct zfcp_dbf - main dbf trace structure
+ * @pay: reference to payload trace area
+ * @rec: reference to recovery trace area
+ * @hba: reference to hba trace area
+ * @san: reference to san trace area
+ * @scsi: reference to scsi trace area
+ * @pay_lock: lock protecting payload trace buffer
+ * @rec_lock: lock protecting recovery trace buffer
+ * @hba_lock: lock protecting hba trace buffer
+ * @san_lock: lock protecting san trace buffer
+ * @scsi_lock: lock protecting scsi trace buffer
+ * @pay_buf: pre-allocated buffer for payload
+ * @rec_buf: pre-allocated buffer for recovery
+ * @hba_buf: pre-allocated buffer for hba
+ * @san_buf: pre-allocated buffer for san
+ * @scsi_buf: pre-allocated buffer for scsi
+ */
 struct zfcp_dbf {
+	debug_info_t			*pay;
 	debug_info_t			*rec;
 	debug_info_t			*hba;
 	debug_info_t			*san;
 	debug_info_t			*scsi;
+	spinlock_t			pay_lock;
 	spinlock_t			rec_lock;
 	spinlock_t			hba_lock;
 	spinlock_t			san_lock;
 	spinlock_t			scsi_lock;
-	struct zfcp_dbf_rec_record	rec_buf;
-	struct zfcp_dbf_hba_record	hba_buf;
-	struct zfcp_dbf_san_record	san_buf;
-	struct zfcp_dbf_scsi_record	scsi_buf;
-	struct zfcp_adapter		*adapter;
+	struct zfcp_dbf_pay		pay_buf;
+	struct zfcp_dbf_rec		rec_buf;
+	struct zfcp_dbf_hba		hba_buf;
+	struct zfcp_dbf_san		san_buf;
+	struct zfcp_dbf_scsi		scsi_buf;
 };
 
 static inline
-void zfcp_dbf_hba_fsf_resp(const char *tag2, int level,
-			   struct zfcp_fsf_req *req, struct zfcp_dbf *dbf)
+void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req)
 {
-	if (level <= dbf->hba->level)
-		_zfcp_dbf_hba_fsf_response(tag2, level, req, dbf);
+	if (level <= req->adapter->dbf->hba->level)
+		zfcp_dbf_hba_fsf_res(tag, req);
 }
 
 /**
  * zfcp_dbf_hba_fsf_response - trace event for request completion
- * @fsf_req: request that has been completed
+ * @req: request that has been completed
  */
-static inline void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req)
+static inline
+void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req)
 {
-	struct zfcp_dbf *dbf = req->adapter->dbf;
 	struct fsf_qtcb *qtcb = req->qtcb;
 
 	if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
 	    (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
-		zfcp_dbf_hba_fsf_resp("perr", 1, req, dbf);
+		zfcp_dbf_hba_fsf_resp("fs_perr", 1, req);
 
 	} else if (qtcb->header.fsf_status != FSF_GOOD) {
-		zfcp_dbf_hba_fsf_resp("ferr", 1, req, dbf);
+		zfcp_dbf_hba_fsf_resp("fs_ferr", 1, req);
 
 	} else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
 		   (req->fsf_command == FSF_QTCB_OPEN_LUN)) {
-		zfcp_dbf_hba_fsf_resp("open", 4, req, dbf);
+		zfcp_dbf_hba_fsf_resp("fs_open", 4, req);
 
 	} else if (qtcb->header.log_length) {
-		zfcp_dbf_hba_fsf_resp("qtcb", 5, req, dbf);
+		zfcp_dbf_hba_fsf_resp("fs_qtcb", 5, req);
 
 	} else {
-		zfcp_dbf_hba_fsf_resp("norm", 6, req, dbf);
+		zfcp_dbf_hba_fsf_resp("fs_norm", 6, req);
 	}
- }
-
-/**
- * zfcp_dbf_hba_fsf_unsol - trace event for an unsolicited status buffer
- * @tag: tag indicating which kind of unsolicited status has been received
- * @dbf: reference to dbf structure
- * @status_buffer: buffer containing payload of unsolicited status
- */
-static inline
-void zfcp_dbf_hba_fsf_unsol(const char *tag, struct zfcp_dbf *dbf,
-			    struct fsf_status_read_buffer *buf)
-{
-	int level = 2;
-
-	if (level <= dbf->hba->level)
-		_zfcp_dbf_hba_fsf_unsol(tag, level, dbf, buf);
 }
 
 static inline
-void zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
-		   struct zfcp_dbf *dbf, struct scsi_cmnd *scmd,
-		   struct zfcp_fsf_req *req, unsigned long old_id)
+void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd,
+		   struct zfcp_fsf_req *req)
 {
-	if (level <= dbf->scsi->level)
-		_zfcp_dbf_scsi(tag, tag2, level, dbf, scmd, req, old_id);
+	struct zfcp_adapter *adapter = (struct zfcp_adapter *)
+					scmd->device->host->hostdata[0];
+
+	if (level <= adapter->dbf->scsi->level)
+		zfcp_dbf_scsi(tag, scmd, req);
 }
 
 /**
  * zfcp_dbf_scsi_result - trace event for SCSI command completion
- * @dbf: adapter dbf trace
  * @scmd: SCSI command pointer
  * @req: FSF request used to issue SCSI command
  */
 static inline
-void zfcp_dbf_scsi_result(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd,
-			  struct zfcp_fsf_req *req)
+void zfcp_dbf_scsi_result(struct scsi_cmnd *scmd, struct zfcp_fsf_req *req)
 {
 	if (scmd->result != 0)
-		zfcp_dbf_scsi("rslt", "erro", 3, dbf, scmd, req, 0);
+		_zfcp_dbf_scsi("rsl_err", 3, scmd, req);
 	else if (scmd->retries > 0)
-		zfcp_dbf_scsi("rslt", "retr", 4, dbf, scmd, req, 0);
+		_zfcp_dbf_scsi("rsl_ret", 4, scmd, req);
 	else
-		zfcp_dbf_scsi("rslt", "norm", 6, dbf, scmd, req, 0);
+		_zfcp_dbf_scsi("rsl_nor", 6, scmd, req);
 }
 
 /**
  * zfcp_dbf_scsi_fail_send - trace event for failure to send SCSI command
- * @dbf: adapter dbf trace
  * @scmd: SCSI command pointer
  */
 static inline
-void zfcp_dbf_scsi_fail_send(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd)
+void zfcp_dbf_scsi_fail_send(struct scsi_cmnd *scmd)
 {
-	zfcp_dbf_scsi("rslt", "fail", 4, dbf, scmd, NULL, 0);
+	_zfcp_dbf_scsi("rsl_fai", 4, scmd, NULL);
 }
 
 /**
  * zfcp_dbf_scsi_abort - trace event for SCSI command abort
  * @tag: tag indicating success or failure of abort operation
- * @adapter: adapter thas has been used to issue SCSI command to be aborted
  * @scmd: SCSI command to be aborted
- * @new_req: request containing abort (might be NULL)
- * @old_id: identifier of request containg SCSI command to be aborted
+ * @fsf_req: request containing abort (might be NULL)
  */
 static inline
-void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf,
-			 struct scsi_cmnd *scmd, struct zfcp_fsf_req *new_req,
-			 unsigned long old_id)
+void zfcp_dbf_scsi_abort(char *tag, struct scsi_cmnd *scmd,
+			 struct zfcp_fsf_req *fsf_req)
 {
-	zfcp_dbf_scsi("abrt", tag, 1, dbf, scmd, new_req, old_id);
+	_zfcp_dbf_scsi(tag, 1, scmd, fsf_req);
 }
 
 /**
@@ -352,12 +366,17 @@
  * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
  */
 static inline
-void zfcp_dbf_scsi_devreset(const char *tag, struct scsi_cmnd *scmnd, u8 flag)
+void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag)
 {
-	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+	char tmp_tag[ZFCP_DBF_TAG_LEN];
 
-	zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1,
-		      zfcp_sdev->port->adapter->dbf, scmnd, NULL, 0);
+	if (flag == FCP_TMF_TGT_RESET)
+		memcpy(tmp_tag, "tr_", 3);
+	else
+		memcpy(tmp_tag, "lr_", 3);
+
+	memcpy(&tmp_tag[3], tag, 4);
+	_zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL);
 }
 
 #endif /* ZFCP_DBF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 0bcd580..e003e30 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -76,9 +76,9 @@
 	struct zfcp_adapter *adapter = act->adapter;
 
 	list_move(&act->list, &act->adapter->erp_ready_head);
-	zfcp_dbf_rec_action("erardy1", act);
+	zfcp_dbf_rec_run("erardy1", act);
 	wake_up(&adapter->erp_ready_wq);
-	zfcp_dbf_rec_thread("erardy2", adapter->dbf);
+	zfcp_dbf_rec_run("erardy2", act);
 }
 
 static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
@@ -236,10 +236,10 @@
 static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
 				   struct zfcp_port *port,
 				   struct scsi_device *sdev,
-				   char *id, void *ref, u32 act_status)
+				   char *id, u32 act_status)
 {
 	int retval = 1, need;
-	struct zfcp_erp_action *act = NULL;
+	struct zfcp_erp_action *act;
 
 	if (!adapter->erp_thread)
 		return -EIO;
@@ -255,15 +255,14 @@
 	++adapter->erp_total_count;
 	list_add_tail(&act->list, &adapter->erp_ready_head);
 	wake_up(&adapter->erp_ready_wq);
-	zfcp_dbf_rec_thread("eracte1", adapter->dbf);
 	retval = 0;
  out:
-	zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, sdev);
+	zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need);
 	return retval;
 }
 
 static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
-				    int clear_mask, char *id, void *ref)
+				    int clear_mask, char *id)
 {
 	zfcp_erp_adapter_block(adapter, clear_mask);
 	zfcp_scsi_schedule_rports_block(adapter);
@@ -275,7 +274,7 @@
 		return -EIO;
 	}
 	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
-				       adapter, NULL, NULL, id, ref, 0);
+				       adapter, NULL, NULL, id, 0);
 }
 
 /**
@@ -283,10 +282,8 @@
  * @adapter: Adapter to reopen.
  * @clear: Status flags to clear.
  * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
  */
-void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
-			     char *id, void *ref)
+void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id)
 {
 	unsigned long flags;
 
@@ -299,7 +296,7 @@
 					    ZFCP_STATUS_COMMON_ERP_FAILED);
 	else
 		zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
-					NULL, NULL, id, ref, 0);
+					NULL, NULL, id, 0);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
@@ -308,13 +305,12 @@
  * @adapter: Adapter to shut down.
  * @clear: Status flags to clear.
  * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
  */
 void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear,
-			       char *id, void *ref)
+			       char *id)
 {
 	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
-	zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref);
+	zfcp_erp_adapter_reopen(adapter, clear | flags, id);
 }
 
 /**
@@ -322,13 +318,11 @@
  * @port: Port to shut down.
  * @clear: Status flags to clear.
  * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
  */
-void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id,
-			    void *ref)
+void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id)
 {
 	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
-	zfcp_erp_port_reopen(port, clear | flags, id, ref);
+	zfcp_erp_port_reopen(port, clear | flags, id);
 }
 
 static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
@@ -337,8 +331,8 @@
 				    ZFCP_STATUS_COMMON_UNBLOCKED | clear);
 }
 
-static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
-					 int clear, char *id, void *ref)
+static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear,
+					 char *id)
 {
 	zfcp_erp_port_block(port, clear);
 	zfcp_scsi_schedule_rport_block(port);
@@ -347,28 +341,26 @@
 		return;
 
 	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
-				port->adapter, port, NULL, id, ref, 0);
+				port->adapter, port, NULL, id, 0);
 }
 
 /**
  * zfcp_erp_port_forced_reopen - Forced close of port and open again
  * @port: Port to force close and to reopen.
+ * @clear: Status flags to clear.
  * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
  */
-void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id,
-				 void *ref)
+void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id)
 {
 	unsigned long flags;
 	struct zfcp_adapter *adapter = port->adapter;
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
-	_zfcp_erp_port_forced_reopen(port, clear, id, ref);
+	_zfcp_erp_port_forced_reopen(port, clear, id);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
-static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
-				 void *ref)
+static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
 {
 	zfcp_erp_port_block(port, clear);
 	zfcp_scsi_schedule_rport_block(port);
@@ -380,24 +372,25 @@
 	}
 
 	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
-				       port->adapter, port, NULL, id, ref, 0);
+				       port->adapter, port, NULL, id, 0);
 }
 
 /**
  * zfcp_erp_port_reopen - trigger remote port recovery
  * @port: port to recover
  * @clear_mask: flags in port status to be cleared
+ * @id: Id for debug trace event.
  *
  * Returns 0 if recovery has been triggered, < 0 if not.
  */
-int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref)
+int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
 {
 	int retval;
 	unsigned long flags;
 	struct zfcp_adapter *adapter = port->adapter;
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
-	retval = _zfcp_erp_port_reopen(port, clear, id, ref);
+	retval = _zfcp_erp_port_reopen(port, clear, id);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 
 	return retval;
@@ -410,7 +403,7 @@
 }
 
 static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
-				 void *ref, u32 act_status)
+				 u32 act_status)
 {
 	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
@@ -421,17 +414,18 @@
 		return;
 
 	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
-				zfcp_sdev->port, sdev, id, ref, act_status);
+				zfcp_sdev->port, sdev, id, act_status);
 }
 
 /**
  * zfcp_erp_lun_reopen - initiate reopen of a LUN
  * @sdev: SCSI device / LUN to be reopened
  * @clear_mask: specifies flags in LUN status to be cleared
+ * @id: Id for debug trace event.
+ *
  * Return: 0 on success, < 0 on error
  */
-void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
-			 void *ref)
+void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id)
 {
 	unsigned long flags;
 	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
@@ -439,7 +433,7 @@
 	struct zfcp_adapter *adapter = port->adapter;
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
-	_zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
+	_zfcp_erp_lun_reopen(sdev, clear, id, 0);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
@@ -448,13 +442,11 @@
  * @sdev: SCSI device / LUN to shut down.
  * @clear: Status flags to clear.
  * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
  */
-void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id,
-			   void *ref)
+void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id)
 {
 	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
-	zfcp_erp_lun_reopen(sdev, clear | flags, id, ref);
+	zfcp_erp_lun_reopen(sdev, clear | flags, id);
 }
 
 /**
@@ -476,7 +468,7 @@
 	int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
-	_zfcp_erp_lun_reopen(sdev, clear, id, NULL, ZFCP_STATUS_ERP_NO_REF);
+	_zfcp_erp_lun_reopen(sdev, clear, id, ZFCP_STATUS_ERP_NO_REF);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 
 	zfcp_erp_wait(adapter);
@@ -490,14 +482,14 @@
 static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 {
 	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
-		zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf);
+		zfcp_dbf_rec_run("eraubl1", &adapter->erp_action);
 	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
 }
 
 static void zfcp_erp_port_unblock(struct zfcp_port *port)
 {
 	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
-		zfcp_dbf_rec_port("erpubl1", NULL, port);
+		zfcp_dbf_rec_run("erpubl1", &port->erp_action);
 	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
 }
 
@@ -506,14 +498,14 @@
 	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 
 	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
-		zfcp_dbf_rec_lun("erlubl1", NULL, sdev);
+		zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action);
 	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
 }
 
 static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
 {
 	list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
-	zfcp_dbf_rec_action("erator1", erp_action);
+	zfcp_dbf_rec_run("erator1", erp_action);
 }
 
 static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
@@ -530,11 +522,11 @@
 		if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
 				   ZFCP_STATUS_ERP_TIMEDOUT)) {
 			req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
-			zfcp_dbf_rec_action("erscf_1", act);
+			zfcp_dbf_rec_run("erscf_1", act);
 			req->erp_action = NULL;
 		}
 		if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
-			zfcp_dbf_rec_action("erscf_2", act);
+			zfcp_dbf_rec_run("erscf_2", act);
 		if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
 			act->fsf_req_id = 0;
 	} else
@@ -585,40 +577,40 @@
 }
 
 static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
-				      int clear, char *id, void *ref)
+				      int clear, char *id)
 {
 	struct zfcp_port *port;
 
 	read_lock(&adapter->port_list_lock);
 	list_for_each_entry(port, &adapter->port_list, list)
-		_zfcp_erp_port_reopen(port, clear, id, ref);
+		_zfcp_erp_port_reopen(port, clear, id);
 	read_unlock(&adapter->port_list_lock);
 }
 
 static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
-				     char *id, void *ref)
+				     char *id)
 {
 	struct scsi_device *sdev;
 
 	shost_for_each_device(sdev, port->adapter->scsi_host)
 		if (sdev_to_zfcp(sdev)->port == port)
-			_zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
+			_zfcp_erp_lun_reopen(sdev, clear, id, 0);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
 {
 	switch (act->action) {
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
-		_zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL);
+		_zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1");
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
-		_zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL);
+		_zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2");
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
-		_zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
+		_zfcp_erp_port_reopen(act->port, 0, "ersff_3");
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_LUN:
-		_zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", NULL, 0);
+		_zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", 0);
 		break;
 	}
 }
@@ -627,13 +619,13 @@
 {
 	switch (act->action) {
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
-		_zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL);
+		_zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1");
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
-		_zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
+		_zfcp_erp_port_reopen(act->port, 0, "ersfs_2");
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
-		_zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3", NULL);
+		_zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3");
 		break;
 	}
 }
@@ -652,17 +644,6 @@
 	read_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
-static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
-{
-	struct zfcp_qdio *qdio = act->adapter->qdio;
-
-	if (zfcp_qdio_open(qdio))
-		return ZFCP_ERP_FAILED;
-	init_waitqueue_head(&qdio->req_q_wq);
-	atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status);
-	return ZFCP_ERP_SUCCEEDED;
-}
-
 static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter)
 {
 	struct zfcp_port *port;
@@ -670,7 +651,7 @@
 				 adapter->peer_d_id);
 	if (IS_ERR(port)) /* error or port already attached */
 		return;
-	_zfcp_erp_port_reopen(port, 0, "ereptp1", NULL);
+	_zfcp_erp_port_reopen(port, 0, "ereptp1");
 }
 
 static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
@@ -693,10 +674,8 @@
 			return ZFCP_ERP_FAILED;
 		}
 
-		zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf);
 		wait_event(adapter->erp_ready_wq,
 			   !list_empty(&adapter->erp_ready_head));
-		zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf);
 		if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
 			break;
 
@@ -735,10 +714,10 @@
 	if (ret)
 		return ZFCP_ERP_FAILED;
 
-	zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf);
+	zfcp_dbf_rec_run("erasox1", act);
 	wait_event(adapter->erp_ready_wq,
 		   !list_empty(&adapter->erp_ready_head));
-	zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf);
+	zfcp_dbf_rec_run("erasox2", act);
 	if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
 		return ZFCP_ERP_FAILED;
 
@@ -788,7 +767,7 @@
 {
 	struct zfcp_adapter *adapter = act->adapter;
 
-	if (zfcp_erp_adapter_strategy_open_qdio(act)) {
+	if (zfcp_qdio_open(adapter->qdio)) {
 		atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
 				  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
 				  &adapter->status);
@@ -1166,7 +1145,7 @@
 		if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) {
 			_zfcp_erp_adapter_reopen(adapter,
 						 ZFCP_STATUS_COMMON_ERP_FAILED,
-						 "ersscg1", NULL);
+						 "ersscg1");
 			return ZFCP_ERP_EXIT;
 		}
 		break;
@@ -1176,7 +1155,7 @@
 		if (zfcp_erp_strat_change_det(&port->status, erp_status)) {
 			_zfcp_erp_port_reopen(port,
 					      ZFCP_STATUS_COMMON_ERP_FAILED,
-					      "ersscg2", NULL);
+					      "ersscg2");
 			return ZFCP_ERP_EXIT;
 		}
 		break;
@@ -1186,7 +1165,7 @@
 		if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) {
 			_zfcp_erp_lun_reopen(sdev,
 					     ZFCP_STATUS_COMMON_ERP_FAILED,
-					     "ersscg3", NULL, 0);
+					     "ersscg3", 0);
 			return ZFCP_ERP_EXIT;
 		}
 		break;
@@ -1206,7 +1185,7 @@
 	}
 
 	list_del(&erp_action->list);
-	zfcp_dbf_rec_action("eractd1", erp_action);
+	zfcp_dbf_rec_run("eractd1", erp_action);
 
 	switch (erp_action->action) {
 	case ZFCP_ERP_ACTION_REOPEN_LUN:
@@ -1313,7 +1292,7 @@
 			erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;
 		}
 		if (adapter->erp_total_count == adapter->erp_low_mem_count)
-			_zfcp_erp_adapter_reopen(adapter, 0, "erstgy1", NULL);
+			_zfcp_erp_adapter_reopen(adapter, 0, "erstgy1");
 		else {
 			zfcp_erp_strategy_memwait(erp_action);
 			retval = ZFCP_ERP_CONTINUES;
@@ -1357,11 +1336,9 @@
 	unsigned long flags;
 
 	for (;;) {
-		zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf);
 		wait_event_interruptible(adapter->erp_ready_wq,
 			   !list_empty(&adapter->erp_ready_head) ||
 			   kthread_should_stop());
-		zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf);
 
 		if (kthread_should_stop())
 			break;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index bf8f3e5..6e32528 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -45,47 +45,33 @@
 
 /* zfcp_dbf.c */
 extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
-extern void zfcp_dbf_adapter_unregister(struct zfcp_dbf *);
-extern void zfcp_dbf_rec_thread(char *, struct zfcp_dbf *);
-extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *);
-extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *);
-extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *);
-extern void zfcp_dbf_rec_lun(char *, void *, struct scsi_device *);
-extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *,
-				 struct zfcp_adapter *, struct zfcp_port *,
-				 struct scsi_device *);
-extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *);
-extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *,
-				       struct zfcp_dbf *);
-extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *,
-					  struct fsf_status_read_buffer *);
-extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int);
+extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *);
+extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
+			      struct zfcp_port *, struct scsi_device *, u8, u8);
+extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
+extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
-extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *, u32);
-extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *);
-extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *);
-extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *);
-extern void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *);
-extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *,
-			   struct scsi_cmnd *, struct zfcp_fsf_req *,
-			   unsigned long);
+extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
+extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_scsi(char *, struct scsi_cmnd *, struct zfcp_fsf_req *);
 
 /* zfcp_erp.c */
 extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
 extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32);
-extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *);
-extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *,
-				      void *);
+extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *);
+extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *);
 extern void zfcp_erp_set_port_status(struct zfcp_port *, u32);
 extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32);
-extern int  zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *);
-extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *);
-extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *,
-					void *);
+extern int  zfcp_erp_port_reopen(struct zfcp_port *, int, char *);
+extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *);
+extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *);
 extern void zfcp_erp_set_lun_status(struct scsi_device *, u32);
 extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32);
-extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *, void *);
-extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *, void *);
+extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *);
+extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *);
 extern void zfcp_erp_lun_shutdown_wait(struct scsi_device *, char *);
 extern int  zfcp_erp_thread_setup(struct zfcp_adapter *);
 extern void zfcp_erp_thread_kill(struct zfcp_adapter *);
@@ -149,6 +135,8 @@
 extern int zfcp_qdio_open(struct zfcp_qdio *);
 extern void zfcp_qdio_close(struct zfcp_qdio *);
 extern void zfcp_qdio_siosl(struct zfcp_adapter *);
+extern struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *,
+					     struct qdio_buffer *);
 
 /* zfcp_scsi.c */
 extern struct zfcp_data zfcp_data;
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 86fd905..30cf91a 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -174,7 +174,7 @@
 		if (!port->d_id)
 			zfcp_erp_port_reopen(port,
 					     ZFCP_STATUS_COMMON_ERP_FAILED,
-					     "fcrscn1", NULL);
+					     "fcrscn1");
 	}
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
@@ -215,7 +215,7 @@
 	read_lock_irqsave(&adapter->port_list_lock, flags);
 	list_for_each_entry(port, &adapter->port_list, list)
 		if (port->wwpn == wwpn) {
-			zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req);
+			zfcp_erp_port_forced_reopen(port, 0, "fciwwp1");
 			break;
 		}
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
@@ -251,7 +251,7 @@
 		(struct fsf_status_read_buffer *) fsf_req->data;
 	unsigned int els_type = status_buffer->payload.data[0];
 
-	zfcp_dbf_san_incoming_els(fsf_req);
+	zfcp_dbf_san_in_els("fciels1", fsf_req);
 	if (els_type == ELS_PLOGI)
 		zfcp_fc_incoming_plogi(fsf_req);
 	else if (els_type == ELS_LOGO)
@@ -360,7 +360,7 @@
 	ret = zfcp_fc_ns_gid_pn(port);
 	if (ret) {
 		/* could not issue gid_pn for some reason */
-		zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1", NULL);
+		zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1");
 		goto out;
 	}
 
@@ -369,7 +369,7 @@
 		goto out;
 	}
 
-	zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL);
+	zfcp_erp_port_reopen(port, 0, "fcgpn_3");
 out:
 	put_device(&port->dev);
 }
@@ -426,7 +426,7 @@
 	if (adisc->els.status) {
 		/* request rejected or timed out */
 		zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
-					    "fcadh_1", NULL);
+					    "fcadh_1");
 		goto out;
 	}
 
@@ -436,7 +436,7 @@
 	if ((port->wwpn != adisc_resp->adisc_wwpn) ||
 	    !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) {
 		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
-				     "fcadh_2", NULL);
+				     "fcadh_2");
 		goto out;
 	}
 
@@ -507,7 +507,7 @@
 
 	/* send of ADISC was not possible */
 	atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
-	zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL);
+	zfcp_erp_port_forced_reopen(port, 0, "fcltwk1");
 
 out:
 	put_device(&port->dev);
@@ -659,7 +659,7 @@
 		port = zfcp_port_enqueue(adapter, acc->fp_wwpn,
 					 ZFCP_STATUS_COMMON_NOESC, d_id);
 		if (!IS_ERR(port))
-			zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL);
+			zfcp_erp_port_reopen(port, 0, "fcegpf1");
 		else if (PTR_ERR(port) != -EEXIST)
 			ret = PTR_ERR(port);
 	}
@@ -671,7 +671,7 @@
 	write_unlock_irqrestore(&adapter->port_list_lock, flags);
 
 	list_for_each_entry_safe(port, tmp, &remove_lh, list) {
-		zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL);
+		zfcp_erp_port_shutdown(port, 0, "fcegpf2");
 		zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs);
 	}
 
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 2eb7dd5..60ff9d1 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -23,7 +23,7 @@
 	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
 	zfcp_qdio_siosl(adapter);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
-				"fsrth_1", NULL);
+				"fsrth_1");
 }
 
 static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req,
@@ -65,7 +65,7 @@
 {
 	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
 		"operational because of an unsupported FC class\n");
-	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req);
+	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1");
 	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 }
 
@@ -98,7 +98,7 @@
 	read_lock_irqsave(&adapter->port_list_lock, flags);
 	list_for_each_entry(port, &adapter->port_list, list)
 		if (port->d_id == d_id) {
-			zfcp_erp_port_reopen(port, 0, "fssrpc1", req);
+			zfcp_erp_port_reopen(port, 0, "fssrpc1");
 			break;
 		}
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
@@ -211,13 +211,13 @@
 	struct fsf_status_read_buffer *sr_buf = req->data;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
-		zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf);
+		zfcp_dbf_hba_fsf_uss("fssrh_1", req);
 		mempool_free(sr_buf, adapter->pool.status_read_data);
 		zfcp_fsf_req_free(req);
 		return;
 	}
 
-	zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf);
+	zfcp_dbf_hba_fsf_uss("fssrh_2", req);
 
 	switch (sr_buf->status_type) {
 	case FSF_STATUS_READ_PORT_CLOSED:
@@ -232,7 +232,7 @@
 		dev_warn(&adapter->ccw_device->dev,
 			 "The error threshold for checksum statistics "
 			 "has been exceeded\n");
-		zfcp_dbf_hba_berr(adapter->dbf, req);
+		zfcp_dbf_hba_bit_err("fssrh_3", req);
 		break;
 	case FSF_STATUS_READ_LINK_DOWN:
 		zfcp_fsf_status_read_link_down(req);
@@ -247,7 +247,7 @@
 		zfcp_erp_adapter_reopen(adapter,
 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
 					ZFCP_STATUS_COMMON_ERP_FAILED,
-					"fssrh_2", req);
+					"fssrh_2");
 		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0);
 
 		break;
@@ -287,7 +287,7 @@
 			"The FCP adapter reported a problem "
 			"that cannot be recovered\n");
 		zfcp_qdio_siosl(req->adapter);
-		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req);
+		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1");
 		break;
 	}
 	/* all non-return stats set FSFREQ_ERROR*/
@@ -304,7 +304,7 @@
 		dev_err(&req->adapter->ccw_device->dev,
 			"The FCP adapter does not recognize the command 0x%x\n",
 			req->qtcb->header.fsf_command);
-		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req);
+		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -335,17 +335,17 @@
 			"QTCB version 0x%x not supported by FCP adapter "
 			"(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION,
 			psq->word[0], psq->word[1]);
-		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1");
 		break;
 	case FSF_PROT_ERROR_STATE:
 	case FSF_PROT_SEQ_NUMB_ERROR:
-		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req);
+		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PROT_UNSUPP_QTCB_TYPE:
 		dev_err(&adapter->ccw_device->dev,
 			"The QTCB type is not supported by the FCP adapter\n");
-		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3");
 		break;
 	case FSF_PROT_HOST_CONNECTION_INITIALIZING:
 		atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
@@ -355,12 +355,12 @@
 		dev_err(&adapter->ccw_device->dev,
 			"0x%Lx is an ambiguous request identifier\n",
 			(unsigned long long)qtcb->bottom.support.req_handle);
-		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4");
 		break;
 	case FSF_PROT_LINK_DOWN:
 		zfcp_fsf_link_down_info_eval(req, &psq->link_down_info);
 		/* go through reopen to flush pending requests */
-		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
+		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6");
 		break;
 	case FSF_PROT_REEST_QUEUE:
 		/* All ports should be marked as ready to run again */
@@ -369,14 +369,14 @@
 		zfcp_erp_adapter_reopen(adapter,
 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
 					ZFCP_STATUS_COMMON_ERP_FAILED,
-					"fspse_8", req);
+					"fspse_8");
 		break;
 	default:
 		dev_err(&adapter->ccw_device->dev,
 			"0x%x is not a valid transfer protocol status\n",
 			qtcb->prefix.prot_status);
 		zfcp_qdio_siosl(adapter);
-		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9");
 	}
 	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 }
@@ -482,7 +482,7 @@
 		dev_err(&adapter->ccw_device->dev,
 			"Unknown or unsupported arbitrated loop "
 			"fibre channel topology detected\n");
-		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1");
 		return -EIO;
 	}
 
@@ -518,7 +518,7 @@
 				"FCP adapter maximum QTCB size (%d bytes) "
 				"is too small\n",
 				bottom->max_qtcb_size);
-			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req);
+			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1");
 			return;
 		}
 		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
@@ -536,7 +536,7 @@
 			&qtcb->header.fsf_status_qual.link_down_info);
 		break;
 	default:
-		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3");
 		return;
 	}
 
@@ -552,14 +552,14 @@
 		dev_err(&adapter->ccw_device->dev,
 			"The FCP adapter only supports newer "
 			"control block versions\n");
-		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4");
 		return;
 	}
 	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
 		dev_err(&adapter->ccw_device->dev,
 			"The FCP adapter only supports older "
 			"control block versions\n");
-		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req);
+		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5");
 	}
 }
 
@@ -700,7 +700,7 @@
 		del_timer(&req->timer);
 		/* lookup request again, list might have changed */
 		zfcp_reqlist_find_rm(adapter->req_list, req_id);
-		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
+		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1");
 		return -EIO;
 	}
 
@@ -754,10 +754,11 @@
 	goto out;
 
 failed_req_send:
+	req->data = NULL;
 	mempool_free(sr_buf, adapter->pool.status_read_data);
 failed_buf:
+	zfcp_dbf_hba_fsf_uss("fssr__1", req);
 	zfcp_fsf_req_free(req);
-	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
 out:
 	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
@@ -776,14 +777,13 @@
 	case FSF_PORT_HANDLE_NOT_VALID:
 		if (fsq->word[0] == fsq->word[1]) {
 			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
-						"fsafch1", req);
+						"fsafch1");
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		}
 		break;
 	case FSF_LUN_HANDLE_NOT_VALID:
 		if (fsq->word[0] == fsq->word[1]) {
-			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2",
-					     req);
+			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2");
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		}
 		break;
@@ -794,14 +794,13 @@
 		zfcp_erp_set_port_status(zfcp_sdev->port,
 					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
 		zfcp_erp_port_reopen(zfcp_sdev->port,
-				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3",
-				     req);
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_BOXED:
 		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
 		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
-				    "fsafch4", req);
+				    "fsafch4");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                 break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -882,7 +881,7 @@
 
 	switch (header->fsf_status) {
         case FSF_GOOD:
-		zfcp_dbf_san_ct_response(req);
+		zfcp_dbf_san_res("fsscth1", req);
 		ct->status = 0;
 		break;
         case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -902,7 +901,7 @@
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req);
+		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1");
 		/* fall through */
 	case FSF_GENERIC_COMMAND_REJECTED:
 	case FSF_PAYLOAD_SIZE_MISMATCH:
@@ -1025,7 +1024,7 @@
 	req->qtcb->header.port_handle = wka_port->handle;
 	req->data = ct;
 
-	zfcp_dbf_san_ct_request(req, wka_port->d_id);
+	zfcp_dbf_san_req("fssct_1", req, wka_port->d_id);
 
 	ret = zfcp_fsf_req_send(req);
 	if (ret)
@@ -1053,7 +1052,7 @@
 
 	switch (header->fsf_status) {
 	case FSF_GOOD:
-		zfcp_dbf_san_els_response(req);
+		zfcp_dbf_san_res("fsselh1", req);
 		send_els->status = 0;
 		break;
 	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1127,7 +1126,7 @@
 	req->handler = zfcp_fsf_send_els_handler;
 	req->data = els;
 
-	zfcp_dbf_san_els_request(req);
+	zfcp_dbf_san_req("fssels1", req, d_id);
 
 	ret = zfcp_fsf_req_send(req);
 	if (ret)
@@ -1448,7 +1447,7 @@
 
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req);
+		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1580,7 +1579,7 @@
 
 	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req);
+		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1");
 	}
 
 	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
@@ -1638,7 +1637,7 @@
 
 	switch (header->fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req);
+		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ACCESS_DENIED:
@@ -1654,7 +1653,7 @@
 						  &sdev_to_zfcp(sdev)->status);
 		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
 		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
-				     "fscpph2", req);
+				     "fscpph2");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1743,7 +1742,7 @@
 	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1", req);
+		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
 		/* fall through */
 	case FSF_LUN_ALREADY_OPEN:
 		break;
@@ -1755,8 +1754,7 @@
 		zfcp_erp_set_port_status(zfcp_sdev->port,
 					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
 		zfcp_erp_port_reopen(zfcp_sdev->port,
-				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2",
-				     req);
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_SHARING_VIOLATION:
@@ -1852,20 +1850,18 @@
 
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1",
-					req);
+		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_HANDLE_NOT_VALID:
-		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2", req);
+		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_BOXED:
 		zfcp_erp_set_port_status(zfcp_sdev->port,
 					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
 		zfcp_erp_port_reopen(zfcp_sdev->port,
-				     ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3",
-				     req);
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -2002,13 +1998,12 @@
 	switch (header->fsf_status) {
 	case FSF_HANDLE_MISMATCH:
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1",
-					req);
+		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_FCPLUN_NOT_VALID:
 	case FSF_LUN_HANDLE_NOT_VALID:
-		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req);
+		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -2026,7 +2021,7 @@
 			(unsigned long long)zfcp_scsi_dev_lun(sdev),
 			(unsigned long long)zfcp_sdev->port->wwpn);
 		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
-					  "fssfch3", req);
+					  "fssfch3");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_CMND_LENGTH_NOT_VALID:
@@ -2037,21 +2032,20 @@
 			(unsigned long long)zfcp_scsi_dev_lun(sdev),
 			(unsigned long long)zfcp_sdev->port->wwpn);
 		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
-					  "fssfch4", req);
+					  "fssfch4");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_BOXED:
 		zfcp_erp_set_port_status(zfcp_sdev->port,
 					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
 		zfcp_erp_port_reopen(zfcp_sdev->port,
-				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5",
-				     req);
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_BOXED:
 		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
 		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
-				    "fssfch6", req);
+				    "fssfch6");
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -2104,7 +2098,7 @@
 
 skip_fsfstatus:
 	zfcp_fsf_req_trace(req, scpnt);
-	zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req);
+	zfcp_dbf_scsi_result(scpnt, req);
 
 	scpnt->host_scribble = NULL;
 	(scpnt->scsi_done) (scpnt);
@@ -2420,3 +2414,12 @@
 			break;
 	}
 }
+
+struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *qdio,
+				      struct qdio_buffer *sbal)
+{
+	struct qdio_buffer_element *sbale = &sbal->element[0];
+	u64 req_id = (unsigned long) sbale->addr;
+
+	return zfcp_reqlist_find(qdio->adapter->req_list, req_id);
+}
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index a0554be..8da5ed6 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -41,7 +41,7 @@
 		zfcp_qdio_siosl(adapter);
 	zfcp_erp_adapter_reopen(adapter,
 				ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
-				ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL);
+				ZFCP_STATUS_COMMON_ERP_FAILED, id);
 }
 
 static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
@@ -74,7 +74,6 @@
 	struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
 
 	if (unlikely(qdio_err)) {
-		zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count);
 		zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err);
 		return;
 	}
@@ -97,7 +96,6 @@
 	int sbal_idx, sbal_no;
 
 	if (unlikely(qdio_err)) {
-		zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count);
 		zfcp_qdio_handler_error(qdio, "qdires1", qdio_err);
 		return;
 	}
@@ -116,7 +114,7 @@
 	 * put SBALs back to response queue
 	 */
 	if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count))
-		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2", NULL);
+		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2");
 }
 
 static struct qdio_buffer_element *
@@ -236,7 +234,7 @@
 	if (!ret) {
 		atomic_inc(&qdio->req_q_full);
 		/* assume hanging outbound queue, try queue recovery */
-		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
+		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
 	}
 
 	spin_lock_irq(&qdio->req_q_lock);
@@ -292,6 +290,8 @@
 	id->int_parm = (unsigned long) qdio;
 	id->input_sbal_addr_array = (void **) (qdio->res_q);
 	id->output_sbal_addr_array = (void **) (qdio->req_q);
+	id->scan_threshold =
+		QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
 }
 
 /**
@@ -309,6 +309,7 @@
 		return -ENOMEM;
 
 	zfcp_qdio_setup_init_data(&init_data, qdio);
+	init_waitqueue_head(&qdio->req_q_wq);
 
 	return qdio_allocate(&init_data);
 }
@@ -393,6 +394,7 @@
 	/* set index of first avalable SBALS / number of available SBALS */
 	qdio->req_q_idx = 0;
 	atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
+	atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
 
 	return 0;
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 63529ed..ddb5800 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -30,6 +30,10 @@
 MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support");
 #endif
 
+static bool allow_lun_scan = 1;
+module_param(allow_lun_scan, bool, 0600);
+MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs");
+
 static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
 					int reason)
 {
@@ -68,11 +72,8 @@
 
 static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
 {
-	struct zfcp_adapter *adapter =
-		(struct zfcp_adapter *) scpnt->device->host->hostdata[0];
-
 	set_host_byte(scpnt, result);
-	zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt);
+	zfcp_dbf_scsi_fail_send(scpnt);
 	scpnt->scsi_done(scpnt);
 }
 
@@ -80,7 +81,6 @@
 int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
 {
 	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
-	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
 	int    status, scsi_result, ret;
 
@@ -91,7 +91,7 @@
 	scsi_result = fc_remote_port_chkready(rport);
 	if (unlikely(scsi_result)) {
 		scpnt->result = scsi_result;
-		zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt);
+		zfcp_dbf_scsi_fail_send(scpnt);
 		scpnt->scsi_done(scpnt);
 		return 0;
 	}
@@ -134,6 +134,7 @@
 	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	struct zfcp_port *port;
 	struct zfcp_unit *unit;
+	int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE;
 
 	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
 	if (!port)
@@ -143,7 +144,7 @@
 	if (unit)
 		put_device(&unit->dev);
 
-	if (!unit && !(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
+	if (!unit && !(allow_lun_scan && npiv)) {
 		put_device(&port->dev);
 		return -ENXIO;
 	}
@@ -158,7 +159,7 @@
 	spin_lock_init(&zfcp_sdev->latencies.lock);
 
 	zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
-	zfcp_erp_lun_reopen(sdev, 0, "scsla_1", NULL);
+	zfcp_erp_lun_reopen(sdev, 0, "scsla_1");
 	zfcp_erp_wait(port->adapter);
 
 	return 0;
@@ -182,8 +183,7 @@
 	old_req = zfcp_reqlist_find(adapter->req_list, old_reqid);
 	if (!old_req) {
 		write_unlock_irqrestore(&adapter->abort_lock, flags);
-		zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL,
-				    old_reqid);
+		zfcp_dbf_scsi_abort("abrt_or", scpnt, NULL);
 		return FAILED; /* completion could be in progress */
 	}
 	old_req->data = NULL;
@@ -198,29 +198,32 @@
 
 		zfcp_erp_wait(adapter);
 		ret = fc_block_scsi_eh(scpnt);
-		if (ret)
+		if (ret) {
+			zfcp_dbf_scsi_abort("abrt_bl", scpnt, NULL);
 			return ret;
+		}
 		if (!(atomic_read(&adapter->status) &
 		      ZFCP_STATUS_COMMON_RUNNING)) {
-			zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL,
-					    old_reqid);
+			zfcp_dbf_scsi_abort("abrt_ru", scpnt, NULL);
 			return SUCCESS;
 		}
 	}
-	if (!abrt_req)
+	if (!abrt_req) {
+		zfcp_dbf_scsi_abort("abrt_ar", scpnt, NULL);
 		return FAILED;
+	}
 
 	wait_for_completion(&abrt_req->completion);
 
 	if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
-		dbf_tag = "okay";
+		dbf_tag = "abrt_ok";
 	else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
-		dbf_tag = "lte2";
+		dbf_tag = "abrt_nn";
 	else {
-		dbf_tag = "fail";
+		dbf_tag = "abrt_fa";
 		retval = FAILED;
 	}
-	zfcp_dbf_scsi_abort(dbf_tag, adapter->dbf, scpnt, abrt_req, old_reqid);
+	zfcp_dbf_scsi_abort(dbf_tag, scpnt, abrt_req);
 	zfcp_fsf_req_free(abrt_req);
 	return retval;
 }
@@ -280,7 +283,7 @@
 	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	int ret;
 
-	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
+	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1");
 	zfcp_erp_wait(adapter);
 	ret = fc_block_scsi_eh(scpnt);
 	if (ret)
@@ -518,7 +521,7 @@
 	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
 
 	if (port) {
-		zfcp_erp_port_forced_reopen(port, 0, "sctrpi1", NULL);
+		zfcp_erp_port_forced_reopen(port, 0, "sctrpi1");
 		put_device(&port->dev);
 	}
 }
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 2f2c54f..cdc4ff7 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -105,8 +105,7 @@
 		return -EINVAL;
 
 	zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING);
-	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2",
-			     NULL);
+	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2");
 	zfcp_erp_wait(port->adapter);
 
 	return count;
@@ -148,7 +147,7 @@
 	if (sdev) {
 		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
-				    "syufai2", NULL);
+				    "syufai2");
 		zfcp_erp_wait(unit->port->adapter);
 	} else
 		zfcp_unit_scsi_scan(unit);
@@ -198,7 +197,7 @@
 
 	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
-				"syafai2", NULL);
+				"syafai2");
 	zfcp_erp_wait(adapter);
 out:
 	zfcp_ccw_adapter_put(adapter);
@@ -256,7 +255,7 @@
 
 	put_device(&port->dev);
 
-	zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL);
+	zfcp_erp_port_shutdown(port, 0, "syprs_1");
 	zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs);
  out:
 	zfcp_ccw_adapter_put(adapter);
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 17e3df4..1cadcd6 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -1171,9 +1171,8 @@
 	arcmsr_cdb->msgPages = arccdbsize/0x100 + (arccdbsize % 0x100 ? 1 : 0);
 	if ( arccdbsize > 256)
 		arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
-	if (pcmd->cmnd[0]|WRITE_6 || pcmd->cmnd[0]|WRITE_10 || pcmd->cmnd[0]|WRITE_12 ){
+	if (pcmd->sc_data_direction == DMA_TO_DEVICE)
 		arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
-	}
 	ccb->arc_cdb_size = arccdbsize;
 	return SUCCESS;
 }
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 75a85aa..79cefbe 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -3785,7 +3785,7 @@
 	dma_addr_t paddr;
 
 	io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool,
-					  GFP_KERNEL, &paddr);
+					  GFP_ATOMIC, &paddr);
 	if (!io_task->cmd_bhs)
 		return -ENOMEM;
 	io_task->bhs_pa.u.a64.address = paddr;
@@ -3914,7 +3914,8 @@
 			io_task->psgl_handle = NULL;
 		}
 	} else {
-		if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)
+		if (task->hdr &&
+		   ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN))
 			return;
 		if (io_task->psgl_handle) {
 			spin_lock(&phba->mgmt_sgl_lock);
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
index d2eefd3..4ce6f49 100644
--- a/drivers/scsi/bfa/Makefile
+++ b/drivers/scsi/bfa/Makefile
@@ -3,6 +3,4 @@
 bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
 bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
 bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
-bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o
-
-ccflags-y := -DBFA_PERF_BUILD
+bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
index ff2bd07..7be6b5a 100644
--- a/drivers/scsi/bfa/bfa.h
+++ b/drivers/scsi/bfa/bfa.h
@@ -17,7 +17,7 @@
 #ifndef __BFA_H__
 #define __BFA_H__
 
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 #include "bfa_cs.h"
 #include "bfa_plog.h"
 #include "bfa_defs_svc.h"
@@ -33,7 +33,6 @@
  * Interrupt message handlers
  */
 void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
 
 /*
  * Request and response queue related defines
@@ -121,8 +120,8 @@
 									\
 		struct list_head *waitq = bfa_reqq(__bfa, __reqq);      \
 									\
-		bfa_assert(((__reqq) < BFI_IOC_MAX_CQS));      \
-		bfa_assert((__wqe)->qresume && (__wqe)->cbarg);      \
+		WARN_ON(((__reqq) >= BFI_IOC_MAX_CQS));			\
+		WARN_ON(!((__wqe)->qresume && (__wqe)->cbarg));		\
 									\
 		list_add_tail(&(__wqe)->qe, waitq);      \
 	} while (0)
@@ -297,7 +296,6 @@
 		      struct bfa_iocfc_cfg_s *cfg,
 		      struct bfa_meminfo_s *meminfo,
 		      struct bfa_pcidev_s *pcidev);
-void bfa_iocfc_detach(struct bfa_s *bfa);
 void bfa_iocfc_init(struct bfa_s *bfa);
 void bfa_iocfc_start(struct bfa_s *bfa);
 void bfa_iocfc_stop(struct bfa_s *bfa);
@@ -333,12 +331,9 @@
 			   u32 *maxvec);
 void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
 				 u32 *end);
-void bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi);
 void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
 wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa);
 wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa);
-void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
-				struct bfa_boot_pbc_s *pbcfg);
 int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
 				struct bfi_pbc_vport_s *pbc_vport);
 
@@ -386,19 +381,11 @@
 void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 		struct bfa_meminfo_s *meminfo,
 		struct bfa_pcidev_s *pcidev);
-void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
-void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
 void bfa_detach(struct bfa_s *bfa);
-void bfa_init(struct bfa_s *bfa);
-void bfa_start(struct bfa_s *bfa);
-void bfa_stop(struct bfa_s *bfa);
-void bfa_attach_fcs(struct bfa_s *bfa);
 void bfa_cb_init(void *bfad, bfa_status_t status);
 void bfa_cb_updateq(void *bfad, bfa_status_t status);
 
 bfa_boolean_t bfa_intx(struct bfa_s *bfa);
-void bfa_intx_disable(struct bfa_s *bfa);
-void bfa_intx_enable(struct bfa_s *bfa);
 void bfa_isr_enable(struct bfa_s *bfa);
 void bfa_isr_disable(struct bfa_s *bfa);
 
@@ -408,31 +395,14 @@
 
 typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
 void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
-void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
 
-void bfa_adapter_get_attr(struct bfa_s *bfa,
-			  struct bfa_adapter_attr_s *ad_attr);
-u64 bfa_adapter_get_id(struct bfa_s *bfa);
 
 bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
 				   struct bfa_iocfc_intr_attr_s *attr);
 
 void bfa_iocfc_enable(struct bfa_s *bfa);
 void bfa_iocfc_disable(struct bfa_s *bfa);
-void bfa_chip_reset(struct bfa_s *bfa);
-void bfa_timer_tick(struct bfa_s *bfa);
 #define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)		\
 	bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
 
-/*
- * BFA debug API functions
- */
-bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
-bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
-bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf,
-			      u32 *offset, int *buflen);
-void bfa_debug_fwsave_clear(struct bfa_s *bfa);
-bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data);
-bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa);
-
 #endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/bfa_cb_ioim.h b/drivers/scsi/bfa/bfa_cb_ioim.h
deleted file mode 100644
index 6f02101..0000000
--- a/drivers/scsi/bfa/bfa_cb_ioim.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_HCB_IOIM_H__
-#define __BFA_HCB_IOIM_H__
-
-#include "bfa_os_inc.h"
-/*
- * task attribute values in FCP-2 FCP_CMND IU
- */
-#define SIMPLE_Q    0
-#define HEAD_OF_Q   1
-#define ORDERED_Q   2
-#define ACA_Q	    4
-#define UNTAGGED    5
-
-static inline lun_t
-bfad_int_to_lun(u32 luno)
-{
-	union {
-		u16	scsi_lun[4];
-		lun_t		bfa_lun;
-	} lun;
-
-	lun.bfa_lun     = 0;
-	lun.scsi_lun[0] = cpu_to_be16(luno);
-
-	return lun.bfa_lun;
-}
-
-/*
- * Get LUN for the I/O request
- */
-#define bfa_cb_ioim_get_lun(__dio)	\
-	bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun)
-
-/*
- * Get CDB for the I/O request
- */
-static inline u8 *
-bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
-	return (u8 *) cmnd->cmnd;
-}
-
-/*
- * Get I/O direction (read/write) for the I/O request
- */
-static inline enum fcp_iodir
-bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-	enum dma_data_direction dmadir;
-
-	dmadir = cmnd->sc_data_direction;
-	if (dmadir == DMA_TO_DEVICE)
-		return FCP_IODIR_WRITE;
-	else if (dmadir == DMA_FROM_DEVICE)
-		return FCP_IODIR_READ;
-	else
-		return FCP_IODIR_NONE;
-}
-
-/*
- * Get IO size in bytes for the I/O request
- */
-static inline u32
-bfa_cb_ioim_get_size(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
-	return scsi_bufflen(cmnd);
-}
-
-/*
- * Get timeout for the I/O request
- */
-static inline u8
-bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-	/*
-	 * TBD: need a timeout for scsi passthru
-	 */
-	if (cmnd->device->host == NULL)
-		return 4;
-
-	return 0;
-}
-
-/*
- * Get Command Reference Number for the I/O request. 0 if none.
- */
-static inline u8
-bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio)
-{
-	return 0;
-}
-
-/*
- * Get SAM-3 priority for the I/O request. 0 is default.
- */
-static inline u8
-bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio)
-{
-	return 0;
-}
-
-/*
- * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0).
- */
-static inline u8
-bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-	u8	task_attr = UNTAGGED;
-
-	if (cmnd->device->tagged_supported) {
-		switch (cmnd->tag) {
-		case HEAD_OF_QUEUE_TAG:
-			task_attr = HEAD_OF_Q;
-			break;
-		case ORDERED_QUEUE_TAG:
-			task_attr = ORDERED_Q;
-			break;
-		default:
-			task_attr = SIMPLE_Q;
-			break;
-		}
-	}
-
-	return task_attr;
-}
-
-/*
- * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16).
- */
-static inline u8
-bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
-{
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-
-	return cmnd->cmd_len;
-}
-
-/*
- * Assign queue to be used for the I/O request. This value depends on whether
- * the driver wants to use the queues via any specific algorithm. Currently,
- * this is not supported.
- */
-#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE
-
-#endif /* __BFA_HCB_IOIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 2345f48..1cd5c8b 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -15,13 +15,100 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_modules.h"
 #include "bfi_ctreg.h"
-#include "bfad_drv.h"
 
 BFA_TRC_FILE(HAL, CORE);
 
 /*
+ * BFA module list terminated by NULL
+ */
+static struct bfa_module_s *hal_mods[] = {
+	&hal_mod_sgpg,
+	&hal_mod_fcport,
+	&hal_mod_fcxp,
+	&hal_mod_lps,
+	&hal_mod_uf,
+	&hal_mod_rport,
+	&hal_mod_fcpim,
+	NULL
+};
+
+/*
+ * Message handlers for various modules.
+ */
+static bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
+	bfa_isr_unhandled,	/* NONE */
+	bfa_isr_unhandled,	/* BFI_MC_IOC */
+	bfa_isr_unhandled,	/* BFI_MC_DIAG */
+	bfa_isr_unhandled,	/* BFI_MC_FLASH */
+	bfa_isr_unhandled,	/* BFI_MC_CEE */
+	bfa_fcport_isr,		/* BFI_MC_FCPORT */
+	bfa_isr_unhandled,	/* BFI_MC_IOCFC */
+	bfa_isr_unhandled,	/* BFI_MC_LL */
+	bfa_uf_isr,		/* BFI_MC_UF */
+	bfa_fcxp_isr,		/* BFI_MC_FCXP */
+	bfa_lps_isr,		/* BFI_MC_LPS */
+	bfa_rport_isr,		/* BFI_MC_RPORT */
+	bfa_itnim_isr,		/* BFI_MC_ITNIM */
+	bfa_isr_unhandled,	/* BFI_MC_IOIM_READ */
+	bfa_isr_unhandled,	/* BFI_MC_IOIM_WRITE */
+	bfa_isr_unhandled,	/* BFI_MC_IOIM_IO */
+	bfa_ioim_isr,		/* BFI_MC_IOIM */
+	bfa_ioim_good_comp_isr,	/* BFI_MC_IOIM_IOCOM */
+	bfa_tskim_isr,		/* BFI_MC_TSKIM */
+	bfa_isr_unhandled,	/* BFI_MC_SBOOT */
+	bfa_isr_unhandled,	/* BFI_MC_IPFC */
+	bfa_isr_unhandled,	/* BFI_MC_PORT */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+	bfa_isr_unhandled,	/* --------- */
+};
+/*
+ * Message handlers for mailbox command classes
+ */
+static bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
+	NULL,
+	NULL,		/* BFI_MC_IOC   */
+	NULL,		/* BFI_MC_DIAG  */
+	NULL,		/* BFI_MC_FLASH */
+	NULL,		/* BFI_MC_CEE   */
+	NULL,		/* BFI_MC_PORT  */
+	bfa_iocfc_isr,	/* BFI_MC_IOCFC */
+	NULL,
+};
+
+
+
+static void
+bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+{
+	struct bfa_port_s	*port = &bfa->modules.port;
+	u32			dm_len;
+	u8			*dm_kva;
+	u64			dm_pa;
+
+	dm_len = bfa_port_meminfo();
+	dm_kva = bfa_meminfo_dma_virt(mi);
+	dm_pa  = bfa_meminfo_dma_phys(mi);
+
+	memset(port, 0, sizeof(struct bfa_port_s));
+	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
+	bfa_port_mem_claim(port, dm_kva, dm_pa);
+
+	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
+	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+}
+
+/*
  * BFA IOC FC related definitions
  */
 
@@ -67,18 +154,6 @@
  * BFA Interrupt handling functions
  */
 static void
-bfa_msix_errint(struct bfa_s *bfa, u32 intr)
-{
-	bfa_ioc_error_isr(&bfa->ioc);
-}
-
-static void
-bfa_msix_lpu(struct bfa_s *bfa)
-{
-	bfa_ioc_mbox_isr(&bfa->ioc);
-}
-
-static void
 bfa_reqq_resume(struct bfa_s *bfa, int qid)
 {
 	struct list_head *waitq, *qe, *qen;
@@ -104,9 +179,6 @@
 	bfa_intx(bfa);
 }
 
-/*
- *  hal_intr_api
- */
 bfa_boolean_t
 bfa_intx(struct bfa_s *bfa)
 {
@@ -151,18 +223,6 @@
 }
 
 void
-bfa_intx_enable(struct bfa_s *bfa)
-{
-	writel(bfa->iocfc.intr_mask, bfa->iocfc.bfa_regs.intr_mask);
-}
-
-void
-bfa_intx_disable(struct bfa_s *bfa)
-{
-	writel(-1L, bfa->iocfc.bfa_regs.intr_mask);
-}
-
-void
 bfa_isr_enable(struct bfa_s *bfa)
 {
 	u32 intr_unmask;
@@ -225,7 +285,7 @@
 	bfa_trc(bfa, m->mhdr.msg_class);
 	bfa_trc(bfa, m->mhdr.msg_id);
 	bfa_trc(bfa, m->mhdr.mtag.i2htok);
-	bfa_assert(0);
+	WARN_ON(1);
 	bfa_trc_stop(bfa->trcmod);
 }
 
@@ -236,8 +296,6 @@
 	u32 pi, ci;
 	struct list_head *waitq;
 
-	bfa_trc_fp(bfa, qid);
-
 	qid &= (BFI_IOC_MAX_CQS - 1);
 
 	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
@@ -245,16 +303,10 @@
 	ci = bfa_rspq_ci(bfa, qid);
 	pi = bfa_rspq_pi(bfa, qid);
 
-	bfa_trc_fp(bfa, ci);
-	bfa_trc_fp(bfa, pi);
-
 	if (bfa->rme_process) {
 		while (ci != pi) {
 			m = bfa_rspq_elem(bfa, qid, ci);
-			bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
-
 			bfa_isrs[m->mhdr.msg_class] (bfa, m);
-
 			CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
 		}
 	}
@@ -282,7 +334,7 @@
 	intr = readl(bfa->iocfc.bfa_regs.intr_status);
 
 	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
-		bfa_msix_lpu(bfa);
+		bfa_ioc_mbox_isr(&bfa->ioc);
 
 	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
 		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
@@ -313,22 +365,16 @@
 		}
 
 		writel(intr, bfa->iocfc.bfa_regs.intr_status);
-		bfa_msix_errint(bfa, intr);
+		bfa_ioc_error_isr(&bfa->ioc);
 	}
 }
 
-void
-bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
-{
-	bfa_isrs[mc] = isr_func;
-}
-
 /*
  * BFA IOC FC related functions
  */
 
 /*
- *  hal_ioc_pvt BFA IOC private functions
+ *  BFA IOC private functions
  */
 
 static void
@@ -379,7 +425,7 @@
 	struct bfa_iocfc_cfg_s	*cfg = &iocfc->cfg;
 	int		i;
 
-	bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
+	WARN_ON(cfg->fwcfg.num_cqs > BFI_IOC_MAX_CQS);
 	bfa_trc(bfa, cfg->fwcfg.num_cqs);
 
 	bfa_iocfc_reset_queues(bfa);
@@ -488,8 +534,8 @@
 	 * First allocate dma memory for IOC.
 	 */
 	bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
-	dm_kva += bfa_ioc_meminfo();
-	dm_pa  += bfa_ioc_meminfo();
+	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
+	dm_pa  += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
 
 	/*
 	 * Claim DMA-able memory for the request/response queues and for shadow
@@ -552,7 +598,7 @@
 	bfa_meminfo_dma_virt(meminfo) = dm_kva;
 	bfa_meminfo_dma_phys(meminfo) = dm_pa;
 
-	dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
+	dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
 	if (dbgsz > 0) {
 		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
 		bfa_meminfo_kva(meminfo) += dbgsz;
@@ -699,7 +745,7 @@
 		bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
 			     bfa);
 	else {
-		bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
+		WARN_ON(bfa->iocfc.action != BFA_IOCFC_ACT_DISABLE);
 		bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
 			     bfa);
 	}
@@ -735,9 +781,6 @@
 	bfa_isr_enable(bfa);
 }
 
-/*
- *  hal_ioc_public
- */
 
 /*
  * Query IOC memory requirement information.
@@ -747,11 +790,11 @@
 		  u32 *dm_len)
 {
 	/* dma memory for IOC */
-	*dm_len += bfa_ioc_meminfo();
+	*dm_len += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
 
 	bfa_iocfc_fw_cfg_sz(cfg, dm_len);
 	bfa_iocfc_cqs_sz(cfg, dm_len);
-	*km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
+	*km_len += (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
 }
 
 /*
@@ -783,7 +826,7 @@
 
 	bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
 	bfa_iocfc_mem_claim(bfa, cfg, meminfo);
-	bfa_timer_init(&bfa->timer_mod);
+	INIT_LIST_HEAD(&bfa->timer_mod.timer_q);
 
 	INIT_LIST_HEAD(&bfa->comp_q);
 	for (i = 0; i < BFI_IOC_MAX_CQS; i++)
@@ -794,15 +837,6 @@
  * Query IOC memory requirement information.
  */
 void
-bfa_iocfc_detach(struct bfa_s *bfa)
-{
-	bfa_ioc_detach(&bfa->ioc);
-}
-
-/*
- * Query IOC memory requirement information.
- */
-void
 bfa_iocfc_init(struct bfa_s *bfa)
 {
 	bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
@@ -852,23 +886,11 @@
 		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
 		break;
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
 void
-bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
-{
-	bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
-}
-
-u64
-bfa_adapter_get_id(struct bfa_s *bfa)
-{
-	return bfa_ioc_get_adid(&bfa->ioc);
-}
-
-void
 bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
 {
 	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
@@ -976,18 +998,6 @@
 	memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));
 }
 
-void
-bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
-	pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
-	pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
-	memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
-}
-
 int
 bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
 {
@@ -998,9 +1008,6 @@
 	return cfgrsp->pbc_cfg.nvports;
 }
 
-/*
- *  hal_api
- */
 
 /*
  * Use this function query the memory requirement of the BFA library.
@@ -1036,7 +1043,7 @@
 	int		i;
 	u32	km_len = 0, dm_len = 0;
 
-	bfa_assert((cfg != NULL) && (meminfo != NULL));
+	WARN_ON((cfg == NULL) || (meminfo == NULL));
 
 	memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s));
 	meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type =
@@ -1090,7 +1097,7 @@
 
 	bfa->fcs = BFA_FALSE;
 
-	bfa_assert((cfg != NULL) && (meminfo != NULL));
+	WARN_ON((cfg == NULL) || (meminfo == NULL));
 
 	/*
 	 * initialize all memory pointers for iterative allocation
@@ -1129,79 +1136,7 @@
 
 	for (i = 0; hal_mods[i]; i++)
 		hal_mods[i]->detach(bfa);
-
-	bfa_iocfc_detach(bfa);
-}
-
-
-void
-bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod)
-{
-	bfa->trcmod = trcmod;
-}
-
-void
-bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog)
-{
-	bfa->plog = plog;
-}
-
-/*
- * Initialize IOC.
- *
- * This function will return immediately, when the IOC initialization is
- * completed, the bfa_cb_init() will be called.
- *
- * @param[in]	bfa	instance
- *
- * @return void
- *
- * Special Considerations:
- *
- * @note
- * When this function returns, the driver should register the interrupt service
- * routine(s) and enable the device interrupts. If this is not done,
- * bfa_cb_init() will never get called
- */
-void
-bfa_init(struct bfa_s *bfa)
-{
-	bfa_iocfc_init(bfa);
-}
-
-/*
- * Use this function initiate the IOC configuration setup. This function
- * will return immediately.
- *
- * @param[in]	bfa	instance
- *
- * @return None
- */
-void
-bfa_start(struct bfa_s *bfa)
-{
-	bfa_iocfc_start(bfa);
-}
-
-/*
- * Use this function quiese the IOC. This function will return immediately,
- * when the IOC is actually stopped, the bfad->comp will be set.
- *
- * @param[in]bfa - pointer to bfa_t.
- *
- * @return None
- *
- * Special Considerations:
- * bfad->comp can be set before or after bfa_stop() returns.
- *
- * @note
- * In case of any failure, we could handle it automatically by doing a
- * reset and then succeed the bfa_stop() call.
- */
-void
-bfa_stop(struct bfa_s *bfa)
-{
-	bfa_iocfc_stop(bfa);
+	bfa_ioc_detach(&bfa->ioc);
 }
 
 void
@@ -1237,20 +1172,6 @@
 	}
 }
 
-void
-bfa_attach_fcs(struct bfa_s *bfa)
-{
-	bfa->fcs = BFA_TRUE;
-}
-
-/*
- * Periodic timer heart beat from driver
- */
-void
-bfa_timer_tick(struct bfa_s *bfa)
-{
-	bfa_timer_beat(&bfa->timer_mod);
-}
 
 /*
  * Return the list of PCI vendor/device id lists supported by this
@@ -1321,89 +1242,3 @@
 	cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;
 	cfg->drvcfg.min_cfg	   = BFA_TRUE;
 }
-
-void
-bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr)
-{
-	bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
-}
-
-/*
- * Retrieve firmware trace information on IOC failure.
- */
-bfa_status_t
-bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen)
-{
-	return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen);
-}
-
-/*
- * Clear the saved firmware trace information of an IOC.
- */
-void
-bfa_debug_fwsave_clear(struct bfa_s *bfa)
-{
-	bfa_ioc_debug_fwsave_clear(&bfa->ioc);
-}
-
-/*
- * Fetch firmware trace data.
- *
- * @param[in]		bfa			BFA instance
- * @param[out]		trcdata		Firmware trace buffer
- * @param[in,out]	trclen		Firmware trace buffer len
- *
- * @retval BFA_STATUS_OK			Firmware trace is fetched.
- * @retval BFA_STATUS_INPROGRESS	Firmware trace fetch is in progress.
- */
-bfa_status_t
-bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen)
-{
-	return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen);
-}
-
-/*
- * Dump firmware memory.
- *
- * @param[in]		bfa		BFA instance
- * @param[out]		buf		buffer for dump
- * @param[in,out]	offset		smem offset to start read
- * @param[in,out]	buflen		length of buffer
- *
- * @retval BFA_STATUS_OK		Firmware memory is dumped.
- * @retval BFA_STATUS_INPROGRESS	Firmware memory dump is in progress.
- */
-bfa_status_t
-bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen)
-{
-	return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen);
-}
-/*
- * Reset hw semaphore & usage cnt regs and initialize.
- */
-void
-bfa_chip_reset(struct bfa_s *bfa)
-{
-	bfa_ioc_ownership_reset(&bfa->ioc);
-	bfa_ioc_pll_init(&bfa->ioc);
-}
-
-/*
- * Fetch firmware statistics data.
- *
- * @param[in]		bfa		BFA instance
- * @param[out]		data		Firmware stats buffer
- *
- * @retval BFA_STATUS_OK		Firmware trace is fetched.
- */
-bfa_status_t
-bfa_fw_stats_get(struct bfa_s *bfa, void *data)
-{
-	return bfa_ioc_fw_stats_get(&bfa->ioc, data);
-}
-
-bfa_status_t
-bfa_fw_stats_clear(struct bfa_s *bfa)
-{
-	return bfa_ioc_fw_stats_clear(&bfa->ioc);
-}
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
index 99f242b..12bfeed 100644
--- a/drivers/scsi/bfa/bfa_cs.h
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -22,7 +22,7 @@
 #ifndef __BFA_CS_H__
 #define __BFA_CS_H__
 
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 
 /*
  * BFA TRC
@@ -32,12 +32,20 @@
 #define BFA_TRC_MAX	(4 * 1024)
 #endif
 
+#define BFA_TRC_TS(_trcm)                               \
+	({                                              \
+		struct timeval tv;                      \
+							\
+		do_gettimeofday(&tv);                   \
+		(tv.tv_sec*1000000+tv.tv_usec);         \
+	})
+
 #ifndef BFA_TRC_TS
 #define BFA_TRC_TS(_trcm)	((_trcm)->ticks++)
 #endif
 
 struct bfa_trc_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u16	fileno;
 	u16	line;
 #else
@@ -99,13 +107,6 @@
 	trcm->stopped = 1;
 }
 
-#ifdef FWTRC
-extern void dc_flush(void *data);
-#else
-#define dc_flush(data)
-#endif
-
-
 static inline void
 __bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
 {
@@ -119,12 +120,10 @@
 	trc->line = (u16) line;
 	trc->data.u64 = data;
 	trc->timestamp = BFA_TRC_TS(trcm);
-	dc_flush(trc);
 
 	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
 	if (trcm->tail == trcm->head)
 		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
-	dc_flush(trcm);
 }
 
 
@@ -141,42 +140,18 @@
 	trc->line = (u16) line;
 	trc->data.u32.u32 = data;
 	trc->timestamp = BFA_TRC_TS(trcm);
-	dc_flush(trc);
 
 	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
 	if (trcm->tail == trcm->head)
 		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
-	dc_flush(trcm);
 }
 
-#ifndef BFA_PERF_BUILD
-#define bfa_trc_fp(_trcp, _data)	bfa_trc(_trcp, _data)
-#else
-#define bfa_trc_fp(_trcp, _data)
-#endif
-
-/*
- * @ BFA LOG interfaces
- */
-#define bfa_assert(__cond)	do {					\
-	if (!(__cond)) {						\
-		printk(KERN_ERR "assert(%s) failed at %s:%d\\n",         \
-		#__cond, __FILE__, __LINE__);				\
-	}								\
-} while (0)
-
 #define bfa_sm_fault(__mod, __event)	do {				\
 	bfa_trc(__mod, (((u32)0xDEAD << 16) | __event));		\
 	printk(KERN_ERR	"Assertion failure: %s:%d: %d",			\
 		__FILE__, __LINE__, (__event));				\
 } while (0)
 
-#ifndef BFA_PERF_BUILD
-#define bfa_assert_fp(__cond)	bfa_assert(__cond)
-#else
-#define bfa_assert_fp(__cond)
-#endif
-
 /* BFA queue definitions */
 #define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
 #define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
@@ -199,7 +174,6 @@
 		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
 				(struct list_head *) (_q);		\
 		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\
-		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
 	} else {							\
 		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
 	}								\
@@ -214,7 +188,6 @@
 		bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) =	\
 			(struct list_head *) (_q);			\
 		bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
-		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
 	} else {							\
 		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
 	}								\
@@ -236,16 +209,6 @@
 	return 0;
 }
 
-/*
- * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
- * consistent across modules)
- */
-#ifndef BFA_PERF_BUILD
-#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe)
-#else
-#define BFA_Q_DBG_INIT(_qe)
-#endif
-
 #define bfa_q_is_on_q(_q, _qe)      \
 	bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
 
@@ -361,4 +324,43 @@
 	bfa_wc_down(wc);
 }
 
+static inline void
+wwn2str(char *wwn_str, u64 wwn)
+{
+	union {
+		u64 wwn;
+		u8 byte[8];
+	} w;
+
+	w.wwn = wwn;
+	sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0],
+		w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5],
+		w.byte[6], w.byte[7]);
+}
+
+static inline void
+fcid2str(char *fcid_str, u32 fcid)
+{
+	union {
+		u32 fcid;
+		u8 byte[4];
+	} f;
+
+	f.fcid = fcid;
+	sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]);
+}
+
+#define bfa_swap_3b(_x)				\
+	((((_x) & 0xff) << 16) |		\
+	((_x) & 0x00ff00) |			\
+	(((_x) & 0xff0000) >> 16))
+
+#ifndef __BIG_ENDIAN
+#define bfa_hton3b(_x)  bfa_swap_3b(_x)
+#else
+#define bfa_hton3b(_x)  (_x)
+#endif
+
+#define bfa_ntoh3b(_x)  bfa_hton3b(_x)
+
 #endif /* __BFA_CS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index 4b5b9e3..d85f93a 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -19,7 +19,7 @@
 #define __BFA_DEFS_H__
 
 #include "bfa_fc.h"
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 
 #define BFA_MFG_SERIALNUM_SIZE                  11
 #define STRSZ(_n)                               (((_n) + 4) & ~3)
@@ -446,8 +446,8 @@
  * Boot lun information.
  */
 struct bfa_boot_bootlun_s {
-	wwn_t   pwwn;   /*  port wwn of target */
-	lun_t   lun;    /*  64-bit lun */
+	wwn_t   pwwn;		/*  port wwn of target */
+	struct scsi_lun   lun;  /*  64-bit lun */
 };
 #pragma pack()
 
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index e24e9f7..648c841 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -34,8 +34,8 @@
 struct bfa_iocfc_intr_attr_s {
 	u8		coalesce;	/*  enable/disable coalescing */
 	u8		rsvd[3];
-	u16	latency;	/*  latency in microseconds   */
-	u16	delay;		/*  delay in microseconds     */
+	__be16	latency;	/*  latency in microseconds   */
+	__be16	delay;		/*  delay in microseconds     */
 };
 
 /*
@@ -743,7 +743,7 @@
 	u8	 qos_enabled;	/*  qos enabled or not		*/
 	u8	 cfg_hardalpa;	/*  is hard alpa configured	*/
 	u8	 hardalpa;	/*  configured hard alpa	*/
-	u16 maxfrsize;	/*  maximum frame size		*/
+	__be16	 maxfrsize;	/*  maximum frame size		*/
 	u8	 rx_bbcredit;	/*  receive buffer credits	*/
 	u8	 tx_bbcredit;	/*  transmit buffer credits	*/
 	u8	 ratelimit;	/*  ratelimit enabled or not	*/
@@ -843,7 +843,7 @@
 	u8	 fka_disabled;   /*  FKA is disabled	  */
 	u8	 maxsz_verified; /*  FCoE max size verified   */
 	u8	 fc_map[3];      /*  FC map		   */
-	u16	vlan;	   /*  FCoE vlan tag/priority   */
+	__be16	 vlan;	   /*  FCoE vlan tag/priority   */
 	u32	fka_adv_per;    /*  FIP  ka advert. period   */
 	mac_t	   mac;	    /*  FCF mac		  */
 };
diff --git a/drivers/scsi/bfa/bfa_drv.c b/drivers/scsi/bfa/bfa_drv.c
deleted file mode 100644
index 0222d7c..0000000
--- a/drivers/scsi/bfa/bfa_drv.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#include "bfa_modules.h"
-
-/*
- * BFA module list terminated by NULL
- */
-struct bfa_module_s *hal_mods[] = {
-	&hal_mod_sgpg,
-	&hal_mod_fcport,
-	&hal_mod_fcxp,
-	&hal_mod_lps,
-	&hal_mod_uf,
-	&hal_mod_rport,
-	&hal_mod_fcpim,
-	NULL
-};
-
-/*
- * Message handlers for various modules.
- */
-bfa_isr_func_t  bfa_isrs[BFI_MC_MAX] = {
-	bfa_isr_unhandled,	/* NONE */
-	bfa_isr_unhandled,	/* BFI_MC_IOC */
-	bfa_isr_unhandled,	/* BFI_MC_DIAG */
-	bfa_isr_unhandled,	/* BFI_MC_FLASH */
-	bfa_isr_unhandled,	/* BFI_MC_CEE */
-	bfa_fcport_isr,		/* BFI_MC_FCPORT */
-	bfa_isr_unhandled,	/* BFI_MC_IOCFC */
-	bfa_isr_unhandled,	/* BFI_MC_LL */
-	bfa_uf_isr,		/* BFI_MC_UF */
-	bfa_fcxp_isr,		/* BFI_MC_FCXP */
-	bfa_lps_isr,		/* BFI_MC_LPS */
-	bfa_rport_isr,		/* BFI_MC_RPORT */
-	bfa_itnim_isr,		/* BFI_MC_ITNIM */
-	bfa_isr_unhandled,	/* BFI_MC_IOIM_READ */
-	bfa_isr_unhandled,	/* BFI_MC_IOIM_WRITE */
-	bfa_isr_unhandled,	/* BFI_MC_IOIM_IO */
-	bfa_ioim_isr,		/* BFI_MC_IOIM */
-	bfa_ioim_good_comp_isr,	/* BFI_MC_IOIM_IOCOM */
-	bfa_tskim_isr,		/* BFI_MC_TSKIM */
-	bfa_isr_unhandled,	/* BFI_MC_SBOOT */
-	bfa_isr_unhandled,	/* BFI_MC_IPFC */
-	bfa_isr_unhandled,	/* BFI_MC_PORT */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-	bfa_isr_unhandled,	/* --------- */
-};
-
-
-/*
- * Message handlers for mailbox command classes
- */
-bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
-	NULL,
-	NULL,			/* BFI_MC_IOC   */
-	NULL,			/* BFI_MC_DIAG  */
-	NULL,		/* BFI_MC_FLASH */
-	NULL,			/* BFI_MC_CEE   */
-	NULL,			/* BFI_MC_PORT  */
-	bfa_iocfc_isr,		/* BFI_MC_IOCFC */
-	NULL,
-};
-
-
-
-void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
-{
-	struct bfa_port_s	*port = &bfa->modules.port;
-	u32		dm_len;
-	u8			*dm_kva;
-	u64		dm_pa;
-
-	dm_len = bfa_port_meminfo();
-	dm_kva = bfa_meminfo_dma_virt(mi);
-	dm_pa  = bfa_meminfo_dma_phys(mi);
-
-	memset(port, 0, sizeof(struct bfa_port_s));
-	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
-	bfa_port_mem_claim(port, dm_kva, dm_pa);
-
-	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
-	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
-}
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index e929d25..8e764fa 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -18,14 +18,12 @@
 #ifndef __BFA_FC_H__
 #define __BFA_FC_H__
 
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 
 typedef u64 wwn_t;
-typedef u64 lun_t;
 
 #define WWN_NULL	(0)
 #define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */
-#define FC_ALPA_MAX	128
 
 #pragma pack(1)
 
@@ -40,7 +38,6 @@
 struct scsi_cdb_s {
 	u8         scsi_cdb[SCSI_MAX_CDBLEN];
 };
-#define scsi_cdb_t struct scsi_cdb_s
 
 /* ------------------------------------------------------------
  * SCSI status byte values
@@ -63,7 +60,7 @@
  * Fibre Channel Header Structure (FCHS) definition
  */
 struct fchs_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u32        routing:4;	/* routing bits */
 	u32        cat_info:4;	/* category info */
 #else
@@ -75,34 +72,19 @@
 	u32        cs_ctl:8;	/* class specific control */
 	u32        s_id:24;	/* source identifier */
 
-	u32        type:8;		/* data structure type */
+	u32        type:8;	/* data structure type */
 	u32        f_ctl:24;	/* initial frame control */
 
-	u8         seq_id;		/* sequence identifier */
-	u8         df_ctl;		/* data field control */
+	u8         seq_id;	/* sequence identifier */
+	u8         df_ctl;	/* data field control */
 	u16        seq_cnt;	/* sequence count */
 
-	u16        ox_id;		/* originator exchange ID */
-	u16        rx_id;		/* responder exchange ID */
+	__be16     ox_id;	/* originator exchange ID */
+	u16        rx_id;	/* responder exchange ID */
 
 	u32        ro;		/* relative offset */
 };
 
-#define FC_SOF_LEN		4
-#define FC_EOF_LEN		4
-#define FC_CRC_LEN		4
-
-/*
- * Fibre Channel BB_E Header Structure
- */
-struct fcbbehs_s {
-	u16	ver_rsvd;
-	u32	rsvd[2];
-	u32	rsvd__sof;
-};
-
-#define FC_SEQ_ID_MAX		256
-
 /*
  * routing bit definitions
  */
@@ -149,22 +131,6 @@
 };
 
 /*
- * information category for Link Control
- */
-enum {
-	FC_CAT_ACK_1		= 0x00,
-	FC_CAT_ACK_0_N		= 0x01,
-	FC_CAT_P_RJT		= 0x02,
-	FC_CAT_F_RJT		= 0x03,
-	FC_CAT_P_BSY		= 0x04,
-	FC_CAT_F_BSY_DATA	= 0x05,
-	FC_CAT_F_BSY_LINK_CTL	= 0x06,
-	FC_CAT_F_LCR		= 0x07,
-	FC_CAT_NTY		= 0x08,
-	FC_CAT_END		= 0x09,
-};
-
-/*
  * Type Field Definitions. FC-PH Section 18.5 pg. 165
  */
 enum {
@@ -182,10 +148,6 @@
 	FC_TYPE_MAX		= 256,	/* 256 FC-4 types */
 };
 
-struct fc_fc4types_s {
-	u8         bits[FC_TYPE_MAX / 8];
-};
-
 /*
  * Frame Control Definitions. FC-PH Table-45. pg. 168
  */
@@ -288,7 +250,6 @@
 	FC_ELS_AUTH = 0x90,	/* Authentication. Ref FC-SP */
 	FC_ELS_RFCN = 0x97,	/* Request Fabric Change Notification. Ref
 				 *FC-SP */
-
 };
 
 /*
@@ -314,12 +275,12 @@
  * FC-PH-x. Figure-76. pg. 308.
  */
 struct fc_plogi_csp_s {
-	u8         verhi;	/* FC-PH high version */
-	u8         verlo;	/* FC-PH low version */
-	u16        bbcred;	/* BB_Credit */
+	u8		verhi;		/* FC-PH high version */
+	u8		verlo;		/* FC-PH low version */
+	__be16		bbcred;		/* BB_Credit */
 
-#ifdef __BIGENDIAN
-	u8         ciro:1,		/* continuously increasing RO */
+#ifdef __BIG_ENDIAN
+	u8		ciro:1,		/* continuously increasing RO */
 			rro:1,		/* random relative offset */
 			npiv_supp:1,	/* NPIV supported */
 			port_type:1,	/* N_Port/F_port */
@@ -328,7 +289,7 @@
 			vvl_info:1,	/* VVL Info included */
 			reserved1:1;
 
-	u8         hg_supp:1,
+	u8		hg_supp:1,
 			query_dbc:1,
 			security:1,
 			sync_cap:1,
@@ -337,7 +298,7 @@
 			cisc:1,		/* continuously increasing seq count */
 			payload:1;
 #else
-	u8         reserved2:2,
+	u8		reserved2:2,
 			resolution:1,	/* ms/ns ED_TOV resolution */
 			altbbcred:1,	/* alternate BB_Credit */
 			port_type:1,	/* N_Port/F_port */
@@ -345,7 +306,7 @@
 			rro:1,		/* random relative offset */
 			ciro:1;		/* continuously increasing RO */
 
-	u8         payload:1,
+	u8		payload:1,
 			cisc:1,		/* continuously increasing seq count */
 			dh_dup_supp:1,
 			r_t_tov:1,
@@ -354,13 +315,10 @@
 			query_dbc:1,
 			hg_supp:1;
 #endif
-
-	u16        rxsz;		/* recieve data_field size */
-
-	u16        conseq;
-	u16        ro_bitmap;
-
-	u32        e_d_tov;
+	__be16		rxsz;		/* recieve data_field size */
+	__be16		conseq;
+	__be16		ro_bitmap;
+	__be32		e_d_tov;
 };
 
 /*
@@ -368,12 +326,11 @@
  * FC-PH-x. Figure 78. pg. 318.
  */
 struct fc_plogi_clp_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u32        class_valid:1;
 	u32        intermix:1;	/* class intermix supported if set =1.
-					 * valid only for class1. Reserved for
-					 * class2 & class3
-					 */
+				 * valid only for class1. Reserved for
+				 * class2 & class3 */
 	u32        reserved1:2;
 	u32        sequential:1;
 	u32        reserved2:3;
@@ -382,12 +339,10 @@
 	u32        sequential:1;
 	u32        reserved1:2;
 	u32        intermix:1;	/* class intermix supported if set =1.
-					 * valid only for class1. Reserved for
-					 * class2 & class3
-					 */
+				 * valid only for class1. Reserved for
+				 * class2 & class3 */
 	u32        class_valid:1;
 #endif
-
 	u32        reserved3:24;
 
 	u32        reserved4:16;
@@ -395,7 +350,7 @@
 
 	u32        reserved5:8;
 	u32        conseq:8;
-	u32        e2e_credit:16;	/* end to end credit */
+	u32        e2e_credit:16; /* end to end credit */
 
 	u32        reserved7:8;
 	u32        ospx:8;
@@ -409,24 +364,24 @@
  * PLOGI els command and reply payload
  */
 struct fc_logi_s {
-	struct fc_els_cmd_s els_cmd;	/* ELS command code */
-	struct fc_plogi_csp_s csp;		/* common service params */
-	wwn_t           port_name;
-	wwn_t           node_name;
-	struct fc_plogi_clp_s class1;		/* class 1 service parameters */
-	struct fc_plogi_clp_s class2;		/* class 2 service parameters */
-	struct fc_plogi_clp_s class3;		/* class 3 service parameters */
-	struct fc_plogi_clp_s class4;		/* class 4 service parameters */
-	u8         vvl[16];	/* vendor version level */
+	struct fc_els_cmd_s	els_cmd;	/* ELS command code */
+	struct fc_plogi_csp_s	csp;		/* common service params */
+	wwn_t			port_name;
+	wwn_t			node_name;
+	struct fc_plogi_clp_s	class1;		/* class 1 service parameters */
+	struct fc_plogi_clp_s	class2;		/* class 2 service parameters */
+	struct fc_plogi_clp_s	class3;		/* class 3 service parameters */
+	struct fc_plogi_clp_s	class4;		/* class 4 service parameters */
+	u8			vvl[16];	/* vendor version level */
 };
 
 /*
  * LOGO els command payload
  */
 struct fc_logo_s {
-	struct fc_els_cmd_s els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
+	struct fc_els_cmd_s	els_cmd;	/* ELS command code */
+	u32			res1:8;
+	u32		nport_id:24;	/* N_Port identifier of source */
 	wwn_t           orig_port_name;	/* Port name of the LOGO originator */
 };
 
@@ -435,12 +390,12 @@
  */
 struct fc_adisc_s {
 	struct fc_els_cmd_s els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        orig_HA:24;	/* originator hard address */
-	wwn_t           orig_port_name;	/* originator port name */
-	wwn_t           orig_node_name;	/* originator node name */
-	u32        res2:8;
-	u32        nport_id:24;	/* originator NPortID */
+	u32		res1:8;
+	u32		orig_HA:24;	/* originator hard address */
+	wwn_t		orig_port_name;	/* originator port name */
+	wwn_t		orig_node_name;	/* originator node name */
+	u32		res2:8;
+	u32		nport_id:24;	/* originator NPortID */
 };
 
 /*
@@ -466,7 +421,7 @@
 struct fc_res_s {
 	struct fc_els_cmd_s els_cmd;	/* ELS command code */
 	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
+	u32        nport_id:24;		/* N_Port identifier of source */
 	u32        oxid:16;
 	u32        rxid:16;
 	u8         assoc_hdr[32];
@@ -512,8 +467,8 @@
 	u32        orig_id:24;	/* N_Port id of exchange originator */
 	u32        res2:8;
 	u32        resp_id:24;	/* N_Port id of exchange responder */
-	u32        count;		/* data transfer count */
-	u32        e_stat;		/* exchange status */
+	u32        count;	/* data transfer count */
+	u32        e_stat;	/* exchange status */
 };
 
 /*
@@ -533,7 +488,7 @@
  */
 struct fc_prli_params_s {
 	u32        reserved:16;
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u32        reserved1:5;
 	u32        rec_support:1;
 	u32        task_retry_id:1;
@@ -575,7 +530,7 @@
 struct fc_prli_params_page_s {
 	u32        type:8;
 	u32        codext:8;
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u32        origprocasv:1;
 	u32        rsppav:1;
 	u32        imagepair:1;
@@ -611,18 +566,14 @@
 struct fc_prlo_params_page_s {
 	u32        type:8;
 	u32        type_ext:8;
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
+#ifdef __BIG_ENDIAN
+	u32        opa_valid:1;	/* originator process associator valid */
 	u32        rpa_valid:1;	/* responder process associator valid */
 	u32        res1:14;
 #else
 	u32        res1:14;
 	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
+	u32        opa_valid:1;	/* originator process associator valid */
 #endif
 	u32        orig_process_assc;
 	u32        resp_process_assc;
@@ -647,18 +598,14 @@
 	u32        type:8;
 	u32        type_ext:8;
 
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
+#ifdef __BIG_ENDIAN
+	u32        opa_valid:1;	/* originator process associator valid */
 	u32        rpa_valid:1;	/* responder process associator valid */
 	u32        res1:14;
 #else
 	u32        res1:14;
 	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
+	u32        opa_valid:1;	/* originator process associator valid */
 #endif
 	u32        orig_process_assc;
 	u32        resp_process_assc;
@@ -715,9 +662,9 @@
  * LS_RJT els reply payload
  */
 struct fc_ls_rjt_s {
-	struct fc_els_cmd_s els_cmd;		/* ELS command code */
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
 	u32        res1:8;
-	u32        reason_code:8;		/* Reason code for reject */
+	u32        reason_code:8;	/* Reason code for reject */
 	u32        reason_code_expl:8;	/* Reason code explanation */
 	u32        vendor_unique:8;	/* Vendor specific */
 };
@@ -779,12 +726,12 @@
  */
 struct fc_ba_acc_s {
 	u32        seq_id_valid:8;	/* set to 0x00 for Abort Exchange */
-	u32        seq_id:8;	/* invalid for Abort Exchange */
+	u32        seq_id:8;		/* invalid for Abort Exchange */
 	u32        res2:16;
-	u32        ox_id:16;	/* OX_ID from ABTS frame */
-	u32        rx_id:16;	/* RX_ID from ABTS frame */
+	u32        ox_id:16;		/* OX_ID from ABTS frame */
+	u32        rx_id:16;		/* RX_ID from ABTS frame */
 	u32        low_seq_cnt:16;	/* set to 0x0000 for Abort Exchange */
-	u32        high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */
+	u32        high_seq_cnt:16;	/* set to 0xFFFF for Abort Exchange */
 };
 
 /*
@@ -794,17 +741,17 @@
 	u32        res1:8;		/* Reserved */
 	u32        reason_code:8;	/* reason code for reject */
 	u32        reason_expl:8;	/* reason code explanation */
-	u32        vendor_unique:8;/* vendor unique reason code,set to 0 */
+	u32        vendor_unique:8; /* vendor unique reason code,set to 0 */
 };
 
 /*
  * TPRLO logout parameter page
  */
 struct fc_tprlo_params_page_s {
-u32        type:8;
-u32        type_ext:8;
+	u32        type:8;
+	u32        type_ext:8;
 
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u32        opa_valid:1;
 	u32        rpa_valid:1;
 	u32        tpo_nport_valid:1;
@@ -864,16 +811,16 @@
 };
 
 struct fc_rscn_event_s {
-	u32        format:2;
-	u32        qualifier:4;
-	u32        resvd:2;
-	u32        portid:24;
+	u32	format:2;
+	u32	qualifier:4;
+	u32	resvd:2;
+	u32	portid:24;
 };
 
 struct fc_rscn_pl_s {
-	u8         command;
-	u8         pagelen;
-	u16        payldlen;
+	u8	command;
+	u8	pagelen;
+	__be16	payldlen;
 	struct fc_rscn_event_s event[1];
 };
 
@@ -887,7 +834,6 @@
 /*
  * RNID els command
  */
-
 #define RNID_NODEID_DATA_FORMAT_COMMON			0x00
 #define RNID_NODEID_DATA_FORMAT_FCP3			0x08
 #define RNID_NODEID_DATA_FORMAT_DISCOVERY		0xDF
@@ -920,15 +866,15 @@
  */
 
 struct fc_rnid_common_id_data_s {
-	wwn_t           port_name;
+	wwn_t		port_name;
 	wwn_t           node_name;
 };
 
 struct fc_rnid_general_topology_data_s {
 	u32        vendor_unique[4];
-	u32        asso_type;
+	__be32     asso_type;
 	u32        phy_port_num;
-	u32        num_attached_nodes;
+	__be32     num_attached_nodes;
 	u32        node_mgmt:8;
 	u32        ip_version:8;
 	u32        udp_tcp_port_num:16;
@@ -980,59 +926,17 @@
 	RPSC_OP_SPEED_8G = 0x0800,
 	RPSC_OP_SPEED_16G = 0x0400,
 
-	RPSC_OP_SPEED_NOT_EST = 0x0001,	/*! speed not established */
+	RPSC_OP_SPEED_NOT_EST = 0x0001,	/* speed not established */
 };
 
 struct fc_rpsc_speed_info_s {
-	u16        port_speed_cap;	/*! see enum fc_rpsc_speed_cap */
-	u16        port_op_speed;	/*! see enum fc_rpsc_op_speed */
-};
-
-enum link_e2e_beacon_subcmd {
-	LINK_E2E_BEACON_ON = 1,
-	LINK_E2E_BEACON_OFF = 2
-};
-
-enum beacon_type {
-	BEACON_TYPE_NORMAL	= 1,	/*! Normal Beaconing. Green */
-	BEACON_TYPE_WARN	= 2,	/*! Warning Beaconing. Yellow/Amber */
-	BEACON_TYPE_CRITICAL	= 3	/*! Critical Beaconing. Red */
-};
-
-struct link_e2e_beacon_param_s {
-	u8         beacon_type;	/* Beacon Type. See enum beacon_type */
-	u8         beacon_frequency;
-					/* Beacon frequency. Number of blinks
-					 * per 10 seconds
-					 */
-	u16        beacon_duration;/* Beacon duration (in Seconds). The
-					 * command operation should be
-					 * terminated at the end of this
-					 * timeout value.
-					 *
-					 * Ignored if diag_sub_cmd is
-					 * LINK_E2E_BEACON_OFF.
-					 *
-					 * If 0, beaconing will continue till a
-					 * BEACON OFF request is received
-					 */
-};
-
-/*
- * Link E2E beacon request/good response format.
- * For LS_RJTs use struct fc_ls_rjt_s
- */
-struct link_e2e_beacon_req_s {
-	u32        ls_code;	/*! FC_ELS_E2E_LBEACON in requests *
-					 *or FC_ELS_ACC in good replies */
-	u32        ls_sub_cmd;	/*! See enum link_e2e_beacon_subcmd */
-	struct link_e2e_beacon_param_s beacon_parm;
+	__be16        port_speed_cap;	/* see enum fc_rpsc_speed_cap */
+	__be16        port_op_speed;	/* see enum fc_rpsc_op_speed */
 };
 
 /*
  * If RPSC request is sent to the Domain Controller, the request is for
- * all the ports within that domain (TODO - I don't think FOS implements
- * this...).
+ * all the ports within that domain.
  */
 struct fc_rpsc_cmd_s {
 	struct fc_els_cmd_s els_cmd;
@@ -1056,9 +960,9 @@
 
 struct fc_rpsc2_cmd_s {
 	struct fc_els_cmd_s els_cmd;
-	u32	token;
+	__be32	token;
 	u16	resvd;
-	u16	num_pids;	/* Number of pids in the request */
+	__be16	num_pids;		/* Number of pids in the request */
 	struct  {
 		u32	rsvd1:8;
 		u32	pid:24;		/* port identifier */
@@ -1072,16 +976,17 @@
 	RPSC2_PORT_TYPE_NPIV_PORT  = 0x5f,
 	RPSC2_PORT_TYPE_NPORT_TRUNK  = 0x6f,
 };
+
 /*
  * RPSC2 portInfo entry structure
  */
 struct fc_rpsc2_port_info_s {
-    u32    pid;        /* PID */
-    u16    resvd1;
-    u16    index;      /* port number / index */
-    u8     resvd2;
-    u8	   type;	/* port type N/NL/... */
-    u16    speed;      /* port Operating Speed */
+	__be32	pid;		/* PID */
+	u16	resvd1;
+	__be16	index;		/* port number / index */
+	u8	resvd2;
+	u8	type;		/* port type N/NL/... */
+	__be16	speed;		/* port Operating Speed */
 };
 
 /*
@@ -1090,8 +995,8 @@
 struct fc_rpsc2_acc_s {
 	u8        els_cmd;
 	u8        resvd;
-    u16       num_pids;  /* Number of pids in the request */
-    struct fc_rpsc2_port_info_s port_info[1];    /* port information */
+	__be16    num_pids; /* Number of pids in the request */
+	struct fc_rpsc2_port_info_s port_info[1]; /* port information */
 };
 
 /*
@@ -1110,18 +1015,14 @@
 	u8         symname[FC_SYMNAME_MAX];
 };
 
-struct fc_alpabm_s {
-	u8         alpa_bm[FC_ALPA_MAX / 8];
-};
-
 /*
  * protocol default timeout values
  */
-#define FC_ED_TOV		2
-#define FC_REC_TOV		(FC_ED_TOV + 1)
-#define FC_RA_TOV		10
-#define FC_ELS_TOV		(2 * FC_RA_TOV)
-#define FC_FCCT_TOV		(3 * FC_RA_TOV)
+#define FC_ED_TOV	2
+#define FC_REC_TOV	(FC_ED_TOV + 1)
+#define FC_RA_TOV	10
+#define FC_ELS_TOV	(2 * FC_RA_TOV)
+#define FC_FCCT_TOV	(3 * FC_RA_TOV)
 
 /*
  * virtual fabric related defines
@@ -1157,50 +1058,34 @@
 };
 
 /*
- * SRR FC-4 LS payload
- */
-struct fc_srr_s {
-	u32	ls_cmd;
-	u32        ox_id:16;	/* ox-id */
-	u32        rx_id:16;	/* rx-id */
-	u32        ro;		/* relative offset */
-	u32        r_ctl:8;		/* R_CTL for I.U. */
-	u32        res:24;
-};
-
-
-/*
  * FCP_CMND definitions
  */
 #define FCP_CMND_CDB_LEN    16
 #define FCP_CMND_LUN_LEN    8
 
 struct fcp_cmnd_s {
-	lun_t           lun;		/* 64-bit LU number */
-	u8         crn;		/* command reference number */
-#ifdef __BIGENDIAN
-	u8         resvd:1,
+	struct scsi_lun	lun;		/* 64-bit LU number */
+	u8		crn;		/* command reference number */
+#ifdef __BIG_ENDIAN
+	u8		resvd:1,
 			priority:4,	/* FCP-3: SAM-3 priority */
 			taskattr:3;	/* scsi task attribute */
 #else
-	u8         taskattr:3,	/* scsi task attribute */
+	u8		taskattr:3,	/* scsi task attribute */
 			priority:4,	/* FCP-3: SAM-3 priority */
 			resvd:1;
 #endif
-	u8         tm_flags;	/* task management flags */
-#ifdef __BIGENDIAN
-	u8         addl_cdb_len:6,	/* additional CDB length words */
+	u8		tm_flags;	/* task management flags */
+#ifdef __BIG_ENDIAN
+	u8		addl_cdb_len:6,	/* additional CDB length words */
 			iodir:2;	/* read/write FCP_DATA IUs */
 #else
-	u8         iodir:2,	/* read/write FCP_DATA IUs */
+	u8		iodir:2,	/* read/write FCP_DATA IUs */
 			addl_cdb_len:6;	/* additional CDB length */
 #endif
-	scsi_cdb_t      cdb;
+	struct scsi_cdb_s      cdb;
 
-	/*
-	 * !!! additional cdb bytes follows here!!!
-	 */
-	u32        fcp_dl;	/* bytes to be transferred */
+	__be32        fcp_dl;	/* bytes to be transferred */
 };
 
 #define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
@@ -1210,21 +1095,10 @@
  * struct fcp_cmnd_s .iodir field values
  */
 enum fcp_iodir {
-	FCP_IODIR_NONE	= 0,
+	FCP_IODIR_NONE  = 0,
 	FCP_IODIR_WRITE = 1,
-	FCP_IODIR_READ	= 2,
-	FCP_IODIR_RW	= 3,
-};
-
-/*
- * Task attribute field
- */
-enum {
-	FCP_TASK_ATTR_SIMPLE	= 0,
-	FCP_TASK_ATTR_HOQ	= 1,
-	FCP_TASK_ATTR_ORDERED	= 2,
-	FCP_TASK_ATTR_ACA	= 4,
-	FCP_TASK_ATTR_UNTAGGED	= 5,	/* obsolete in FCP-3 */
+	FCP_IODIR_READ  = 2,
+	FCP_IODIR_RW    = 3,
 };
 
 /*
@@ -1239,58 +1113,40 @@
 };
 
 /*
- * FCP_XFER_RDY IU defines
- */
-struct fcp_xfer_rdy_s {
-	u32        data_ro;
-	u32        burst_len;
-	u32        reserved;
-};
-
-/*
  * FCP_RSP residue flags
  */
 enum fcp_residue {
-	FCP_NO_RESIDUE = 0,	/* no residue */
-	FCP_RESID_OVER = 1,	/* more data left that was not sent */
-	FCP_RESID_UNDER = 2,	/* less data than requested */
-};
-
-enum {
-	FCP_RSPINFO_GOOD = 0,
-	FCP_RSPINFO_DATALEN_MISMATCH = 1,
-	FCP_RSPINFO_CMND_INVALID = 2,
-	FCP_RSPINFO_ROLEN_MISMATCH = 3,
-	FCP_RSPINFO_TM_NOT_SUPP = 4,
-	FCP_RSPINFO_TM_FAILED = 5,
+	FCP_NO_RESIDUE = 0,     /* no residue */
+	FCP_RESID_OVER = 1,     /* more data left that was not sent */
+	FCP_RESID_UNDER = 2,    /* less data than requested */
 };
 
 struct fcp_rspinfo_s {
 	u32        res0:24;
-	u32        rsp_code:8;	/* response code (as above) */
+	u32        rsp_code:8;		/* response code (as above) */
 	u32        res1;
 };
 
 struct fcp_resp_s {
-	u32        reserved[2];	/* 2 words reserved */
+	u32        reserved[2];		/* 2 words reserved */
 	u16        reserved2;
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u8         reserved3:3;
 	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
 	u8         resid_flags:2;	/* underflow/overflow */
-	u8         sns_len_valid:1;/* sense len is valid */
-	u8         rsp_len_valid:1;/* response len is valid */
+	u8         sns_len_valid:1;	/* sense len is valid */
+	u8         rsp_len_valid:1;	/* response len is valid */
 #else
-	u8         rsp_len_valid:1;/* response len is valid */
-	u8         sns_len_valid:1;/* sense len is valid */
+	u8         rsp_len_valid:1;	/* response len is valid */
+	u8         sns_len_valid:1;	/* sense len is valid */
 	u8         resid_flags:2;	/* underflow/overflow */
 	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
 	u8         reserved3:3;
 #endif
-	u8         scsi_status;	/* one byte SCSI status */
-	u32        residue;	/* residual data bytes */
-	u32        sns_len;	/* length od sense info */
-	u32        rsp_len;	/* length of response info */
+	u8         scsi_status;		/* one byte SCSI status */
+	u32        residue;		/* residual data bytes */
+	u32        sns_len;		/* length od sense info */
+	u32        rsp_len;		/* length of response info */
 };
 
 #define fcp_snslen(__fcprsp)	((__fcprsp)->sns_len_valid ?		\
@@ -1300,12 +1156,6 @@
 #define fcp_rspinfo(__fcprsp)	((struct fcp_rspinfo_s *)((__fcprsp) + 1))
 #define fcp_snsinfo(__fcprsp)	(((u8 *)fcp_rspinfo(__fcprsp)) +	\
 						fcp_rsplen(__fcprsp))
-
-struct fcp_cmnd_fr_s {
-	struct fchs_s fchs;
-	struct fcp_cmnd_s fcp;
-};
-
 /*
  * CT
  */
@@ -1379,7 +1229,7 @@
 	CT_RSN_LOGICAL_BUSY	= 0x05,
 	CT_RSN_PROTO_ERR	= 0x07,
 	CT_RSN_UNABLE_TO_PERF	= 0x09,
-	CT_RSN_NOT_SUPP			= 0x0B,
+	CT_RSN_NOT_SUPP		= 0x0B,
 	CT_RSN_SERVER_NOT_AVBL  = 0x0D,
 	CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
 	CT_RSN_VENDOR_SPECIFIC  = 0xFF,
@@ -1419,10 +1269,10 @@
  * defintions for the explanation code for all servers
  */
 enum {
-	CT_EXP_AUTH_EXCEPTION			= 0xF1,
-	CT_EXP_DB_FULL					= 0xF2,
-	CT_EXP_DB_EMPTY					= 0xF3,
-	CT_EXP_PROCESSING_REQ			= 0xF4,
+	CT_EXP_AUTH_EXCEPTION		= 0xF1,
+	CT_EXP_DB_FULL			= 0xF2,
+	CT_EXP_DB_EMPTY			= 0xF3,
+	CT_EXP_PROCESSING_REQ		= 0xF4,
 	CT_EXP_UNABLE_TO_VERIFY_CONN	= 0xF5,
 	CT_EXP_DEVICES_NOT_IN_CMN_ZONE  = 0xF6
 };
@@ -1446,7 +1296,7 @@
 	GS_RFF_ID	= 0x021F,	/* Register FC4 Feature		*/
 };
 
-struct fcgs_id_req_s{
+struct fcgs_id_req_s {
 	u32 rsvd:8;
 	u32 dap:24; /* port identifier */
 };
@@ -1460,7 +1310,7 @@
 
 struct fcgs_gidpn_resp_s {
 	u32	rsvd:8;
-	u32	dap:24;	/* port identifier */
+	u32	dap:24;		/* port identifier */
 };
 
 /*
@@ -1469,22 +1319,21 @@
 struct fcgs_rftid_req_s {
 	u32	rsvd:8;
 	u32	dap:24;		/* port identifier */
-	u32	fc4_type[8];	/* fc4 types */
+	__be32	fc4_type[8];	/* fc4 types */
 };
 
 /*
  * RFF_ID : Register FC4 features.
  */
-
 #define FC_GS_FCP_FC4_FEATURE_INITIATOR  0x02
 #define FC_GS_FCP_FC4_FEATURE_TARGET	 0x01
 
 struct fcgs_rffid_req_s {
-    u32    rsvd:8;
-    u32    dap:24;		/* port identifier	*/
-    u32    rsvd1:16;
-    u32    fc4ftr_bits:8;		/* fc4 feature bits	*/
-    u32    fc4_type:8;		/* corresponding FC4 Type */
+	u32	rsvd:8;
+	u32	dap:24;		/* port identifier */
+	u32	rsvd1:16;
+	u32	fc4ftr_bits:8;	/* fc4 feature bits */
+	u32	fc4_type:8;		/* corresponding FC4 Type */
 };
 
 /*
@@ -1495,16 +1344,16 @@
 	u8	domain_id;	/* domain, 0 - all fabric */
 	u8	area_id;	/* area, 0 - whole domain */
 	u8	fc4_type;	/* FC_TYPE_FCP for SCSI devices */
-};		/* GID_FT Request */
+};
 
 /*
  * GID_FT Response
  */
 struct fcgs_gidft_resp_s {
-	u8		last:1;	/* last port identifier flag */
-	u8		reserved:7;
-	u32	pid:24;	/* port identifier */
-};		/* GID_FT Response */
+	u8	last:1;		/* last port identifier flag */
+	u8	reserved:7;
+	u32	pid:24;		/* port identifier */
+};
 
 /*
  * RSPN_ID
@@ -1512,8 +1361,8 @@
 struct fcgs_rspnid_req_s {
 	u32	rsvd:8;
 	u32	dap:24;		/* port identifier */
-	u8		spn_len;	/* symbolic port name length */
-	u8		spn[256];	/* symbolic port name */
+	u8	spn_len;	/* symbolic port name length */
+	u8	spn[256];	/* symbolic port name */
 };
 
 /*
@@ -1522,7 +1371,7 @@
 struct fcgs_rpnid_req_s {
 	u32	rsvd:8;
 	u32	port_id:24;
-	wwn_t		port_name;
+	wwn_t	port_name;
 };
 
 /*
@@ -1531,7 +1380,7 @@
 struct fcgs_rnnid_req_s {
 	u32	rsvd:8;
 	u32	port_id:24;
-	wwn_t		node_name;
+	wwn_t	node_name;
 };
 
 /*
@@ -1565,8 +1414,8 @@
  * GA_NXT Response
  */
 struct fcgs_ganxt_rsp_s {
-	u32	port_type:8;	/* Port Type */
-	u32	port_id:24;	/* Port Identifier */
+	u32		port_type:8;	/* Port Type */
+	u32		port_id:24;	/* Port Identifier */
 	wwn_t		port_name;	/* Port Name */
 	u8		spn_len;	/* Length of Symbolic Port Name */
 	char		spn[255];	/* Symbolic Port Name */
@@ -1575,19 +1424,14 @@
 	char		snn[255];	/* Symbolic Node Name */
 	u8		ipa[8];		/* Initial Process Associator */
 	u8		ip[16];		/* IP Address */
-	u32	cos;		/* Class of Service */
-	u32	fc4types[8];	/* FC-4 TYPEs */
-	wwn_t		fabric_port_name;
-					/* Fabric Port Name */
-	u32	rsvd:8;		/* Reserved */
-	u32	hard_addr:24;	/* Hard Address */
+	u32		cos;		/* Class of Service */
+	u32		fc4types[8];	/* FC-4 TYPEs */
+	wwn_t		fabric_port_name; /* Fabric Port Name */
+	u32		rsvd:8;		/* Reserved */
+	u32		hard_addr:24;	/* Hard Address */
 };
 
 /*
- * Fabric Config Server
- */
-
-/*
  * Command codes for Fabric Configuration Server
  */
 enum {
@@ -1598,159 +1442,9 @@
 };
 
 /*
- * Source or Destination Port Tags.
- */
-enum {
-	GS_FTRACE_TAG_NPORT_ID		= 1,
-	GS_FTRACE_TAG_NPORT_NAME	= 2,
-};
-
-/*
-* Port Value : Could be a Port id or wwn
- */
-union fcgs_port_val_u {
-	u32	nport_id;
-	wwn_t		nport_wwn;
-};
-
-#define GS_FTRACE_MAX_HOP_COUNT	20
-#define GS_FTRACE_REVISION	1
-
-/*
- * Ftrace Related Structures.
- */
-
-/*
- * STR (Switch Trace) Reject Reason Codes. From FC-SW.
- */
-enum {
-	GS_FTRACE_STR_CMD_COMPLETED_SUCC	= 0,
-	GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
-	GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
-	GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
-	GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
-	GS_FTRACE_STR_DST_PORT_NOT_FOUND,
-	GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
-	GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
-	GS_FTRACE_STR_NO_ADDL_EXPLN,
-	GS_FTRACE_STR_FABRIC_BUSY,
-	GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
-	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
-	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
-};
-
-/*
- * Ftrace Request
- */
-struct fcgs_ftrace_req_s {
-	u32	revision;
-	u16	src_port_tag;	/* Source Port tag */
-	u16	src_port_len;	/* Source Port len */
-	union fcgs_port_val_u src_port_val;	/* Source Port value */
-	u16	dst_port_tag;	/* Destination Port tag */
-	u16	dst_port_len;	/* Destination Port len */
-	union fcgs_port_val_u dst_port_val;	/* Destination Port value */
-	u32	token;
-	u8		vendor_id[8];	/* T10 Vendor Identifier */
-	u8		vendor_info[8];	/* Vendor specific Info */
-	u32	max_hop_cnt;	/* Max Hop Count */
-};
-
-/*
- * Path info structure
- */
-struct fcgs_ftrace_path_info_s {
-	wwn_t		switch_name;		/* Switch WWN */
-	u32	domain_id;
-	wwn_t		ingress_port_name;	/* Ingress ports wwn */
-	u32	ingress_phys_port_num;	/* Ingress ports physical port
-						 * number
-						 */
-	wwn_t		egress_port_name;	/* Ingress ports wwn */
-	u32	egress_phys_port_num;	/* Ingress ports physical port
-						 * number
-						 */
-};
-
-/*
- * Ftrace Acc Response
- */
-struct fcgs_ftrace_resp_s {
-	u32	revision;
-	u32	token;
-	u8		vendor_id[8];		/* T10 Vendor Identifier */
-	u8		vendor_info[8];		/* Vendor specific Info */
-	u32	str_rej_reason_code;	/* STR Reject Reason Code */
-	u32	num_path_info_entries;	/* No. of path info entries */
-	/*
-	 * path info entry/entries.
-	 */
-	struct fcgs_ftrace_path_info_s path_info[1];
-
-};
-
-/*
-* Fabric Config Server : FCPing
- */
-
-/*
- * FC Ping Request
- */
-struct fcgs_fcping_req_s {
-	u32	revision;
-	u16	port_tag;
-	u16	port_len;	/* Port len */
-	union fcgs_port_val_u port_val;	/* Port value */
-	u32	token;
-};
-
-/*
- * FC Ping Response
- */
-struct fcgs_fcping_resp_s {
-	u32	token;
-};
-
-/*
- * Command codes for zone server query.
- */
-enum {
-	ZS_GZME = 0x0124,	/* Get zone member extended */
-};
-
-/*
- * ZS GZME request
- */
-#define ZS_GZME_ZNAMELEN	32
-struct zs_gzme_req_s {
-	u8	znamelen;
-	u8	rsvd[3];
-	u8	zname[ZS_GZME_ZNAMELEN];
-};
-
-enum zs_mbr_type {
-	ZS_MBR_TYPE_PWWN	= 1,
-	ZS_MBR_TYPE_DOMPORT	= 2,
-	ZS_MBR_TYPE_PORTID	= 3,
-	ZS_MBR_TYPE_NWWN	= 4,
-};
-
-struct zs_mbr_wwn_s {
-	u8	mbr_type;
-	u8	rsvd[3];
-	wwn_t	wwn;
-};
-
-struct zs_query_resp_s {
-	u32	nmbrs;	/*  number of zone members */
-	struct zs_mbr_wwn_s	mbr[1];
-};
-
-/*
  * GMAL Command ( Get ( interconnect Element) Management Address List)
  * To retrieve the IP Address of a Switch.
  */
-
 #define CT_GMAL_RESP_PREFIX_TELNET	 "telnet://"
 #define CT_GMAL_RESP_PREFIX_HTTP	 "http://"
 
@@ -1764,7 +1458,7 @@
 
 /* Accept Response to GMAL */
 struct fcgs_gmal_resp_s {
-	u32	ms_len;   /* Num of entries */
+	__be32	ms_len;   /* Num of entries */
 	u8	ms_ma[256];
 };
 
@@ -1775,9 +1469,6 @@
 };
 
 /*
- * FDMI
- */
-/*
  * FDMI Command Codes
  */
 #define	FDMI_GRHL		0x0100
@@ -1856,8 +1547,8 @@
  * FDMI attribute
  */
 struct fdmi_attr_s {
-	u16        type;
-	u16        len;
+	__be16        type;
+	__be16        len;
 	u8         value[1];
 };
 
@@ -1865,7 +1556,7 @@
  * HBA Attribute Block
  */
 struct fdmi_hba_attr_s {
-	u32        attr_count;	/* # of attributes */
+	__be32        attr_count;	/* # of attributes */
 	struct fdmi_attr_s hba_attr;	/* n attributes */
 };
 
@@ -1873,15 +1564,15 @@
  * Registered Port List
  */
 struct fdmi_port_list_s {
-	u32        num_ports;	/* number Of Port Entries */
-	wwn_t           port_entry;	/* one or more */
+	__be32		num_ports;	/* number Of Port Entries */
+	wwn_t		port_entry;	/* one or more */
 };
 
 /*
  * Port Attribute Block
  */
 struct fdmi_port_attr_s {
-	u32        attr_count;	/* # of attributes */
+	__be32        attr_count;	/* # of attributes */
 	struct fdmi_attr_s port_attr;	/* n attributes */
 };
 
@@ -1889,7 +1580,7 @@
  * FDMI Register HBA Attributes
  */
 struct fdmi_rhba_s {
-	wwn_t           hba_id;		/* HBA Identifier */
+	wwn_t			hba_id;		/* HBA Identifier */
 	struct fdmi_port_list_s port_list;	/* Registered Port List */
 	struct fdmi_hba_attr_s hba_attr_blk;	/* HBA attribute block */
 };
@@ -1898,8 +1589,8 @@
  * FDMI Register Port
  */
 struct fdmi_rprt_s {
-	wwn_t           hba_id;		/* HBA Identifier */
-	wwn_t           port_name;	/* Port wwn */
+	wwn_t			hba_id;		/* HBA Identifier */
+	wwn_t			port_name;	/* Port wwn */
 	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
 };
 
@@ -1907,7 +1598,7 @@
  * FDMI Register Port Attributes
  */
 struct fdmi_rpa_s {
-	wwn_t           port_name;	/* port wwn */
+	wwn_t			port_name;	/* port wwn */
 	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
 };
 
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index 9c72531..b7e2534 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -18,16 +18,16 @@
  * fcbuild.c - FC link service frame building and parsing routines
  */
 
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 #include "bfa_fcbuild.h"
 
 /*
  * static build functions
  */
 static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-				 u16 ox_id);
+				 __be16 ox_id);
 static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-				 u16 ox_id);
+				 __be16 ox_id);
 static struct fchs_s fc_els_req_tmpl;
 static struct fchs_s fc_els_rsp_tmpl;
 static struct fchs_s fc_bls_req_tmpl;
@@ -48,7 +48,7 @@
 	fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
 	fc_els_req_tmpl.type = FC_TYPE_ELS;
 	fc_els_req_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
 			      FCTL_SI_XFER);
 	fc_els_req_tmpl.rx_id = FC_RXID_ANY;
 
@@ -59,7 +59,7 @@
 	fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
 	fc_els_rsp_tmpl.type = FC_TYPE_ELS;
 	fc_els_rsp_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
 			      FCTL_END_SEQ | FCTL_SI_XFER);
 	fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
 
@@ -68,7 +68,7 @@
 	 */
 	fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
 	fc_bls_req_tmpl.type = FC_TYPE_BLS;
-	fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
+	fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
 	fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
 
 	/*
@@ -78,7 +78,7 @@
 	fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
 	fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
 	fc_bls_rsp_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
+		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
 			      FCTL_END_SEQ | FCTL_SI_XFER);
 	fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
 
@@ -129,7 +129,7 @@
 	fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
 	fcp_fchs_tmpl.type = FC_TYPE_FCP;
 	fcp_fchs_tmpl.f_ctl =
-		bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
+		bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
 	fcp_fchs_tmpl.seq_id = 1;
 	fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
 }
@@ -143,7 +143,7 @@
 	fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
 	fchs->type = FC_TYPE_SERVICES;
 	fchs->f_ctl =
-		bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
+		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
 			      FCTL_SI_XFER);
 	fchs->rx_id = FC_RXID_ANY;
 	fchs->d_id = (d_id);
@@ -157,7 +157,7 @@
 }
 
 void
-fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
 {
 	memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
 	fchs->d_id = (d_id);
@@ -166,7 +166,7 @@
 }
 
 static void
-fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
 {
 	memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
 	fchs->d_id = d_id;
@@ -196,7 +196,7 @@
 }
 
 static void
-fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
+fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
 {
 	memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
 	fchs->d_id = d_id;
@@ -206,7 +206,7 @@
 
 static          u16
 fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		 u16 ox_id, wwn_t port_name, wwn_t node_name,
+		 __be16 ox_id, wwn_t port_name, wwn_t node_name,
 		 u16 pdu_size, u8 els_code)
 {
 	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
@@ -232,8 +232,8 @@
 		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
 	       u8 set_npiv, u8 set_auth, u16 local_bb_credits)
 {
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
-	u32	*vvl_info;
+	u32        d_id = bfa_hton3b(FC_FABRIC_PORT);
+	__be32	*vvl_info;
 
 	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
 
@@ -267,7 +267,7 @@
 
 u16
 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
-		   u16 ox_id, wwn_t port_name, wwn_t node_name,
+		   __be16 ox_id, wwn_t port_name, wwn_t node_name,
 		   u16 pdu_size, u16 local_bb_credits)
 {
 	u32        d_id = 0;
@@ -289,7 +289,7 @@
 fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
 		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
 {
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
+	u32        d_id = bfa_hton3b(FC_FABRIC_PORT);
 
 	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
 
@@ -392,7 +392,7 @@
 
 u16
 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		  u16 ox_id, enum bfa_lport_role role)
+		  __be16 ox_id, enum bfa_lport_role role)
 {
 	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
 
@@ -456,9 +456,9 @@
 	return sizeof(struct fc_logo_s);
 }
 
-static          u16
+static u16
 fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
-		 u32 s_id, u16 ox_id, wwn_t port_name,
+		 u32 s_id, __be16 ox_id, wwn_t port_name,
 		 wwn_t node_name, u8 els_code)
 {
 	memset(adisc, '\0', sizeof(struct fc_adisc_s));
@@ -480,7 +480,7 @@
 
 u16
 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
-		u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name)
+		u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)
 {
 	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
 				node_name, FC_ELS_ADISC);
@@ -488,7 +488,7 @@
 
 u16
 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
-		   u32 s_id, u16 ox_id, wwn_t port_name,
+		   u32 s_id, __be16 ox_id, wwn_t port_name,
 		   wwn_t node_name)
 {
 	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
@@ -592,7 +592,7 @@
 
 u16
 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		  u16 ox_id)
+		  __be16 ox_id)
 {
 	struct fc_els_cmd_s *acc = pld;
 
@@ -606,7 +606,7 @@
 
 u16
 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
-		u32 s_id, u16 ox_id, u8 reason_code,
+		u32 s_id, __be16 ox_id, u8 reason_code,
 		u8 reason_code_expl)
 {
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
@@ -622,7 +622,7 @@
 
 u16
 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
-		u32 s_id, u16 ox_id, u16 rx_id)
+		u32 s_id, __be16 ox_id, u16 rx_id)
 {
 	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
 
@@ -638,7 +638,7 @@
 
 u16
 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
-		u32 s_id, u16 ox_id)
+		u32 s_id, __be16 ox_id)
 {
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 	memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
@@ -666,7 +666,7 @@
 
 u16
 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
-		u32 d_id, u32 s_id, u16 ox_id, int num_pages)
+		u32 d_id, u32 s_id, __be16 ox_id, int num_pages)
 {
 	int             page;
 
@@ -690,7 +690,7 @@
 
 u16
 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
-		  u32 s_id, u16 ox_id, int num_pages)
+		  u32 s_id, __be16 ox_id, int num_pages)
 {
 	int             page;
 
@@ -728,7 +728,7 @@
 
 u16
 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
-		  u32 s_id, u16 ox_id, u32 data_format,
+		  u32 s_id, __be16 ox_id, u32 data_format,
 		  struct fc_rnid_common_id_data_s *common_id_data,
 		  struct fc_rnid_general_topology_data_s *gen_topo_data)
 {
@@ -770,10 +770,10 @@
 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
 		u32 s_id, u32 *pid_list, u16 npids)
 {
-	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id));
+	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));
 	int i = 0;
 
-	fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0);
+	fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);
 
 	memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
 
@@ -788,7 +788,7 @@
 
 u16
 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
-		u32 d_id, u32 s_id, u16 ox_id,
+		u32 d_id, u32 s_id, __be16 ox_id,
 		  struct fc_rpsc_speed_info_s *oper_speed)
 {
 	memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
@@ -807,11 +807,6 @@
 	return sizeof(struct fc_rpsc_acc_s);
 }
 
-/*
- * TBD -
- * . get rid of unnecessary memsets
- */
-
 u16
 fc_logo_rsp_parse(struct fchs_s *fchs, int len)
 {
@@ -995,7 +990,7 @@
 }
 
 u16
-fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,
 		u32 reason_code, u32 reason_expl)
 {
 	struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
@@ -1045,7 +1040,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
 	fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
@@ -1061,7 +1056,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
 	fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
@@ -1077,7 +1072,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
 	fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
@@ -1104,7 +1099,7 @@
 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
 		u8 set_br_reg, u32 s_id, u16 ox_id)
 {
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+	u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
 
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
 
@@ -1121,7 +1116,7 @@
 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
 		u32 s_id, u16 ox_id)
 {
-	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
+	u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
 	u16        payldlen;
 
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
@@ -1143,7 +1138,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
-	u32        type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        type_value, d_id = bfa_hton3b(FC_NAME_SERVER);
 	u8         index;
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1167,7 +1162,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
 	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
@@ -1187,7 +1182,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
-	u32         d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32         d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
 	fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
@@ -1209,7 +1204,7 @@
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rspnid_req_s *rspnid =
 			(struct fcgs_rspnid_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
 	fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
@@ -1229,7 +1224,7 @@
 
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 
@@ -1249,7 +1244,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
@@ -1267,7 +1262,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
@@ -1286,7 +1281,7 @@
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rcsid_req_s *rcsid =
 			(struct fcgs_rcsid_req_s *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
@@ -1304,7 +1299,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
@@ -1321,7 +1316,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
+	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
@@ -1341,7 +1336,7 @@
 {
 
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
-	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
@@ -1356,7 +1351,7 @@
 fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
 {
 	u8         index;
-	u32       *ptr = (u32 *) bit_mask;
+	__be32       *ptr = (__be32 *) bit_mask;
 	u32        type_value;
 
 	/*
@@ -1377,7 +1372,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
@@ -1397,7 +1392,7 @@
 {
 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
-	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
+	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
 	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index 73abd02..ece51ec 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -21,7 +21,7 @@
 #ifndef __FCBUILD_H__
 #define __FCBUILD_H__
 
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 #include "bfa_fc.h"
 #include "bfa_defs_fcs.h"
 
@@ -138,7 +138,7 @@
 			       u16 pdu_size);
 
 u16        fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
-				   u32 s_id, u16 ox_id,
+				   u32 s_id, __be16 ox_id,
 				   wwn_t port_name, wwn_t node_name,
 				   u16 pdu_size,
 				   u16 local_bb_credits);
@@ -186,7 +186,7 @@
 				   u16 pdu_size);
 
 u16        fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
-			u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name,
+			u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
 			       wwn_t node_name);
 
 enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
@@ -196,20 +196,20 @@
 				 wwn_t port_name, wwn_t node_name);
 
 u16        fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
-				   u32 d_id, u32 s_id, u16 ox_id,
+				   u32 d_id, u32 s_id, __be16 ox_id,
 				   wwn_t port_name, wwn_t node_name);
 u16        fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
-				u32 d_id, u32 s_id, u16 ox_id,
+				u32 d_id, u32 s_id, __be16 ox_id,
 				u8 reason_code, u8 reason_code_expl);
 u16        fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
-				u32 d_id, u32 s_id, u16 ox_id);
+				u32 d_id, u32 s_id, __be16 ox_id);
 u16        fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
 			      u32 s_id, u16 ox_id);
 
 enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
 
 u16        fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-				  u32 s_id, u16 ox_id,
+				  u32 s_id, __be16 ox_id,
 				  enum bfa_lport_role role);
 
 u16        fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
@@ -218,7 +218,7 @@
 
 u16        fc_rnid_acc_build(struct fchs_s *fchs,
 			struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id,
-			u16 ox_id, u32 data_format,
+			__be16 ox_id, u32 data_format,
 			struct fc_rnid_common_id_data_s *common_id_data,
 			struct fc_rnid_general_topology_data_s *gen_topo_data);
 
@@ -228,7 +228,7 @@
 			      u32 d_id, u32 s_id, u16 ox_id);
 u16        fc_rpsc_acc_build(struct fchs_s *fchs,
 			struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id,
-			u16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
+			__be16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
 u16        fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
 				u8 fc4_type);
 
@@ -251,7 +251,7 @@
 			      u32 s_id, u16 ox_id, wwn_t port_name);
 
 u16        fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-				  u32 s_id, u16 ox_id);
+				  u32 s_id, __be16 ox_id);
 
 u16        fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
 				     u16 cmd_code);
@@ -261,7 +261,7 @@
 void		fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
 
 void		fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-					 u16 ox_id);
+					 __be16 ox_id);
 
 enum fc_parse_status	fc_els_rsp_parse(struct fchs_s *fchs, int len);
 
@@ -274,15 +274,15 @@
 					wwn_t port_name);
 
 u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
-		u32 s_id, u16 ox_id, u16 rx_id);
+		u32 s_id, __be16 ox_id, u16 rx_id);
 
 int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
 
 u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
-		u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+		u32 d_id, u32 s_id, __be16 ox_id, int num_pages);
 
 u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
-		u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+		u32 d_id, u32 s_id, __be16 ox_id, int num_pages);
 
 u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
 
@@ -304,7 +304,7 @@
 u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
 
 u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-		u16 ox_id, u32 reason_code, u32 reason_expl);
+		__be16 ox_id, u32 reason_code, u32 reason_expl);
 
 u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 		u32 port_id);
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 135c442..9c410b2 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -15,17 +15,12 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_modules.h"
-#include "bfa_cb_ioim.h"
 
 BFA_TRC_FILE(HAL, FCPIM);
 BFA_MODULE(fcpim);
 
-
-#define bfa_fcpim_add_iostats(__l, __r, __stats)	\
-	(__l->__stats += __r->__stats)
-
-
 /*
  *  BFA ITNIM Related definitions
  */
@@ -37,12 +32,12 @@
 #define bfa_fcpim_additn(__itnim)					\
 	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
 #define bfa_fcpim_delitn(__itnim)	do {				\
-	bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \
+	WARN_ON(!bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));   \
 	bfa_itnim_update_del_itn_stats(__itnim);      \
 	list_del(&(__itnim)->qe);      \
-	bfa_assert(list_empty(&(__itnim)->io_q));      \
-	bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \
-	bfa_assert(list_empty(&(__itnim)->pending_q));      \
+	WARN_ON(!list_empty(&(__itnim)->io_q));				\
+	WARN_ON(!list_empty(&(__itnim)->io_cleanup_q));			\
+	WARN_ON(!list_empty(&(__itnim)->pending_q));			\
 } while (0)
 
 #define bfa_itnim_online_cb(__itnim) do {				\
@@ -73,10 +68,8 @@
 } while (0)
 
 /*
- *  bfa_itnim_sm BFA itnim state machine
+ *  itnim state machine event
  */
-
-
 enum bfa_itnim_event {
 	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */
 	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */
@@ -107,9 +100,6 @@
 	if ((__fcpim)->profile_start)					\
 		(__fcpim)->profile_start(__ioim);			\
 } while (0)
-/*
- *  hal_ioim_sm
- */
 
 /*
  * IO state machine events
@@ -221,8 +211,7 @@
  * forward declaration for BFA IOIM functions
  */
 static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
-static bfa_boolean_t	bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
-static void		bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
+static bfa_boolean_t	bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim);
 static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
 static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
 static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
@@ -232,7 +221,6 @@
 static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
 static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
 
-
 /*
  * forward declaration of BFA IO state machine
  */
@@ -260,14 +248,13 @@
 					enum bfa_ioim_event event);
 static void	bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,
 					enum bfa_ioim_event event);
-
 /*
  * forward declaration for BFA TSKIM functions
  */
 static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
 static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
 static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
-					lun_t lun);
+					struct scsi_lun lun);
 static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
 static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);
 static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
@@ -275,7 +262,6 @@
 static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
 static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
 
-
 /*
  * forward declaration of BFA TSKIM state machine
  */
@@ -293,13 +279,12 @@
 					enum bfa_tskim_event event);
 static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
 					enum bfa_tskim_event event);
-
 /*
- *  hal_fcpim_mod BFA FCP Initiator Mode module
+ *  BFA FCP Initiator Mode module
  */
 
 /*
- *	Compute and return memory needed by FCP(im) module.
+ * Compute and return memory needed by FCP(im) module.
  */
 static void
 bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
@@ -357,10 +342,6 @@
 static void
 bfa_fcpim_detach(struct bfa_s *bfa)
 {
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-
-	bfa_ioim_detach(fcpim);
-	bfa_tskim_detach(fcpim);
 }
 
 static void
@@ -387,56 +368,6 @@
 }
 
 void
-bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
-		struct bfa_itnim_iostats_s *rstats)
-{
-	bfa_fcpim_add_iostats(lstats, rstats, total_ios);
-	bfa_fcpim_add_iostats(lstats, rstats, qresumes);
-	bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
-	bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
-	bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
-	bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
-	bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
-	bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
-	bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
-	bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
-	bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
-	bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
-	bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
-	bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
-	bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
-	bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
-	bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
-	bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
-	bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
-	bfa_fcpim_add_iostats(lstats, rstats, onlines);
-	bfa_fcpim_add_iostats(lstats, rstats, offlines);
-	bfa_fcpim_add_iostats(lstats, rstats, creates);
-	bfa_fcpim_add_iostats(lstats, rstats, deletes);
-	bfa_fcpim_add_iostats(lstats, rstats, create_comps);
-	bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
-	bfa_fcpim_add_iostats(lstats, rstats, sler_events);
-	bfa_fcpim_add_iostats(lstats, rstats, fw_create);
-	bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
-	bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
-	bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_success);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
-	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
-	bfa_fcpim_add_iostats(lstats, rstats, io_comps);
-	bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
-	bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
-	bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
-	bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
-}
-
-void
 bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -454,128 +385,6 @@
 	return fcpim->path_tov / 1000;
 }
 
-bfa_status_t
-bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats,
-	u8 lp_tag)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct list_head *qe, *qen;
-	struct bfa_itnim_s *itnim;
-
-	/* accumulate IO stats from itnim */
-	memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
-	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
-		itnim = (struct bfa_itnim_s *) qe;
-		if (itnim->rport->rport_info.lp_tag != lp_tag)
-			continue;
-		bfa_fcpim_add_stats(stats, &(itnim->stats));
-	}
-	return BFA_STATUS_OK;
-}
-bfa_status_t
-bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *modstats)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct list_head *qe, *qen;
-	struct bfa_itnim_s *itnim;
-
-	/* accumulate IO stats from itnim */
-	memset(modstats, 0, sizeof(struct bfa_itnim_iostats_s));
-	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
-		itnim = (struct bfa_itnim_s *) qe;
-		bfa_fcpim_add_stats(modstats, &(itnim->stats));
-	}
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
-	 struct bfa_fcpim_del_itn_stats_s *modstats)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-
-	*modstats = fcpim->del_itn_stats;
-
-	return BFA_STATUS_OK;
-}
-
-
-bfa_status_t
-bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)
-{
-	struct bfa_itnim_s *itnim;
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct list_head *qe, *qen;
-
-	/* accumulate IO stats from itnim */
-	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
-		itnim = (struct bfa_itnim_s *) qe;
-		bfa_itnim_clear_stats(itnim);
-	}
-	fcpim->io_profile = BFA_TRUE;
-	fcpim->io_profile_start_time = time;
-	fcpim->profile_comp = bfa_ioim_profile_comp;
-	fcpim->profile_start = bfa_ioim_profile_start;
-
-	return BFA_STATUS_OK;
-}
-bfa_status_t
-bfa_fcpim_profile_off(struct bfa_s *bfa)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	fcpim->io_profile = BFA_FALSE;
-	fcpim->io_profile_start_time = 0;
-	fcpim->profile_comp = NULL;
-	fcpim->profile_start = NULL;
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct list_head *qe, *qen;
-	struct bfa_itnim_s *itnim;
-
-	/* clear IO stats from all active itnims */
-	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
-		itnim = (struct bfa_itnim_s *) qe;
-		if (itnim->rport->rport_info.lp_tag != lp_tag)
-			continue;
-		bfa_itnim_clear_stats(itnim);
-	}
-	return BFA_STATUS_OK;
-
-}
-
-bfa_status_t
-bfa_fcpim_clr_modstats(struct bfa_s *bfa)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct list_head *qe, *qen;
-	struct bfa_itnim_s *itnim;
-
-	/* clear IO stats from all active itnims */
-	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
-		itnim = (struct bfa_itnim_s *) qe;
-		bfa_itnim_clear_stats(itnim);
-	}
-	memset(&fcpim->del_itn_stats, 0,
-		sizeof(struct bfa_fcpim_del_itn_stats_s));
-
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-
-	bfa_assert(q_depth <= BFA_IOCFC_QDEPTH_MAX);
-
-	fcpim->q_depth = q_depth;
-}
-
 u16
 bfa_fcpim_qdepth_get(struct bfa_s *bfa)
 {
@@ -584,32 +393,12 @@
 	return fcpim->q_depth;
 }
 
-void
-bfa_fcpim_update_ioredirect(struct bfa_s *bfa)
-{
-	bfa_boolean_t ioredirect;
-
-	/*
-	 * IO redirection is turned off when QoS is enabled and vice versa
-	 */
-	ioredirect = bfa_fcport_is_qos_enabled(bfa) ? BFA_FALSE : BFA_TRUE;
-}
-
-void
-bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	fcpim->ioredirect = state;
-}
-
-
-
 /*
  *  BFA ITNIM module state machine functions
  */
 
 /*
- *	Beginning/unallocated state - no events expected.
+ * Beginning/unallocated state - no events expected.
  */
 static void
 bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -630,7 +419,7 @@
 }
 
 /*
- *	Beginning state, only online event expected.
+ * Beginning state, only online event expected.
  */
 static void
 bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -733,7 +522,7 @@
 }
 
 /*
- *	Waiting for itnim create response from firmware, a delete is pending.
+ * Waiting for itnim create response from firmware, a delete is pending.
  */
 static void
 bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
@@ -761,7 +550,7 @@
 }
 
 /*
- *	Online state - normal parking state.
+ * Online state - normal parking state.
  */
 static void
 bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -803,7 +592,7 @@
 }
 
 /*
- *	Second level error recovery need.
+ * Second level error recovery need.
  */
 static void
 bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -834,7 +623,7 @@
 }
 
 /*
- *	Going offline. Waiting for active IO cleanup.
+ * Going offline. Waiting for active IO cleanup.
  */
 static void
 bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
@@ -871,7 +660,7 @@
 }
 
 /*
- *	Deleting itnim. Waiting for active IO cleanup.
+ * Deleting itnim. Waiting for active IO cleanup.
  */
 static void
 bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
@@ -956,7 +745,7 @@
 }
 
 /*
- *	Offline state.
+ * Offline state.
  */
 static void
 bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -987,9 +776,6 @@
 	}
 }
 
-/*
- *	IOC h/w failed state.
- */
 static void
 bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
 				enum bfa_itnim_event event)
@@ -1024,7 +810,7 @@
 }
 
 /*
- *	Itnim is deleted, waiting for firmware response to delete.
+ * Itnim is deleted, waiting for firmware response to delete.
  */
 static void
 bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
@@ -1069,7 +855,7 @@
 }
 
 /*
- *	Initiate cleanup of all IOs on an IOC failure.
+ * Initiate cleanup of all IOs on an IOC failure.
  */
 static void
 bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
@@ -1103,7 +889,7 @@
 }
 
 /*
- *	IO cleanup completion
+ * IO cleanup completion
  */
 static void
 bfa_itnim_cleanp_comp(void *itnim_cbarg)
@@ -1115,7 +901,7 @@
 }
 
 /*
- *	Initiate cleanup of all IOs.
+ * Initiate cleanup of all IOs.
  */
 static void
 bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
@@ -1187,9 +973,6 @@
 	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
 }
 
-
-
-
 /*
  *  bfa_itnim_public
  */
@@ -1401,7 +1184,7 @@
 	if (itnim->fcpim->path_tov > 0) {
 
 		itnim->iotov_active = BFA_TRUE;
-		bfa_assert(bfa_itnim_hold_io(itnim));
+		WARN_ON(!bfa_itnim_hold_io(itnim));
 		bfa_timer_start(itnim->bfa, &itnim->timer,
 			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
 	}
@@ -1457,14 +1240,12 @@
 	fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;
 }
 
-
-
 /*
- *  bfa_itnim_public
+ * bfa_itnim_public
  */
 
 /*
- *	Itnim interrupt processing.
+ * Itnim interrupt processing.
  */
 void
 bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
@@ -1481,7 +1262,7 @@
 	case BFI_ITNIM_I2H_CREATE_RSP:
 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
 						msg.create_rsp->bfa_handle);
-		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
 		bfa_stats(itnim, create_comps);
 		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
 		break;
@@ -1489,7 +1270,7 @@
 	case BFI_ITNIM_I2H_DELETE_RSP:
 		itnim = BFA_ITNIM_FROM_TAG(fcpim,
 						msg.delete_rsp->bfa_handle);
-		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
 		bfa_stats(itnim, delete_comps);
 		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
 		break;
@@ -1503,14 +1284,12 @@
 
 	default:
 		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
-
-
 /*
- *  bfa_itnim_api
+ * bfa_itnim_api
  */
 
 struct bfa_itnim_s *
@@ -1520,7 +1299,7 @@
 	struct bfa_itnim_s *itnim;
 
 	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
-	bfa_assert(itnim->rport == rport);
+	WARN_ON(itnim->rport != rport);
 
 	itnim->ditn = ditn;
 
@@ -1568,31 +1347,6 @@
 		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));
 }
 
-bfa_status_t
-bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
-		struct bfa_itnim_ioprofile_s *ioprofile)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
-	if (!fcpim->io_profile)
-		return BFA_STATUS_IOPROFILE_OFF;
-
-	itnim->ioprofile.index = BFA_IOBUCKET_MAX;
-	itnim->ioprofile.io_profile_start_time =
-		bfa_io_profile_start_time(itnim->bfa);
-	itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
-	itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
-	*ioprofile = itnim->ioprofile;
-
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
-	struct bfa_itnim_iostats_s *stats)
-{
-	*stats = itnim->stats;
-}
-
 void
 bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
 {
@@ -1608,14 +1362,11 @@
  */
 
 /*
- *	IO is not started (unallocated).
+ * IO is not started (unallocated).
  */
 static void
 bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
 {
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
 	switch (event) {
 	case BFA_IOIM_SM_START:
 		if (!bfa_itnim_is_online(ioim->itnim)) {
@@ -1635,7 +1386,7 @@
 		}
 
 		if (ioim->nsges > BFI_SGE_INLINE) {
-			if (!bfa_ioim_sge_setup(ioim)) {
+			if (!bfa_ioim_sgpg_alloc(ioim)) {
 				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
 				return;
 			}
@@ -1662,7 +1413,7 @@
 		 * requests immediately.
 		 */
 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
+		WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
 		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
 				__bfa_cb_ioim_abort, ioim);
 		break;
@@ -1673,7 +1424,7 @@
 }
 
 /*
- *	IO is waiting for SG pages.
+ * IO is waiting for SG pages.
  */
 static void
 bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -1720,14 +1471,11 @@
 }
 
 /*
- *	IO is active.
+ * IO is active.
  */
 static void
 bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
 {
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
 	switch (event) {
 	case BFA_IOIM_SM_COMP_GOOD:
 		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
@@ -1786,8 +1534,8 @@
 		break;
 
 	case BFA_IOIM_SM_SQRETRY:
-		if (bfa_ioim_get_iotag(ioim) != BFA_TRUE) {
-			/* max retry completed free IO */
+		if (bfa_ioim_maxretry_reached(ioim)) {
+			/* max retry reached, free IO */
 			bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
 			bfa_ioim_move_to_comp_q(ioim);
 			bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
@@ -1804,17 +1552,15 @@
 }
 
 /*
-*	IO is retried with new tag.
-*/
+ * IO is retried with new tag.
+ */
 static void
 bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
 {
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
 	switch (event) {
 	case BFA_IOIM_SM_FREE:
 		/* abts and rrq done. Now retry the IO with new tag */
+		bfa_ioim_update_iotag(ioim);
 		if (!bfa_ioim_send_ioreq(ioim)) {
 			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
 			break;
@@ -1858,7 +1604,7 @@
 }
 
 /*
- *	IO is being aborted, waiting for completion from firmware.
+ * IO is being aborted, waiting for completion from firmware.
  */
 static void
 bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -1894,7 +1640,7 @@
 		break;
 
 	case BFA_IOIM_SM_CLEANUP:
-		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);
 		ioim->iosp->abort_explicit = BFA_FALSE;
 
 		if (bfa_ioim_send_abort(ioim))
@@ -1981,7 +1727,7 @@
 }
 
 /*
- *	IO is waiting for room in request CQ
+ * IO is waiting for room in request CQ
  */
 static void
 bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -2025,7 +1771,7 @@
 }
 
 /*
- *	Active IO is being aborted, waiting for room in request CQ.
+ * Active IO is being aborted, waiting for room in request CQ.
  */
 static void
 bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -2040,7 +1786,7 @@
 		break;
 
 	case BFA_IOIM_SM_CLEANUP:
-		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+		WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE);
 		ioim->iosp->abort_explicit = BFA_FALSE;
 		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
 		break;
@@ -2076,7 +1822,7 @@
 }
 
 /*
- *	Active IO is being cleaned up, waiting for room in request CQ.
+ * Active IO is being cleaned up, waiting for room in request CQ.
  */
 static void
 bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
@@ -2131,9 +1877,6 @@
 static void
 bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
 {
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
 	switch (event) {
 	case BFA_IOIM_SM_HCB:
 		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
@@ -2213,11 +1956,6 @@
 }
 
 
-
-/*
- *  hal_ioim_private
- */
-
 static void
 __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
 {
@@ -2323,7 +2061,7 @@
 
 	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
 	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
-	bfa_ioim_sgpg_setup(ioim);
+	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);
 	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
 }
 
@@ -2335,13 +2073,16 @@
 {
 	struct bfa_itnim_s *itnim = ioim->itnim;
 	struct bfi_ioim_req_s *m;
-	static struct fcp_cmnd_s cmnd_z0 = { 0 };
-	struct bfi_sge_s      *sge;
+	static struct fcp_cmnd_s cmnd_z0 = { { { 0 } } };
+	struct bfi_sge_s *sge, *sgpge;
 	u32	pgdlen = 0;
 	u32	fcp_dl;
 	u64 addr;
 	struct scatterlist *sg;
+	struct bfa_sgpg_s *sgpg;
 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+	u32 i, sge_id, pgcumsz;
+	enum dma_data_direction dmadir;
 
 	/*
 	 * check for room in queue to send request now
@@ -2359,22 +2100,61 @@
 	 */
 	m->io_tag = cpu_to_be16(ioim->iotag);
 	m->rport_hdl = ioim->itnim->rport->fw_handle;
-	m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
+	m->io_timeout = 0;
 
-	/*
-	 * build inline IO SG element here
-	 */
 	sge = &m->sges[0];
-	if (ioim->nsges) {
-		sg = (struct scatterlist *)scsi_sglist(cmnd);
-		addr = bfa_os_sgaddr(sg_dma_address(sg));
-		sge->sga = *(union bfi_addr_u *) &addr;
-		pgdlen = sg_dma_len(sg);
-		sge->sg_len = pgdlen;
-		sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
+	sgpg = ioim->sgpg;
+	sge_id = 0;
+	sgpge = NULL;
+	pgcumsz = 0;
+	scsi_for_each_sg(cmnd, sg, ioim->nsges, i) {
+		if (i == 0) {
+			/* build inline IO SG element */
+			addr = bfa_sgaddr_le(sg_dma_address(sg));
+			sge->sga = *(union bfi_addr_u *) &addr;
+			pgdlen = sg_dma_len(sg);
+			sge->sg_len = pgdlen;
+			sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
 					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
-		bfa_sge_to_be(sge);
-		sge++;
+			bfa_sge_to_be(sge);
+			sge++;
+		} else {
+			if (sge_id == 0)
+				sgpge = sgpg->sgpg->sges;
+
+			addr = bfa_sgaddr_le(sg_dma_address(sg));
+			sgpge->sga = *(union bfi_addr_u *) &addr;
+			sgpge->sg_len = sg_dma_len(sg);
+			pgcumsz += sgpge->sg_len;
+
+			/* set flags */
+			if (i < (ioim->nsges - 1) &&
+					sge_id < (BFI_SGPG_DATA_SGES - 1))
+				sgpge->flags = BFI_SGE_DATA;
+			else if (i < (ioim->nsges - 1))
+				sgpge->flags = BFI_SGE_DATA_CPL;
+			else
+				sgpge->flags = BFI_SGE_DATA_LAST;
+
+			bfa_sge_to_le(sgpge);
+
+			sgpge++;
+			if (i == (ioim->nsges - 1)) {
+				sgpge->flags = BFI_SGE_PGDLEN;
+				sgpge->sga.a32.addr_lo = 0;
+				sgpge->sga.a32.addr_hi = 0;
+				sgpge->sg_len = pgcumsz;
+				bfa_sge_to_le(sgpge);
+			} else if (++sge_id == BFI_SGPG_DATA_SGES) {
+				sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
+				sgpge->flags = BFI_SGE_LINK;
+				sgpge->sga = sgpg->sgpg_pa;
+				sgpge->sg_len = pgcumsz;
+				bfa_sge_to_le(sgpge);
+				sge_id = 0;
+				pgcumsz = 0;
+			}
+		}
 	}
 
 	if (ioim->nsges > BFI_SGE_INLINE) {
@@ -2391,10 +2171,17 @@
 	 * set up I/O command parameters
 	 */
 	m->cmnd = cmnd_z0;
-	m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
-	m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
-	m->cmnd.cdb = *(scsi_cdb_t *)bfa_cb_ioim_get_cdb(ioim->dio);
-	fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+	int_to_scsilun(cmnd->device->lun, &m->cmnd.lun);
+	dmadir = cmnd->sc_data_direction;
+	if (dmadir == DMA_TO_DEVICE)
+		m->cmnd.iodir = FCP_IODIR_WRITE;
+	else if (dmadir == DMA_FROM_DEVICE)
+		m->cmnd.iodir = FCP_IODIR_READ;
+	else
+		m->cmnd.iodir = FCP_IODIR_NONE;
+
+	m->cmnd.cdb = *(struct scsi_cdb_s *) cmnd->cmnd;
+	fcp_dl = scsi_bufflen(cmnd);
 	m->cmnd.fcp_dl = cpu_to_be32(fcp_dl);
 
 	/*
@@ -2418,28 +2205,9 @@
 		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
 	}
 	if (itnim->seq_rec ||
-	    (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
+	    (scsi_bufflen(cmnd) & (sizeof(u32) - 1)))
 		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
 
-#ifdef IOIM_ADVANCED
-	m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
-	m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
-	m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
-
-	/*
-	 * Handle large CDB (>16 bytes).
-	 */
-	m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
-					FCP_CMND_CDB_LEN) / sizeof(u32);
-	if (m->cmnd.addl_cdb_len) {
-		memcpy(&m->cmnd.cdb + 1, (scsi_cdb_t *)
-				bfa_cb_ioim_get_cdb(ioim->dio) + 1,
-				m->cmnd.addl_cdb_len * sizeof(u32));
-		fcp_cmnd_fcpdl(&m->cmnd) =
-				cpu_to_be32(bfa_cb_ioim_get_size(ioim->dio));
-	}
-#endif
-
 	/*
 	 * queue I/O message to firmware
 	 */
@@ -2452,11 +2220,11 @@
  * at queuing time.
  */
 static bfa_boolean_t
-bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
+bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim)
 {
 	u16	nsgpgs;
 
-	bfa_assert(ioim->nsges > BFI_SGE_INLINE);
+	WARN_ON(ioim->nsges <= BFI_SGE_INLINE);
 
 	/*
 	 * allocate SG pages needed
@@ -2472,73 +2240,11 @@
 	}
 
 	ioim->nsgpgs = nsgpgs;
-	bfa_ioim_sgpg_setup(ioim);
+	ioim->sgpg = bfa_q_first(&ioim->sgpg_q);
 
 	return BFA_TRUE;
 }
 
-static void
-bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
-{
-	int		sgeid, nsges, i;
-	struct bfi_sge_s      *sge;
-	struct bfa_sgpg_s *sgpg;
-	u32	pgcumsz;
-	u64        addr;
-	struct scatterlist *sg;
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
-	sgeid = BFI_SGE_INLINE;
-	ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
-
-	sg = scsi_sglist(cmnd);
-	sg = sg_next(sg);
-
-	do {
-		sge = sgpg->sgpg->sges;
-		nsges = ioim->nsges - sgeid;
-		if (nsges > BFI_SGPG_DATA_SGES)
-			nsges = BFI_SGPG_DATA_SGES;
-
-		pgcumsz = 0;
-		for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
-			addr = bfa_os_sgaddr(sg_dma_address(sg));
-			sge->sga = *(union bfi_addr_u *) &addr;
-			sge->sg_len = sg_dma_len(sg);
-			pgcumsz += sge->sg_len;
-
-			/*
-			 * set flags
-			 */
-			if (i < (nsges - 1))
-				sge->flags = BFI_SGE_DATA;
-			else if (sgeid < (ioim->nsges - 1))
-				sge->flags = BFI_SGE_DATA_CPL;
-			else
-				sge->flags = BFI_SGE_DATA_LAST;
-
-			bfa_sge_to_le(sge);
-		}
-
-		sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
-
-		/*
-		 * set the link element of each page
-		 */
-		if (sgeid == ioim->nsges) {
-			sge->flags = BFI_SGE_PGDLEN;
-			sge->sga.a32.addr_lo = 0;
-			sge->sga.a32.addr_hi = 0;
-		} else {
-			sge->flags = BFI_SGE_LINK;
-			sge->sga = sgpg->sgpg_pa;
-		}
-		sge->sg_len = pgcumsz;
-
-		bfa_sge_to_le(sge);
-	} while (sgeid < ioim->nsges);
-}
-
 /*
  * Send I/O abort request to firmware.
  */
@@ -2605,7 +2311,7 @@
 		}
 		bfa_itnim_iodone(ioim->itnim);
 	} else
-		bfa_tskim_iodone(ioim->iosp->tskim);
+		bfa_wc_down(&ioim->iosp->tskim->wc);
 }
 
 static bfa_boolean_t
@@ -2623,9 +2329,6 @@
 	return BFA_TRUE;
 }
 
-/*
- *	or after the link comes back.
- */
 void
 bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
 {
@@ -2653,11 +2356,6 @@
 }
 
 
-
-/*
- *  hal_ioim_friend
- */
-
 /*
  * Memory allocation and initialization.
  */
@@ -2722,14 +2420,6 @@
 	}
 }
 
-/*
- * Driver detach time call.
- */
-void
-bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-}
-
 void
 bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
@@ -2742,7 +2432,7 @@
 	iotag = be16_to_cpu(rsp->io_tag);
 
 	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
-	bfa_assert(ioim->iotag == iotag);
+	WARN_ON(ioim->iotag != iotag);
 
 	bfa_trc(ioim->bfa, ioim->iotag);
 	bfa_trc(ioim->bfa, rsp->io_status);
@@ -2773,13 +2463,13 @@
 
 	case BFI_IOIM_STS_PROTO_ERR:
 		bfa_stats(ioim->itnim, iocom_proto_err);
-		bfa_assert(rsp->reuse_io_tag);
+		WARN_ON(!rsp->reuse_io_tag);
 		evt = BFA_IOIM_SM_COMP;
 		break;
 
 	case BFI_IOIM_STS_SQER_NEEDED:
 		bfa_stats(ioim->itnim, iocom_sqer_needed);
-		bfa_assert(rsp->reuse_io_tag == 0);
+		WARN_ON(rsp->reuse_io_tag != 0);
 		evt = BFA_IOIM_SM_SQRETRY;
 		break;
 
@@ -2808,7 +2498,7 @@
 		break;
 
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 
 	bfa_sm_send_event(ioim, evt);
@@ -2825,39 +2515,12 @@
 	iotag = be16_to_cpu(rsp->io_tag);
 
 	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
-	bfa_assert(ioim->iotag == iotag);
+	WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag);
 
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
 	bfa_ioim_cb_profile_comp(fcpim, ioim);
-
 	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
 }
 
-void
-bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
-{
-	ioim->start_time = jiffies;
-}
-
-void
-bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
-{
-	u32 fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
-	u32 index = bfa_ioim_get_index(fcp_dl);
-	u64 end_time = jiffies;
-	struct bfa_itnim_latency_s *io_lat =
-			&(ioim->itnim->ioprofile.io_latency);
-	u32 val = (u32)(end_time - ioim->start_time);
-
-	bfa_itnim_ioprofile_update(ioim->itnim, index);
-
-	io_lat->count[index]++;
-	io_lat->min[index] = (io_lat->min[index] < val) ?
-		io_lat->min[index] : val;
-	io_lat->max[index] = (io_lat->max[index] > val) ?
-		io_lat->max[index] : val;
-	io_lat->avg[index] += val;
-}
 /*
  * Called by itnim to clean up IO while going offline.
  */
@@ -2903,11 +2566,6 @@
 }
 
 
-
-/*
- *  hal_ioim_api
- */
-
 /*
  * Allocate IOIM resource for initiator mode I/O request.
  */
@@ -2936,7 +2594,6 @@
 	fcpim->ios_active++;
 
 	list_add_tail(&ioim->qe, &itnim->io_q);
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
 
 	return ioim;
 }
@@ -2946,18 +2603,13 @@
 {
 	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
 
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
-
-	bfa_assert_fp(list_empty(&ioim->sgpg_q) ||
-			(ioim->nsges > BFI_SGE_INLINE));
-
 	if (ioim->nsgpgs > 0)
 		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
 
 	bfa_stats(ioim->itnim, io_comps);
 	fcpim->ios_active--;
 
+	ioim->iotag &= BFA_IOIM_IOTAG_MASK;
 	list_del(&ioim->qe);
 	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
 }
@@ -2965,16 +2617,13 @@
 void
 bfa_ioim_start(struct bfa_ioim_s *ioim)
 {
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-
 	bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
 
 	/*
 	 * Obtain the queue over which this request has to be issued
 	 */
 	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
-			bfa_cb_ioim_get_reqq(ioim->dio) :
-			bfa_itnim_get_reqq(ioim);
+			BFA_FALSE : bfa_itnim_get_reqq(ioim);
 
 	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
 }
@@ -2997,13 +2646,12 @@
 	return BFA_STATUS_OK;
 }
 
-
 /*
  *  BFA TSKIM state machine functions
  */
 
 /*
- *	Task management command beginning state.
+ * Task management command beginning state.
  */
 static void
 bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3040,9 +2688,8 @@
 }
 
 /*
- * brief
- *	TM command is active, awaiting completion from firmware to
- *	cleanup IO requests in TM scope.
+ * TM command is active, awaiting completion from firmware to
+ * cleanup IO requests in TM scope.
  */
 static void
 bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3077,8 +2724,8 @@
 }
 
 /*
- *	An active TM is being cleaned up since ITN is offline. Awaiting cleanup
- *	completion event from firmware.
+ * An active TM is being cleaned up since ITN is offline. Awaiting cleanup
+ * completion event from firmware.
  */
 static void
 bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3138,7 +2785,7 @@
 }
 
 /*
- *	Task management command is waiting for room in request CQ
+ * Task management command is waiting for room in request CQ
  */
 static void
 bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3173,8 +2820,8 @@
 }
 
 /*
- *	Task management command is active, awaiting for room in request CQ
- *	to send clean up request.
+ * Task management command is active, awaiting for room in request CQ
+ * to send clean up request.
  */
 static void
 bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
@@ -3186,10 +2833,8 @@
 	case BFA_TSKIM_SM_DONE:
 		bfa_reqq_wcancel(&tskim->reqq_wait);
 		/*
-		 *
 		 * Fall through !!!
 		 */
-
 	case BFA_TSKIM_SM_QRESUME:
 		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
 		bfa_tskim_send_abort(tskim);
@@ -3208,7 +2853,7 @@
 }
 
 /*
- *	BFA callback is pending
+ * BFA callback is pending
  */
 static void
 bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
@@ -3233,12 +2878,6 @@
 	}
 }
 
-
-
-/*
- *  hal_tskim_private
- */
-
 static void
 __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
 {
@@ -3268,8 +2907,8 @@
 				BFI_TSKIM_STS_FAILED);
 }
 
-static	bfa_boolean_t
-bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
+static bfa_boolean_t
+bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun)
 {
 	switch (tskim->tm_cmnd) {
 	case FCP_TM_TARGET_RESET:
@@ -3279,24 +2918,26 @@
 	case FCP_TM_CLEAR_TASK_SET:
 	case FCP_TM_LUN_RESET:
 	case FCP_TM_CLEAR_ACA:
-		return (tskim->lun == lun);
+		return !memcmp(&tskim->lun, &lun, sizeof(lun));
 
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 
 	return BFA_FALSE;
 }
 
 /*
- *	Gather affected IO requests and task management commands.
+ * Gather affected IO requests and task management commands.
  */
 static void
 bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
 {
 	struct bfa_itnim_s *itnim = tskim->itnim;
 	struct bfa_ioim_s *ioim;
-	struct list_head	*qe, *qen;
+	struct list_head *qe, *qen;
+	struct scsi_cmnd *cmnd;
+	struct scsi_lun scsilun;
 
 	INIT_LIST_HEAD(&tskim->io_q);
 
@@ -3305,8 +2946,9 @@
 	 */
 	list_for_each_safe(qe, qen, &itnim->io_q) {
 		ioim = (struct bfa_ioim_s *) qe;
-		if (bfa_tskim_match_scope
-			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+		cmnd = (struct scsi_cmnd *) ioim->dio;
+		int_to_scsilun(cmnd->device->lun, &scsilun);
+		if (bfa_tskim_match_scope(tskim, scsilun)) {
 			list_del(&ioim->qe);
 			list_add_tail(&ioim->qe, &tskim->io_q);
 		}
@@ -3317,8 +2959,9 @@
 	 */
 	list_for_each_safe(qe, qen, &itnim->pending_q) {
 		ioim = (struct bfa_ioim_s *) qe;
-		if (bfa_tskim_match_scope
-			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+		cmnd = (struct scsi_cmnd *) ioim->dio;
+		int_to_scsilun(cmnd->device->lun, &scsilun);
+		if (bfa_tskim_match_scope(tskim, scsilun)) {
 			list_del(&ioim->qe);
 			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
 			bfa_ioim_tov(ioim);
@@ -3327,7 +2970,7 @@
 }
 
 /*
- *	IO cleanup completion
+ * IO cleanup completion
  */
 static void
 bfa_tskim_cleanp_comp(void *tskim_cbarg)
@@ -3339,7 +2982,7 @@
 }
 
 /*
- *	Gather affected IO requests and task management commands.
+ * Gather affected IO requests and task management commands.
  */
 static void
 bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
@@ -3359,7 +3002,7 @@
 }
 
 /*
- *	Send task management request to firmware.
+ * Send task management request to firmware.
  */
 static bfa_boolean_t
 bfa_tskim_send(struct bfa_tskim_s *tskim)
@@ -3394,7 +3037,7 @@
 }
 
 /*
- *	Send abort request to cleanup an active TM to firmware.
+ * Send abort request to cleanup an active TM to firmware.
  */
 static bfa_boolean_t
 bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
@@ -3425,7 +3068,7 @@
 }
 
 /*
- *	Call to resume task management cmnd waiting for room in request queue.
+ * Call to resume task management cmnd waiting for room in request queue.
  */
 static void
 bfa_tskim_qresume(void *cbarg)
@@ -3451,12 +3094,6 @@
 	}
 }
 
-
-
-/*
- *  hal_tskim_friend
- */
-
 /*
  * Notification on completions from related ioim.
  */
@@ -3489,7 +3126,7 @@
 }
 
 /*
- *	Memory allocation and initialization.
+ * Memory allocation and initialization.
  */
 void
 bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
@@ -3522,14 +3159,6 @@
 }
 
 void
-bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-	/*
-	* @todo
-	*/
-}
-
-void
 bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -3538,7 +3167,7 @@
 	u16	tsk_tag = be16_to_cpu(rsp->tsk_tag);
 
 	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
-	bfa_assert(tskim->tsk_tag == tsk_tag);
+	WARN_ON(tskim->tsk_tag != tsk_tag);
 
 	tskim->tsk_status = rsp->tsk_status;
 
@@ -3556,12 +3185,6 @@
 }
 
 
-
-/*
- *  hal_tskim_api
- */
-
-
 struct bfa_tskim_s *
 bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
 {
@@ -3579,13 +3202,13 @@
 void
 bfa_tskim_free(struct bfa_tskim_s *tskim)
 {
-	bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
+	WARN_ON(!bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
 	list_del(&tskim->qe);
 	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
 }
 
 /*
- *	Start a task management command.
+ * Start a task management command.
  *
  * @param[in]	tskim	BFA task management command instance
  * @param[in]	itnim	i-t nexus for the task management command
@@ -3596,7 +3219,8 @@
  * @return None.
  */
 void
-bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
+bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim,
+			struct scsi_lun lun,
 			enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
 {
 	tskim->itnim	= itnim;
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index db53717..1e38dad 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -41,7 +41,7 @@
 	(__itnim->ioprofile.iocomps[__index]++)
 
 #define BFA_IOIM_RETRY_TAG_OFFSET 11
-#define BFA_IOIM_RETRY_TAG_MASK 0x07ff /* 2K IOs */
+#define BFA_IOIM_IOTAG_MASK 0x07ff /* 2K IOs */
 #define BFA_IOIM_RETRY_MAX 7
 
 /* Buckets are are 512 bytes to 2MB */
@@ -94,12 +94,12 @@
 	struct list_head	ioim_resfree_q; /*  IOs waiting for f/w */
 	struct list_head	ioim_comp_q;	/*  IO global comp Q	*/
 	struct list_head	tskim_free_q;
-	u32		ios_active;	/*  current active IOs	*/
-	u32		delay_comp;
+	u32			ios_active;	/*  current active IOs	*/
+	u32			delay_comp;
 	struct bfa_fcpim_del_itn_stats_s del_itn_stats;
 	bfa_boolean_t		ioredirect;
 	bfa_boolean_t		io_profile;
-	u32		io_profile_start_time;
+	u32			io_profile_start_time;
 	bfa_fcpim_profile_t     profile_comp;
 	bfa_fcpim_profile_t     profile_start;
 };
@@ -114,25 +114,24 @@
 	struct bfa_fcpim_mod_s	*fcpim;		/*  parent fcpim module */
 	struct bfa_itnim_s	*itnim;		/*  i-t-n nexus for this IO  */
 	struct bfad_ioim_s	*dio;		/*  driver IO handle	*/
-	u16		iotag;		/*  FWI IO tag	*/
-	u16		abort_tag;	/*  unqiue abort request tag */
-	u16		nsges;		/*  number of SG elements */
-	u16		nsgpgs;		/*  number of SG pages	*/
+	u16			iotag;		/*  FWI IO tag	*/
+	u16			abort_tag;	/*  unqiue abort request tag */
+	u16			nsges;		/*  number of SG elements */
+	u16			nsgpgs;		/*  number of SG pages	*/
 	struct bfa_sgpg_s	*sgpg;		/*  first SG page	*/
 	struct list_head	sgpg_q;		/*  allocated SG pages	*/
 	struct bfa_cb_qe_s	hcb_qe;		/*  bfa callback qelem	*/
 	bfa_cb_cbfn_t		io_cbfn;	/*  IO completion handler */
-	struct bfa_ioim_sp_s *iosp;		/*  slow-path IO handling */
-	u8		reqq;		/*  Request queue for I/O */
-	u64 start_time;			/*  IO's Profile start val */
+	struct bfa_ioim_sp_s	*iosp;		/*  slow-path IO handling */
+	u8			reqq;		/*  Request queue for I/O */
+	u64			start_time;	/*  IO's Profile start val */
 };
 
-
 struct bfa_ioim_sp_s {
 	struct bfi_msg_s	comp_rspmsg;	/*  IO comp f/w response */
 	u8			*snsinfo;	/*  sense info for this IO   */
-	struct bfa_sgpg_wqe_s sgpg_wqe;	/*  waitq elem for sgpg	*/
-	struct bfa_reqq_wait_s reqq_wait;	/*  to wait for room in reqq */
+	struct bfa_sgpg_wqe_s	sgpg_wqe;	/*  waitq elem for sgpg	*/
+	struct bfa_reqq_wait_s	reqq_wait;	/*  to wait for room in reqq */
 	bfa_boolean_t		abort_explicit;	/*  aborted by OS	*/
 	struct bfa_tskim_s	*tskim;		/*  Relevant TM cmd	*/
 };
@@ -143,35 +142,34 @@
 struct bfa_tskim_s {
 	struct list_head	qe;
 	bfa_sm_t		sm;
-	struct bfa_s	*bfa;	/*  BFA module  */
+	struct bfa_s		*bfa;	/*  BFA module  */
 	struct bfa_fcpim_mod_s  *fcpim;	/*  parent fcpim module	*/
 	struct bfa_itnim_s	*itnim;	/*  i-t-n nexus for this IO  */
-	struct bfad_tskim_s	*dtsk;   /*  driver task mgmt cmnd	*/
-	bfa_boolean_t	notify;	/*  notify itnim on TM comp  */
-	lun_t	lun;	/*  lun if applicable	*/
-	enum fcp_tm_cmnd	tm_cmnd;	/*  task management command  */
-	u16	tsk_tag;	/*  FWI IO tag	*/
-	u8	tsecs;	/*  timeout in seconds	*/
+	struct bfad_tskim_s	*dtsk;  /*  driver task mgmt cmnd	*/
+	bfa_boolean_t		notify;	/*  notify itnim on TM comp  */
+	struct scsi_lun		lun;	/*  lun if applicable	*/
+	enum fcp_tm_cmnd	tm_cmnd; /*  task management command  */
+	u16			tsk_tag; /*  FWI IO tag	*/
+	u8			tsecs;	/*  timeout in seconds	*/
 	struct bfa_reqq_wait_s  reqq_wait;   /*  to wait for room in reqq */
 	struct list_head	io_q;	/*  queue of affected IOs	*/
-	struct bfa_wc_s	wc;	/*  waiting counter	*/
+	struct bfa_wc_s		wc;	/*  waiting counter	*/
 	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/
 	enum bfi_tskim_status   tsk_status;  /*  TM status	*/
 };
 
-
 /*
  * BFA i-t-n (initiator mode)
  */
 struct bfa_itnim_s {
-	struct list_head	qe;		/*  queue element	*/
-	bfa_sm_t	  sm;		/*  i-t-n im BFA state machine  */
-	struct bfa_s	*bfa;		/*  bfa instance	*/
-	struct bfa_rport_s *rport;	/*  bfa rport	*/
-	void	*ditn;		/*  driver i-t-n structure	*/
+	struct list_head	qe;	/*  queue element	*/
+	bfa_sm_t		sm;	/*  i-t-n im BFA state machine  */
+	struct bfa_s		*bfa;	/*  bfa instance	*/
+	struct bfa_rport_s	*rport;	/*  bfa rport	*/
+	void			*ditn;	/*  driver i-t-n structure	*/
 	struct bfi_mhdr_s	mhdr;	/*  pre-built mhdr	*/
-	u8	msg_no;		/*  itnim/rport firmware handle */
-	u8	reqq;		/*  CQ for requests	*/
+	u8			msg_no;	/*  itnim/rport firmware handle */
+	u8			reqq;	/*  CQ for requests	*/
 	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/
 	struct list_head pending_q;	/*  queue of pending IO requests */
 	struct list_head io_q;		/*  queue of active IO requests */
@@ -181,19 +179,19 @@
 	bfa_boolean_t   seq_rec;	/*  SQER supported	*/
 	bfa_boolean_t   is_online;	/*  itnim is ONLINE for IO	*/
 	bfa_boolean_t   iotov_active;	/*  IO TOV timer is active	 */
-	struct bfa_wc_s	wc;	/*  waiting counter	*/
-	struct bfa_timer_s timer;	/*  pending IO TOV		 */
+	struct bfa_wc_s	wc;		/*  waiting counter	*/
+	struct bfa_timer_s timer;	/*  pending IO TOV	 */
 	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
 	struct bfa_fcpim_mod_s *fcpim;	/*  fcpim module	*/
 	struct bfa_itnim_iostats_s	stats;
 	struct bfa_itnim_ioprofile_s  ioprofile;
 };
 
-
 #define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
 #define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_IOIM_TAG_2_ID(_iotag)	((_iotag) & BFA_IOIM_IOTAG_MASK)
 #define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\
-	(&fcpim->ioim_arr[(_iotag & BFA_IOIM_RETRY_TAG_MASK)])
+	(&fcpim->ioim_arr[(_iotag & BFA_IOIM_IOTAG_MASK)])
 #define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag)	\
 	(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
 
@@ -201,26 +199,26 @@
 	(_bfa->modules.fcpim_mod.io_profile_start_time)
 #define bfa_fcpim_get_io_profile(_bfa)	\
 	(_bfa->modules.fcpim_mod.io_profile)
+#define bfa_ioim_update_iotag(__ioim) do {				\
+	uint16_t k = (__ioim)->iotag >> BFA_IOIM_RETRY_TAG_OFFSET;	\
+	k++; (__ioim)->iotag &= BFA_IOIM_IOTAG_MASK;			\
+	(__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET;		\
+} while (0)
 
 static inline bfa_boolean_t
-bfa_ioim_get_iotag(struct bfa_ioim_s *ioim)
+bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
 {
-	u16 k = ioim->iotag;
-
-	k >>= BFA_IOIM_RETRY_TAG_OFFSET; k++;
-
-	if (k > BFA_IOIM_RETRY_MAX)
+	uint16_t k = ioim->iotag >> BFA_IOIM_RETRY_TAG_OFFSET;
+	if (k < BFA_IOIM_RETRY_MAX)
 		return BFA_FALSE;
-	ioim->iotag &= BFA_IOIM_RETRY_TAG_MASK;
-	ioim->iotag |= k<<BFA_IOIM_RETRY_TAG_OFFSET;
 	return BFA_TRUE;
 }
+
 /*
  * function prototypes
  */
 void	bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
 					struct bfa_meminfo_s *minfo);
-void	bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
 void	bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 void	bfa_ioim_good_comp_isr(struct bfa_s *bfa,
 					struct bfi_msg_s *msg);
@@ -232,7 +230,6 @@
 
 void	bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
 					struct bfa_meminfo_s *minfo);
-void	bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
 void	bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
 void	bfa_tskim_iodone(struct bfa_tskim_s *tskim);
 void	bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
@@ -248,32 +245,14 @@
 void	bfa_itnim_iodone(struct bfa_itnim_s *itnim);
 void	bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
 bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
-void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim);
-void bfa_ioim_profile_start(struct bfa_ioim_s *ioim);
-
 
 /*
  * bfa fcpim module API functions
  */
-void		bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
+void	bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
 u16	bfa_fcpim_path_tov_get(struct bfa_s *bfa);
-void		bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
 u16	bfa_fcpim_qdepth_get(struct bfa_s *bfa);
-bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
-	 struct bfa_itnim_iostats_s *modstats);
-bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
-		struct bfa_itnim_iostats_s *stats, u8 lp_tag);
-bfa_status_t bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
-	 struct bfa_fcpim_del_itn_stats_s *modstats);
-bfa_status_t bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag);
-void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
-		struct bfa_itnim_iostats_s *itnim_stats);
-bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
-void		bfa_fcpim_set_ioredirect(struct bfa_s *bfa,
-				bfa_boolean_t state);
-void		bfa_fcpim_update_ioredirect(struct bfa_s *bfa);
-bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time);
-bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);
+
 #define bfa_fcpim_ioredirect_enabled(__bfa)				\
 	(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
 
@@ -291,48 +270,33 @@
  * bfa itnim API functions
  */
 struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
-					struct bfa_rport_s *rport, void *itnim);
-void		bfa_itnim_delete(struct bfa_itnim_s *itnim);
-void		bfa_itnim_online(struct bfa_itnim_s *itnim,
-				 bfa_boolean_t seq_rec);
-void		bfa_itnim_offline(struct bfa_itnim_s *itnim);
-void		bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
-			struct bfa_itnim_iostats_s *stats);
-void		bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
-bfa_status_t	bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
-		struct bfa_itnim_ioprofile_s *ioprofile);
+		struct bfa_rport_s *rport, void *itnim);
+void bfa_itnim_delete(struct bfa_itnim_s *itnim);
+void bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec);
+void bfa_itnim_offline(struct bfa_itnim_s *itnim);
+void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
+bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+			struct bfa_itnim_ioprofile_s *ioprofile);
+
 #define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
 
 /*
- *	BFA completion callback for bfa_itnim_online().
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
+ * BFA completion callback for bfa_itnim_online().
  */
 void	bfa_cb_itnim_online(void *itnim);
 
 /*
- *	BFA completion callback for bfa_itnim_offline().
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
+ * BFA completion callback for bfa_itnim_offline().
  */
 void	bfa_cb_itnim_offline(void *itnim);
 void	bfa_cb_itnim_tov_begin(void *itnim);
 void	bfa_cb_itnim_tov(void *itnim);
 
 /*
- *	BFA notification to FCS/driver for second level error recovery.
- *
+ * BFA notification to FCS/driver for second level error recovery.
  * Atleast one I/O request has timedout and target is unresponsive to
  * repeated abort requests. Second level error recovery should be initiated
  * by starting implicit logout and recovery procedures.
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
  */
 void	bfa_cb_itnim_sler(void *itnim);
 
@@ -349,10 +313,8 @@
 bfa_status_t	bfa_ioim_abort(struct bfa_ioim_s *ioim);
 void		bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
 				      bfa_boolean_t iotov);
-
-
 /*
- *	I/O completion notification.
+ * I/O completion notification.
  *
  * @param[in]		dio			driver IO structure
  * @param[in]		io_status		IO completion status
@@ -363,39 +325,31 @@
  *
  * @return None
  */
-void	bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
-				  enum bfi_ioim_status io_status,
-				  u8 scsi_status, int sns_len,
-				  u8 *sns_info, s32 residue);
+void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
+			enum bfi_ioim_status io_status,
+			u8 scsi_status, int sns_len,
+			u8 *sns_info, s32 residue);
 
 /*
- *	I/O good completion notification.
- *
- * @param[in]		dio			driver IO structure
- *
- * @return None
+ * I/O good completion notification.
  */
-void	bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
+void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
 
 /*
- *	I/O abort completion notification
- *
- * @param[in]		dio			driver IO that was aborted
- *
- * @return None
+ * I/O abort completion notification
  */
-void	bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
+void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
 
 /*
  * bfa tskim API functions
  */
-struct bfa_tskim_s	*bfa_tskim_alloc(struct bfa_s *bfa,
-					struct bfad_tskim_s *dtsk);
-void		bfa_tskim_free(struct bfa_tskim_s *tskim);
-void		bfa_tskim_start(struct bfa_tskim_s *tskim,
-				struct bfa_itnim_s *itnim, lun_t lun,
-				enum fcp_tm_cmnd tm, u8 t_secs);
-void		bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
-				  enum bfi_tskim_status tsk_status);
+struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa,
+			struct bfad_tskim_s *dtsk);
+void bfa_tskim_free(struct bfa_tskim_s *tskim);
+void bfa_tskim_start(struct bfa_tskim_s *tskim,
+			struct bfa_itnim_s *itnim, struct scsi_lun lun,
+			enum fcp_tm_cmnd tm, u8 t_secs);
+void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
+			enum bfi_tskim_status tsk_status);
 
 #endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index 045d7e8..f674f93 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -19,9 +19,9 @@
  *  bfa_fcs.c BFA FCS main
  */
 
+#include "bfad_drv.h"
 #include "bfa_fcs.h"
 #include "bfa_fcbuild.h"
-#include "bfad_drv.h"
 
 BFA_TRC_FILE(FCS, FCS);
 
@@ -76,7 +76,7 @@
 	fcs->bfad = bfad;
 	fcs->min_cfg = min_cfg;
 
-	bfa_attach_fcs(bfa);
+	bfa->fcs = BFA_TRUE;
 	fcbuild_init();
 
 	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
@@ -110,14 +110,6 @@
 	}
 }
 
-/*
- * Start FCS operations.
- */
-void
-bfa_fcs_start(struct bfa_fcs_s *fcs)
-{
-	bfa_fcs_fabric_modstart(fcs);
-}
 
 /*
  *	brief
@@ -140,22 +132,6 @@
 
 /*
  *	brief
- *		FCS FDMI Driver Parameter Initialization
- *
- *	param[in]		fcs		FCS instance
- *	param[in]		fdmi_enable	TRUE/FALSE
- *
- *	return None
- */
-void
-bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable)
-{
-
-	fcs->fdmi_enabled = fdmi_enable;
-
-}
-/*
- *	brief
  *		FCS instance cleanup and exit.
  *
  *	param[in]		fcs			FCS instance
@@ -184,18 +160,6 @@
 }
 
 
-void
-bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod)
-{
-	fcs->trcmod = trcmod;
-}
-
-void
-bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
-{
-	bfa_wc_down(&fcs->wc);
-}
-
 /*
  * Fabric module implementation.
  */
@@ -232,31 +196,6 @@
 					 u32 rsp_len,
 					 u32 resid_len,
 					 struct fchs_s *rspfchs);
-/*
- *  fcs_fabric_sm fabric state machine functions
- */
-
-/*
- * Fabric state machine events
- */
-enum bfa_fcs_fabric_event {
-	BFA_FCS_FABRIC_SM_CREATE	= 1,	/*  create from driver	      */
-	BFA_FCS_FABRIC_SM_DELETE	= 2,	/*  delete from driver	      */
-	BFA_FCS_FABRIC_SM_LINK_DOWN	= 3,	/*  link down from port      */
-	BFA_FCS_FABRIC_SM_LINK_UP	= 4,	/*  link up from port	      */
-	BFA_FCS_FABRIC_SM_CONT_OP	= 5,	/*  flogi/auth continue op   */
-	BFA_FCS_FABRIC_SM_RETRY_OP	= 6,	/*  flogi/auth retry op      */
-	BFA_FCS_FABRIC_SM_NO_FABRIC	= 7,	/*  from flogi/auth	      */
-	BFA_FCS_FABRIC_SM_PERF_EVFP	= 8,	/*  from flogi/auth	      */
-	BFA_FCS_FABRIC_SM_ISOLATE	= 9,	/*  from EVFP processing     */
-	BFA_FCS_FABRIC_SM_NO_TAGGING	= 10,	/*  no VFT tagging from EVFP */
-	BFA_FCS_FABRIC_SM_DELAYED	= 11,	/*  timeout delay event      */
-	BFA_FCS_FABRIC_SM_AUTH_FAILED	= 12,	/*  auth failed	      */
-	BFA_FCS_FABRIC_SM_AUTH_SUCCESS	= 13,	/*  auth successful	      */
-	BFA_FCS_FABRIC_SM_DELCOMP	= 14,	/*  all vports deleted event */
-	BFA_FCS_FABRIC_SM_LOOPBACK	= 15,	/*  Received our own FLOGI   */
-	BFA_FCS_FABRIC_SM_START		= 16,	/*  from driver	      */
-};
 
 static void	bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
 					 enum bfa_fcs_fabric_event event);
@@ -270,14 +209,8 @@
 					      enum bfa_fcs_fabric_event event);
 static void	bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
 				       enum bfa_fcs_fabric_event event);
-static void	bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
-					      enum bfa_fcs_fabric_event event);
-static void	bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
 static void	bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
 					   enum bfa_fcs_fabric_event event);
-static void	bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
-					 enum bfa_fcs_fabric_event event);
 static void	bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
 				       enum bfa_fcs_fabric_event event);
 static void	bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
@@ -337,7 +270,7 @@
 
 	case BFA_FCS_FABRIC_SM_DELETE:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-		bfa_fcs_modexit_comp(fabric->fcs);
+		bfa_wc_down(&fabric->fcs->wc);
 		break;
 
 	default:
@@ -410,7 +343,7 @@
 
 	case BFA_FCS_FABRIC_SM_LOOPBACK:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		bfa_fcs_fabric_set_opertype(fabric);
 		break;
 
@@ -424,12 +357,12 @@
 
 	case BFA_FCS_FABRIC_SM_LINK_DOWN:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		break;
 
 	case BFA_FCS_FABRIC_SM_DELETE:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		bfa_fcs_fabric_delete(fabric);
 		break;
 
@@ -481,7 +414,7 @@
 	switch (event) {
 	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		break;
 
 	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
@@ -495,7 +428,7 @@
 
 	case BFA_FCS_FABRIC_SM_LINK_DOWN:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		break;
 
 	case BFA_FCS_FABRIC_SM_DELETE:
@@ -511,7 +444,7 @@
 /*
  *   Authentication failed
  */
-static void
+void
 bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
 			      enum bfa_fcs_fabric_event event)
 {
@@ -537,7 +470,7 @@
 /*
  *   Port is in loopback mode.
  */
-static void
+void
 bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
 			   enum bfa_fcs_fabric_event event)
 {
@@ -573,7 +506,7 @@
 	switch (event) {
 	case BFA_FCS_FABRIC_SM_LINK_DOWN:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		bfa_fcs_fabric_notify_offline(fabric);
 		break;
 
@@ -596,7 +529,7 @@
 /*
  *   Fabric is online - normal operating state.
  */
-static void
+void
 bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
 			 enum bfa_fcs_fabric_event event)
 {
@@ -606,7 +539,7 @@
 	switch (event) {
 	case BFA_FCS_FABRIC_SM_LINK_DOWN:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		bfa_fcs_fabric_notify_offline(fabric);
 		break;
 
@@ -617,7 +550,7 @@
 
 	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-		bfa_lps_discard(fabric->lps);
+		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
 		break;
 
 	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
@@ -697,7 +630,7 @@
 	switch (event) {
 	case BFA_FCS_FABRIC_SM_DELCOMP:
 		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-		bfa_fcs_modexit_comp(fabric->fcs);
+		bfa_wc_down(&fabric->fcs->wc);
 		break;
 
 	case BFA_FCS_FABRIC_SM_LINK_UP:
@@ -724,8 +657,8 @@
 	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
 
 	port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
-	port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
-	port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
+	port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;
+	port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;
 }
 
 /*
@@ -813,7 +746,7 @@
 		return;
 
 	case BFA_STATUS_EPROTOCOL:
-		switch (bfa_lps_get_extstatus(fabric->lps)) {
+		switch (fabric->lps->ext_status) {
 		case BFA_EPROTO_BAD_ACCEPT:
 			fabric->stats.flogi_acc_err++;
 			break;
@@ -840,26 +773,26 @@
 		return;
 	}
 
-	fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
+	fabric->bb_credit = fabric->lps->pr_bbcred;
 	bfa_trc(fabric->fcs, fabric->bb_credit);
 
-	if (!bfa_lps_is_brcd_fabric(fabric->lps))
-		fabric->fabric_name =  bfa_lps_get_peer_nwwn(fabric->lps);
+	if (!(fabric->lps->brcd_switch))
+		fabric->fabric_name =  fabric->lps->pr_nwwn;
 
 	/*
 	 * Check port type. It should be 1 = F-port.
 	 */
-	if (bfa_lps_is_fport(fabric->lps)) {
-		fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
-		fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
-		fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
+	if (fabric->lps->fport) {
+		fabric->bport.pid = fabric->lps->lp_pid;
+		fabric->is_npiv = fabric->lps->npiv_en;
+		fabric->is_auth = fabric->lps->auth_req;
 		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
 	} else {
 		/*
 		 * Nport-2-Nport direct attached
 		 */
 		fabric->bport.port_topo.pn2n.rem_port_wwn =
-			bfa_lps_get_peer_pwwn(fabric->lps);
+			fabric->lps->pr_pwwn;
 		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
 	}
 
@@ -987,7 +920,7 @@
 	INIT_LIST_HEAD(&fabric->vport_q);
 	INIT_LIST_HEAD(&fabric->vf_q);
 	fabric->lps = bfa_lps_alloc(fcs->bfa);
-	bfa_assert(fabric->lps);
+	WARN_ON(!fabric->lps);
 
 	/*
 	 * Initialize fabric delete completion handler. Fabric deletion is
@@ -1038,31 +971,6 @@
 	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
 }
 
-/*
- *   Suspend fabric activity as part of driver suspend.
- */
-void
-bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
-{
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-}
-
-enum bfa_port_type
-bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
-{
-	return fabric->oper_type;
-}
 
 /*
  *   Link up notification from BFA physical port module.
@@ -1123,40 +1031,6 @@
 	bfa_wc_down(&fabric->wc);
 }
 
-/*
- *   Base port is deleted.
- */
-void
-bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
-{
-	bfa_wc_down(&fabric->wc);
-}
-
-
-/*
- *    Check if fabric is online.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
- *   @return  TRUE/FALSE
- */
-int
-bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
-}
-
-/*
- *	brief
- *
- */
-bfa_status_t
-bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
-		     struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
-{
-	bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
-	return BFA_STATUS_OK;
-}
 
 /*
  * Lookup for a vport withing a fabric given its pwwn
@@ -1176,18 +1050,6 @@
 	return NULL;
 }
 
-/*
- *    In a given fabric, return the number of lports.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
- *   @return : 1 or more.
- */
-u16
-bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
-{
-	return fabric->num_vports;
-}
 
 /*
  *  Get OUI of the attached switch.
@@ -1207,7 +1069,7 @@
 	u8 *tmp;
 	u16 oui;
 
-	fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
+	fab_nwwn = fabric->lps->pr_nwwn;
 
 	tmp = (u8 *)&fab_nwwn;
 	oui = (tmp[3] << 8) | tmp[4];
@@ -1235,7 +1097,7 @@
 	 * external loopback cable is in place. Our own FLOGI frames are
 	 * sometimes looped back when switch port gets temporarily bypassed.
 	 */
-	if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) &&
+	if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&
 	    (els_cmd->els_code == FC_ELS_FLOGI) &&
 	    (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
 		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
@@ -1245,7 +1107,7 @@
 	/*
 	 * FLOGI/EVFP exchanges should be consumed by base fabric.
 	 */
-	if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
+	if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {
 		bfa_trc(fabric->fcs, pid);
 		bfa_fcs_fabric_process_uf(fabric, fchs, len);
 		return;
@@ -1358,13 +1220,13 @@
 		return;
 
 	reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				    bfa_os_hton3b(FC_FABRIC_PORT),
+				    bfa_hton3b(FC_FABRIC_PORT),
 				    n2n_port->reply_oxid, pcfg->pwwn,
 				    pcfg->nwwn,
 				    bfa_fcport_get_maxfrsize(bfa),
 				    bfa_fcport_get_rx_bbcredit(bfa));
 
-	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
+	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
 		      BFA_FALSE, FC_CLASS_3,
 		      reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
 		      FC_MAX_PDUSZ, 0);
@@ -1455,7 +1317,7 @@
 		break;
 
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
@@ -1502,7 +1364,7 @@
 		 * drop frame if vfid is unknown
 		 */
 		if (!fabric) {
-			bfa_assert(0);
+			WARN_ON(1);
 			bfa_stats(fcs, uf.vfid_unknown);
 			bfa_uf_free(uf);
 			return;
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
index 9cb6a55..0fd6316 100644
--- a/drivers/scsi/bfa/bfa_fcs.h
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -27,6 +27,22 @@
 #define BFA_FCS_OS_STR_LEN		64
 
 /*
+ *  lps_pvt BFA LPS private functions
+ */
+
+enum bfa_lps_event {
+	BFA_LPS_SM_LOGIN	= 1,	/* login request from user      */
+	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user     */
+	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout */
+	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue  */
+	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user         */
+	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline              */
+	BFA_LPS_SM_RX_CVL	= 7,	/* Rx clear virtual link        */
+	BFA_LPS_SM_SET_N2N_PID  = 8,	/* Set assigned PID for n2n */
+};
+
+
+/*
  * !!! Only append to the enums defined here to avoid any versioning
  * !!! needed between trace utility and driver version
  */
@@ -41,13 +57,12 @@
 struct bfa_fcs_s;
 
 #define __fcs_min_cfg(__fcs)       ((__fcs)->min_cfg)
-void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
 
 #define BFA_FCS_BRCD_SWITCH_OUI  0x051e
 #define N2N_LOCAL_PID	    0x010000
 #define N2N_REMOTE_PID		0x020000
 #define	BFA_FCS_RETRY_TIMEOUT 2000
-#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_os_ntoh3b(pid) > 0xFFF000) ?  1 : 0)
+#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_ntoh3b(pid) > 0xFFF000) ?  1 : 0)
 
 
 
@@ -109,7 +124,7 @@
 
 struct bfa_fcs_lport_n2n_s {
 	u32        rsvd;
-	u16        reply_oxid;	/*  ox_id from the req flogi to be
+	__be16     reply_oxid;	/*  ox_id from the req flogi to be
 					 *used in flogi acc */
 	wwn_t           rem_port_wwn;	/*  Attached port's wwn */
 };
@@ -316,8 +331,6 @@
 				       struct bfa_fcs_rport_s *rport);
 void            bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
 				       struct bfa_fcs_rport_s *rport);
-void bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs);
 void            bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);
 void            bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);
 void            bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);
@@ -359,9 +372,6 @@
 bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
 void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
 			    struct bfa_vport_attr_s *vport_attr);
-void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
-			     struct bfa_vport_stats_s *vport_stats);
-void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
 struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
 					     u16 vf_id, wwn_t vpwwn);
 void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
@@ -406,7 +416,7 @@
 	struct bfad_rport_s	*rp_drv;	/*  driver peer instance */
 	u32	pid;	/*  port ID of rport */
 	u16	maxfrsize;	/*  maximum frame size */
-	u16	reply_oxid;	/*  OX_ID of inbound requests */
+	__be16	reply_oxid;	/*  OX_ID of inbound requests */
 	enum fc_cos	fc_cos;	/*  FC classes of service supp */
 	bfa_boolean_t	cisc;	/*  CISC capable device */
 	bfa_boolean_t	prlo;	/*  processing prlo or LOGO */
@@ -437,32 +447,18 @@
 /*
  * bfa fcs rport API functions
  */
-bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
-			       struct bfa_fcs_rport_s *rport,
-			       struct bfad_rport_s *rport_drv);
-bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
-			    struct bfa_rport_attr_s *attr);
-void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
-			     struct bfa_rport_stats_s *stats);
-void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
 struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
 					     wwn_t rpwwn);
 struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
 	struct bfa_fcs_lport_s *port, wwn_t rnwwn);
 void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
 
-void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
-			     enum bfa_port_speed speed);
 void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
 	 struct fchs_s *fchs, u16 len);
 void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
 
 struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_lport_s *port,
 	 u32 pid);
-void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
 void bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 			 struct fc_logi_s *plogi_rsp);
 void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port,
@@ -470,10 +466,8 @@
 				struct fc_logi_s *plogi);
 void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
 			 struct fc_logi_s *plogi);
-void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id);
+void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id);
 
-void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
 void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
 void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
 int  bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
@@ -618,7 +612,7 @@
 	u8         option_rom_ver[BFA_VERSION_LEN];
 	u8         fw_version[8];
 	u8         os_name[256];
-	u32        max_ct_pyld;
+	__be32        max_ct_pyld;
 };
 
 /*
@@ -626,9 +620,9 @@
  */
 struct bfa_fcs_fdmi_port_attr_s {
 	u8         supp_fc4_types[32];	/* supported FC4 types */
-	u32        supp_speed;	/* supported speed */
-	u32        curr_speed;	/* current Speed */
-	u32        max_frm_size;	/* max frame size */
+	__be32        supp_speed;	/* supported speed */
+	__be32        curr_speed;	/* current Speed */
+	__be32        max_frm_size;	/* max frame size */
 	u8         os_device_name[256];	/* OS device Name */
 	u8         host_name[256];	/* host name */
 };
@@ -664,6 +658,57 @@
 };
 
 /*
+ *  fcs_fabric_sm fabric state machine functions
+ */
+
+/*
+ * Fabric state machine events
+ */
+enum bfa_fcs_fabric_event {
+	BFA_FCS_FABRIC_SM_CREATE        = 1,    /*  create from driver        */
+	BFA_FCS_FABRIC_SM_DELETE        = 2,    /*  delete from driver        */
+	BFA_FCS_FABRIC_SM_LINK_DOWN     = 3,    /*  link down from port      */
+	BFA_FCS_FABRIC_SM_LINK_UP       = 4,    /*  link up from port         */
+	BFA_FCS_FABRIC_SM_CONT_OP       = 5,    /*  flogi/auth continue op   */
+	BFA_FCS_FABRIC_SM_RETRY_OP      = 6,    /*  flogi/auth retry op      */
+	BFA_FCS_FABRIC_SM_NO_FABRIC     = 7,    /*  from flogi/auth           */
+	BFA_FCS_FABRIC_SM_PERF_EVFP     = 8,    /*  from flogi/auth           */
+	BFA_FCS_FABRIC_SM_ISOLATE       = 9,    /*  from EVFP processing     */
+	BFA_FCS_FABRIC_SM_NO_TAGGING    = 10,   /*  no VFT tagging from EVFP */
+	BFA_FCS_FABRIC_SM_DELAYED       = 11,   /*  timeout delay event      */
+	BFA_FCS_FABRIC_SM_AUTH_FAILED   = 12,   /*  auth failed       */
+	BFA_FCS_FABRIC_SM_AUTH_SUCCESS  = 13,   /*  auth successful           */
+	BFA_FCS_FABRIC_SM_DELCOMP       = 14,   /*  all vports deleted event */
+	BFA_FCS_FABRIC_SM_LOOPBACK      = 15,   /*  Received our own FLOGI   */
+	BFA_FCS_FABRIC_SM_START         = 16,   /*  from driver       */
+};
+
+/*
+ *  fcs_rport_sm FCS rport state machine events
+ */
+
+enum rport_event {
+	RPSM_EVENT_PLOGI_SEND   = 1,    /*  new rport; start with PLOGI */
+	RPSM_EVENT_PLOGI_RCVD   = 2,    /*  Inbound PLOGI from remote port */
+	RPSM_EVENT_PLOGI_COMP   = 3,    /*  PLOGI completed to rport    */
+	RPSM_EVENT_LOGO_RCVD    = 4,    /*  LOGO from remote device     */
+	RPSM_EVENT_LOGO_IMP     = 5,    /*  implicit logo for SLER      */
+	RPSM_EVENT_FCXP_SENT    = 6,    /*  Frame from has been sent    */
+	RPSM_EVENT_DELETE       = 7,    /*  RPORT delete request        */
+	RPSM_EVENT_SCN          = 8,    /*  state change notification   */
+	RPSM_EVENT_ACCEPTED     = 9,    /*  Good response from remote device */
+	RPSM_EVENT_FAILED       = 10,   /*  Request to rport failed.    */
+	RPSM_EVENT_TIMEOUT      = 11,   /*  Rport SM timeout event      */
+	RPSM_EVENT_HCB_ONLINE  = 12,    /*  BFA rport online callback   */
+	RPSM_EVENT_HCB_OFFLINE = 13,    /*  BFA rport offline callback  */
+	RPSM_EVENT_FC4_OFFLINE = 14,    /*  FC-4 offline complete       */
+	RPSM_EVENT_ADDRESS_CHANGE = 15, /*  Rport's PID has changed     */
+	RPSM_EVENT_ADDRESS_DISC = 16,   /*  Need to Discover rport's PID */
+	RPSM_EVENT_PRLO_RCVD   = 17,    /*  PRLO from remote device     */
+	RPSM_EVENT_PLOGI_RETRY = 18,    /*  Retry PLOGI continously */
+};
+
+/*
  * bfa fcs API functions
  */
 void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
@@ -672,16 +717,12 @@
 void bfa_fcs_init(struct bfa_fcs_s *fcs);
 void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
 			      struct bfa_fcs_driver_info_s *driver_info);
-void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
 void bfa_fcs_exit(struct bfa_fcs_s *fcs);
-void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
-void		bfa_fcs_start(struct bfa_fcs_s *fcs);
 
 /*
  * bfa fcs vf public functions
  */
 bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
-u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
 
 /*
  * fabric protected interface functions
@@ -689,32 +730,29 @@
 void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
 void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
 void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
 void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
 void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
 void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
 	struct bfa_fcs_vport_s *vport);
 void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
 	struct bfa_fcs_vport_s *vport);
-int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
 struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
 		struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
 void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
 void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
 		struct fchs_s *fchs, u16 len);
-bfa_boolean_t	bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t	bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
-enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
 void	bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
-void	bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
-bfa_status_t	bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
-			struct bfa_fcs_s *fcs, struct bfa_lport_cfg_s *port_cfg,
-			struct bfad_vf_s *vf_drv);
 void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
 	       wwn_t fabric_name);
 u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
 void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
 void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+			enum bfa_fcs_fabric_event event);
+void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+			enum bfa_fcs_fabric_event event);
+void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+			enum bfa_fcs_fabric_event event);
 
 /*
  * BFA FCS callback interfaces
diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index 413b58e..e7b49f4 100644
--- a/drivers/scsi/bfa/bfa_fcs_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -19,9 +19,9 @@
  *  fcpim.c - FCP initiator mode i-t nexus state machine
  */
 
+#include "bfad_drv.h"
 #include "bfa_fcs.h"
 #include "bfa_fcbuild.h"
-#include "bfad_drv.h"
 #include "bfad_im.h"
 
 BFA_TRC_FILE(FCS, FCPIM);
@@ -103,7 +103,7 @@
 		break;
 
 	case BFA_FCS_ITNIM_SM_OFFLINE:
-		bfa_fcs_rport_itnim_ack(itnim->rport);
+		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 		break;
 
 	case BFA_FCS_ITNIM_SM_INITIATOR:
@@ -140,7 +140,7 @@
 	case BFA_FCS_ITNIM_SM_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
+		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 		break;
 
 	case BFA_FCS_ITNIM_SM_DELETE:
@@ -181,7 +181,7 @@
 	case BFA_FCS_ITNIM_SM_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 		bfa_fcxp_discard(itnim->fcxp);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
+		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 		break;
 
 	case BFA_FCS_ITNIM_SM_INITIATOR:
@@ -217,7 +217,7 @@
 		} else {
 			/* invoke target offline */
 			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-			bfa_fcs_rport_logo_imp(itnim->rport);
+			bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
 		}
 		break;
 
@@ -225,7 +225,7 @@
 	case BFA_FCS_ITNIM_SM_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 		bfa_timer_stop(&itnim->timer);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
+		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 		break;
 
 	case BFA_FCS_ITNIM_SM_INITIATOR:
@@ -269,7 +269,7 @@
 	case BFA_FCS_ITNIM_SM_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 		bfa_itnim_offline(itnim->bfa_itnim);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
+		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 		break;
 
 	case BFA_FCS_ITNIM_SM_DELETE:
@@ -330,7 +330,7 @@
 	switch (event) {
 	case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
+		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 		break;
 
 	case BFA_FCS_ITNIM_SM_DELETE:
@@ -358,7 +358,7 @@
 	switch (event) {
 	case BFA_FCS_ITNIM_SM_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
-		bfa_fcs_rport_itnim_ack(itnim->rport);
+		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
 		break;
 
 	case BFA_FCS_ITNIM_SM_RSP_ERROR:
@@ -536,7 +536,7 @@
 	if (bfa_itnim == NULL) {
 		bfa_trc(port->fcs, rport->pwwn);
 		bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
-		bfa_assert(0);
+		WARN_ON(1);
 		return NULL;
 	}
 
@@ -688,7 +688,7 @@
 
 	itnim->stats.sler++;
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_fcs_rport_logo_imp(itnim->rport);
+	bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
 }
 
 struct bfa_fcs_itnim_s *
@@ -700,7 +700,7 @@
 	if (!rport)
 		return NULL;
 
-	bfa_assert(rport->itnim != NULL);
+	WARN_ON(rport->itnim == NULL);
 	return rport->itnim;
 }
 
@@ -729,7 +729,7 @@
 {
 	struct bfa_fcs_itnim_s *itnim = NULL;
 
-	bfa_assert(port != NULL);
+	WARN_ON(port == NULL);
 
 	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
 
@@ -746,7 +746,7 @@
 {
 	struct bfa_fcs_itnim_s *itnim = NULL;
 
-	bfa_assert(port != NULL);
+	WARN_ON(port == NULL);
 
 	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
 
@@ -778,6 +778,6 @@
 		break;
 
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 8d65130..4e2eb92 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -15,10 +15,10 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_fcs.h"
 #include "bfa_fcbuild.h"
 #include "bfa_fc.h"
-#include "bfad_drv.h"
 
 BFA_TRC_FILE(FCS, PORT);
 
@@ -159,7 +159,7 @@
 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 			list_for_each_safe(qe, qen, &port->rport_q) {
 				rport = (struct bfa_fcs_rport_s *) qe;
-				bfa_fcs_rport_delete(rport);
+				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 			}
 		}
 		break;
@@ -197,7 +197,7 @@
 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 			list_for_each_safe(qe, qen, &port->rport_q) {
 				rport = (struct bfa_fcs_rport_s *) qe;
-				bfa_fcs_rport_delete(rport);
+				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 			}
 		}
 		break;
@@ -309,6 +309,7 @@
 			return;
 		}
 		port->pid  = rx_fchs->d_id;
+		bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
 	}
 
 	/*
@@ -323,6 +324,7 @@
 			(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
 			(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
 			port->pid  = rx_fchs->d_id;
+			bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
 			rport->pid = rx_fchs->s_id;
 		}
 		bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
@@ -349,8 +351,8 @@
 		 * This is a different device with the same pid. Old device
 		 * disappeared. Send implicit LOGO to old device.
 		 */
-		bfa_assert(rport->pwwn != plogi->port_name);
-		bfa_fcs_rport_logo_imp(rport);
+		WARN_ON(rport->pwwn == plogi->port_name);
+		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
 
 		/*
 		 * Inbound PLOGI from a new device (with old PID).
@@ -362,7 +364,7 @@
 	/*
 	 * PLOGI crossing each other.
 	 */
-	bfa_assert(rport->pwwn == WWN_NULL);
+	WARN_ON(rport->pwwn != WWN_NULL);
 	bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
 }
 
@@ -511,7 +513,8 @@
 	__port_action[port->fabric->fab_type].offline(port);
 
 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
-	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
+	if (bfa_sm_cmp_state(port->fabric,
+			bfa_fcs_fabric_sm_online) == BFA_TRUE)
 		BFA_LOG(KERN_ERR, bfad, bfa_log_level,
 		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
 		lpwwn_buf, "Initiator");
@@ -522,26 +525,26 @@
 
 	list_for_each_safe(qe, qen, &port->rport_q) {
 		rport = (struct bfa_fcs_rport_s *) qe;
-		bfa_fcs_rport_offline(rport);
+		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
 	}
 }
 
 static void
 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
 {
-	bfa_assert(0);
+	WARN_ON(1);
 }
 
 static void
 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
 {
-	bfa_assert(0);
+	WARN_ON(1);
 }
 
 static void
 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
 {
-	bfa_assert(0);
+	WARN_ON(1);
 }
 
 static void
@@ -584,33 +587,11 @@
 				port->vport ? port->vport->vport_drv : NULL);
 		bfa_fcs_vport_delete_comp(port->vport);
 	} else {
-		 bfa_fcs_fabric_port_delete_comp(port->fabric);
+		bfa_wc_down(&port->fabric->wc);
 	}
 }
 
 
-
-/*
- *  fcs_lport_api BFA FCS port API
- */
-/*
- *   Module initialization
- */
-void
-bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs)
-{
-
-}
-
-/*
- *   Module cleanup
- */
-void
-bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs)
-{
-	bfa_fcs_modexit_comp(fcs);
-}
-
 /*
  * Unsolicited frame receive handling.
  */
@@ -623,6 +604,7 @@
 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
 
 	bfa_stats(lport, uf_recvs);
+	bfa_trc(lport->fcs, fchs->type);
 
 	if (!bfa_fcs_lport_is_online(lport)) {
 		bfa_stats(lport, uf_recv_drops);
@@ -682,8 +664,11 @@
 	 * Only handles ELS frames for now.
 	 */
 	if (fchs->type != FC_TYPE_ELS) {
-		bfa_trc(lport->fcs, fchs->type);
-		bfa_assert(0);
+		bfa_trc(lport->fcs, fchs->s_id);
+		bfa_trc(lport->fcs, fchs->d_id);
+		/* ignore type FC_TYPE_FC_FSS */
+		if (fchs->type != FC_TYPE_FC_FSS)
+			bfa_sm_fault(lport->fcs, fchs->type);
 		return;
 	}
 
@@ -792,7 +777,7 @@
 	struct bfa_fcs_lport_s *port,
 	struct bfa_fcs_rport_s *rport)
 {
-	bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
+	WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
 	list_del(&rport->qe);
 	port->num_rports--;
 
@@ -850,8 +835,8 @@
 	lport->fcs = fcs;
 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
 	lport->vport = vport;
-	lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
-				  bfa_lps_get_tag(lport->fabric->lps);
+	lport->lp_tag = (vport) ? vport->lps->lp_tag :
+				  lport->fabric->lps->lp_tag;
 
 	INIT_LIST_HEAD(&lport->rport_q);
 	lport->num_rports = 0;
@@ -903,10 +888,12 @@
 	port_attr->port_cfg = port->port_cfg;
 
 	if (port->fabric) {
-		port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
-		port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
+		port_attr->port_type = port->fabric->oper_type;
+		port_attr->loopback = bfa_sm_cmp_state(port->fabric,
+				bfa_fcs_fabric_sm_loopback);
 		port_attr->authfail =
-			bfa_fcs_fabric_is_auth_failed(port->fabric);
+			bfa_sm_cmp_state(port->fabric,
+				bfa_fcs_fabric_sm_auth_failed);
 		port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
 		memcpy(port_attr->fabric_ip_addr,
 			bfa_fcs_lport_get_fabric_ipaddr(port),
@@ -915,10 +902,10 @@
 		if (port->vport != NULL) {
 			port_attr->port_type = BFA_PORT_TYPE_VPORT;
 			port_attr->fpma_mac =
-				bfa_lps_get_lp_mac(port->vport->lps);
+				port->vport->lps->lp_mac;
 		} else {
 			port_attr->fpma_mac =
-				bfa_lps_get_lp_mac(port->fabric->lps);
+				port->fabric->lps->lp_mac;
 		}
 	} else {
 		port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
@@ -998,6 +985,7 @@
 	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
 	     sizeof(wwn_t)) > 0) {
 		port->pid = N2N_LOCAL_PID;
+		bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
 		/*
 		 * First, check if we know the device by pwwn.
 		 */
@@ -1007,7 +995,7 @@
 			bfa_trc(port->fcs, rport->pid);
 			bfa_trc(port->fcs, rport->pwwn);
 			rport->pid = N2N_REMOTE_PID;
-			bfa_fcs_rport_online(rport);
+			bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
 			return;
 		}
 
@@ -1017,10 +1005,10 @@
 		 */
 		if (port->num_rports > 0) {
 			rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
-			bfa_assert(rport != NULL);
+			WARN_ON(rport == NULL);
 			if (rport) {
 				bfa_trc(port->fcs, rport->pwwn);
-				bfa_fcs_rport_delete(rport);
+				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 			}
 		}
 		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
@@ -1569,6 +1557,7 @@
 	struct fdmi_attr_s *attr;
 	u8        *curr_ptr;
 	u16        len, count;
+	u16	templen;
 
 	/*
 	 * get hba attributes
@@ -1594,69 +1583,69 @@
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
-	attr->len = sizeof(wwn_t);
-	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = sizeof(wwn_t);
+	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * Manufacturer
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
-	attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
-	memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = (u16) strlen(fcs_hba_attr->manufacturer);
+	memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
+	templen = fc_roundup(templen, sizeof(u32));
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * Serial Number
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
-	attr->len = (u16) strlen(fcs_hba_attr->serial_num);
-	memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = (u16) strlen(fcs_hba_attr->serial_num);
+	memcpy(attr->value, fcs_hba_attr->serial_num, templen);
+	templen = fc_roundup(templen, sizeof(u32));
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * Model
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
-	attr->len = (u16) strlen(fcs_hba_attr->model);
-	memcpy(attr->value, fcs_hba_attr->model, attr->len);
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = (u16) strlen(fcs_hba_attr->model);
+	memcpy(attr->value, fcs_hba_attr->model, templen);
+	templen = fc_roundup(templen, sizeof(u32));
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * Model Desc
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
-	attr->len = (u16) strlen(fcs_hba_attr->model_desc);
-	memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = (u16) strlen(fcs_hba_attr->model_desc);
+	memcpy(attr->value, fcs_hba_attr->model_desc, templen);
+	templen = fc_roundup(templen, sizeof(u32));
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * H/W Version
@@ -1664,14 +1653,14 @@
 	if (fcs_hba_attr->hw_version[0] != '\0') {
 		attr = (struct fdmi_attr_s *) curr_ptr;
 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
-		attr->len = (u16) strlen(fcs_hba_attr->hw_version);
-		memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
+		templen = (u16) strlen(fcs_hba_attr->hw_version);
+		memcpy(attr->value, fcs_hba_attr->hw_version, templen);
+		templen = fc_roundup(templen, sizeof(u32));
+		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+		len += templen;
 		count++;
-		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-					 sizeof(attr->len));
+		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+					 sizeof(templen));
 	}
 
 	/*
@@ -1679,14 +1668,14 @@
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
-	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
-	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;;
+	templen = (u16) strlen(fcs_hba_attr->driver_version);
+	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
+	templen = fc_roundup(templen, sizeof(u32));
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * Option Rom Version
@@ -1694,14 +1683,14 @@
 	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
 		attr = (struct fdmi_attr_s *) curr_ptr;
 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
-		attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
-		memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
+		templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
+		memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
+		templen = fc_roundup(templen, sizeof(u32));
+		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+		len += templen;
 		count++;
-		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-					 sizeof(attr->len));
+		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+					 sizeof(templen));
 	}
 
 	/*
@@ -1709,14 +1698,14 @@
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
-	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
-	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = (u16) strlen(fcs_hba_attr->driver_version);
+	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
+	templen = fc_roundup(templen, sizeof(u32));
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * OS Name
@@ -1724,14 +1713,14 @@
 	if (fcs_hba_attr->os_name[0] != '\0') {
 		attr = (struct fdmi_attr_s *) curr_ptr;
 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
-		attr->len = (u16) strlen(fcs_hba_attr->os_name);
-		memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
+		templen = (u16) strlen(fcs_hba_attr->os_name);
+		memcpy(attr->value, fcs_hba_attr->os_name, templen);
+		templen = fc_roundup(templen, sizeof(u32));
+		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+		len += templen;
 		count++;
-		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-					sizeof(attr->len));
+		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+					sizeof(templen));
 	}
 
 	/*
@@ -1739,12 +1728,12 @@
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
-	attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
-	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
-	len += attr->len;
+	templen = sizeof(fcs_hba_attr->max_ct_pyld);
+	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
+	len += templen;
 	count++;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * Update size of payload
@@ -1845,6 +1834,7 @@
 	u8        *curr_ptr;
 	u16        len;
 	u8	count = 0;
+	u16	templen;
 
 	/*
 	 * get port attributes
@@ -1863,54 +1853,54 @@
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
-	attr->len = sizeof(fcs_port_attr.supp_fc4_types);
-	memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = sizeof(fcs_port_attr.supp_fc4_types);
+	memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	++count;
 	attr->len =
-		cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+		cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * Supported Speed
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
-	attr->len = sizeof(fcs_port_attr.supp_speed);
-	memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = sizeof(fcs_port_attr.supp_speed);
+	memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	++count;
 	attr->len =
-		cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+		cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * current Port Speed
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
-	attr->len = sizeof(fcs_port_attr.curr_speed);
-	memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = sizeof(fcs_port_attr.curr_speed);
+	memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	++count;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * max frame size
 	 */
 	attr = (struct fdmi_attr_s *) curr_ptr;
 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
-	attr->len = sizeof(fcs_port_attr.max_frm_size);
-	memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
+	templen = sizeof(fcs_port_attr.max_frm_size);
+	memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
+	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+	len += templen;
 	++count;
-	attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
+	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+			     sizeof(templen));
 
 	/*
 	 * OS Device Name
@@ -1918,14 +1908,14 @@
 	if (fcs_port_attr.os_device_name[0] != '\0') {
 		attr = (struct fdmi_attr_s *) curr_ptr;
 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
-		attr->len = (u16) strlen(fcs_port_attr.os_device_name);
-		memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
+		templen = (u16) strlen(fcs_port_attr.os_device_name);
+		memcpy(attr->value, fcs_port_attr.os_device_name, templen);
+		templen = fc_roundup(templen, sizeof(u32));
+		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+		len += templen;
 		++count;
-		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-					sizeof(attr->len));
+		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+					sizeof(templen));
 	}
 	/*
 	 * Host Name
@@ -1933,14 +1923,14 @@
 	if (fcs_port_attr.host_name[0] != '\0') {
 		attr = (struct fdmi_attr_s *) curr_ptr;
 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
-		attr->len = (u16) strlen(fcs_port_attr.host_name);
-		memcpy(attr->value, fcs_port_attr.host_name, attr->len);
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
+		templen = (u16) strlen(fcs_port_attr.host_name);
+		memcpy(attr->value, fcs_port_attr.host_name, templen);
+		templen = fc_roundup(templen, sizeof(u32));
+		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
+		len += templen;
 		++count;
-		attr->len = cpu_to_be16(attr->len + sizeof(attr->type) +
-				sizeof(attr->len));
+		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
+				sizeof(templen));
 	}
 
 	/*
@@ -2103,7 +2093,7 @@
 	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
 }
 
-void
+static void
 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
 {
@@ -2147,7 +2137,7 @@
 	hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
 }
 
-void
+static void
 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
 {
@@ -2560,7 +2550,7 @@
 
 	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 			     bfa_fcs_lport_get_fcid(port),
-				 bfa_lps_get_peer_nwwn(port->fabric->lps));
+				 port->fabric->lps->pr_nwwn);
 
 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
 			  FC_CLASS_3, len, &fchs,
@@ -2760,7 +2750,7 @@
 
 	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 			     bfa_fcs_lport_get_fcid(port),
-				 bfa_lps_get_peer_nwwn(port->fabric->lps));
+				 port->fabric->lps->pr_nwwn);
 
 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
 			  FC_CLASS_3, len, &fchs,
@@ -2836,7 +2826,7 @@
 	ms->fcxp = fcxp;
 
 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_os_hton3b(FC_MGMT_SERVER),
+			     bfa_hton3b(FC_MGMT_SERVER),
 			     bfa_fcs_lport_get_fcid(port), 0,
 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
 				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
@@ -3593,7 +3583,7 @@
 	ns->fcxp = fcxp;
 
 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_os_hton3b(FC_NAME_SERVER),
+			     bfa_hton3b(FC_NAME_SERVER),
 			     bfa_fcs_lport_get_fcid(port), 0,
 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
 				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
@@ -4150,7 +4140,7 @@
 	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
 }
 
-void
+static void
 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
 {
 
@@ -4163,7 +4153,7 @@
 
 	for (ii = 0 ; ii < nwwns; ++ii) {
 		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
-		bfa_assert(rport);
+		WARN_ON(!rport);
 	}
 }
 
@@ -4352,8 +4342,8 @@
 	/* Handle VU registrations for Base port only */
 	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
 		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				bfa_lps_is_brcd_fabric(port->fabric->lps),
-							port->pid, 0);
+				port->fabric->lps->brcd_switch,
+				port->pid, 0);
 	} else {
 	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
 				    BFA_FALSE,
@@ -4626,7 +4616,7 @@
 
 
 		default:
-			bfa_assert(0);
+			WARN_ON(1);
 			nsquery = BFA_TRUE;
 		}
 	}
@@ -4672,7 +4662,7 @@
 
 	while ((qe != qh) && (i < nrports)) {
 		rport = (struct bfa_fcs_rport_s *) qe;
-		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
 			qe = bfa_q_next(qe);
 			bfa_trc(fcs, (u32) rport->pwwn);
 			bfa_trc(fcs, rport->pid);
@@ -4720,7 +4710,7 @@
 
 	while ((qe != qh) && (i < *nrports)) {
 		rport = (struct bfa_fcs_rport_s *) qe;
-		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
 			qe = bfa_q_next(qe);
 			bfa_trc(fcs, (u32) rport->pwwn);
 			bfa_trc(fcs, rport->pid);
@@ -4771,7 +4761,7 @@
 
 	while (qe != qh) {
 		rport = (struct bfa_fcs_rport_s *) qe;
-		if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
+		if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
 			(bfa_fcs_rport_get_state(rport) ==
 			  BFA_RPORT_OFFLINE)) {
 			qe = bfa_q_next(qe);
@@ -4807,7 +4797,7 @@
 	struct bfa_fcs_vport_s *vport;
 	bfa_fcs_vf_t   *vf;
 
-	bfa_assert(fcs != NULL);
+	WARN_ON(fcs == NULL);
 
 	vf = bfa_fcs_vf_lookup(fcs, vf_id);
 	if (vf == NULL) {
@@ -4853,7 +4843,7 @@
 		port_info->max_vports_supp =
 			bfa_lps_get_max_vport(port->fcs->bfa);
 		port_info->num_vports_inuse =
-			bfa_fcs_fabric_vport_count(port->fabric);
+			port->fabric->num_vports;
 		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
 		port_info->num_rports_inuse = port->num_rports;
 	} else {
@@ -4997,7 +4987,8 @@
 
 	switch (event) {
 	case BFA_FCS_VPORT_SM_START:
-		if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
+		if (bfa_sm_cmp_state(__vport_fabric(vport),
+					bfa_fcs_fabric_sm_online)
 		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
 			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
 			bfa_fcs_vport_do_fdisc(vport);
@@ -5080,13 +5071,13 @@
 	switch (event) {
 	case BFA_FCS_VPORT_SM_DELETE:
 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_lps_discard(vport->lps);
+		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
 		bfa_fcs_lport_delete(&vport->lport);
 		break;
 
 	case BFA_FCS_VPORT_SM_OFFLINE:
 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_lps_discard(vport->lps);
+		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
 		break;
 
 	case BFA_FCS_VPORT_SM_RSP_OK:
@@ -5166,7 +5157,7 @@
 
 	case BFA_FCS_VPORT_SM_OFFLINE:
 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_lps_discard(vport->lps);
+		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
 		bfa_fcs_lport_offline(&vport->lport);
 		break;
 
@@ -5266,7 +5257,7 @@
 
 	switch (event) {
 	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_lps_discard(vport->lps);
+		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
 		/*
 		 * !!! fall through !!!
 		 */
@@ -5305,14 +5296,14 @@
 static void
 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
 {
-	u8		lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
-	u8		lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
+	u8		lsrjt_rsn = vport->lps->lsrjt_rsn;
+	u8		lsrjt_expl = vport->lps->lsrjt_expl;
 
 	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
 	bfa_trc(__vport_fcs(vport), lsrjt_expl);
 
 	/* For certain reason codes, we don't want to retry. */
-	switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
+	switch (vport->lps->lsrjt_expl) {
 	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
 	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
 		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
@@ -5476,7 +5467,7 @@
 	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
 		return BFA_STATUS_VPORT_EXISTS;
 
-	if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
+	if (fcs->fabric.num_vports ==
 			bfa_lps_get_max_vport(fcs->bfa))
 		return BFA_STATUS_VPORT_MAX;
 
@@ -5618,33 +5609,6 @@
 	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
 }
 
-/*
- *	Use this function to get vport's statistics.
- *
- *	param[in]	vport	pointer to bfa_fcs_vport_t.
- *	param[out]	stats	pointer to return vport statistics in
- *
- *	return None
- */
-void
-bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
-			struct bfa_vport_stats_s *stats)
-{
-	*stats = vport->vport_stats;
-}
-
-/*
- *	Use this function to clear vport's statistics.
- *
- *	param[in]	vport	pointer to bfa_fcs_vport_t.
- *
- *	return None
- */
-void
-bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
-{
-	memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
-}
 
 /*
  *	Lookup a virtual port. Excludes base port from lookup.
@@ -5684,7 +5648,7 @@
 		/*
 		 * Initialiaze the V-Port fields
 		 */
-		__vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
+		__vport_fcid(vport) = vport->lps->lp_pid;
 		vport->vport_stats.fdisc_accepts++;
 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
 		break;
@@ -5697,7 +5661,7 @@
 		break;
 
 	case BFA_STATUS_EPROTOCOL:
-		switch (bfa_lps_get_extstatus(vport->lps)) {
+		switch (vport->lps->ext_status) {
 		case BFA_EPROTO_BAD_ACCEPT:
 			vport->vport_stats.fdisc_acc_bad++;
 			break;
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index cf4a6e7..caaee6f 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -19,9 +19,9 @@
  *  rport.c Remote port implementation.
  */
 
+#include "bfad_drv.h"
 #include "bfa_fcs.h"
 #include "bfa_fcbuild.h"
-#include "bfad_drv.h"
 
 BFA_TRC_FILE(FCS, RPORT);
 
@@ -75,30 +75,6 @@
 static void	bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
 				struct fchs_s *rx_fchs, u16 len);
 static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
-/*
- *  fcs_rport_sm FCS rport state machine events
- */
-
-enum rport_event {
-	RPSM_EVENT_PLOGI_SEND	= 1,	/*  new rport; start with PLOGI */
-	RPSM_EVENT_PLOGI_RCVD	= 2,	/*  Inbound PLOGI from remote port */
-	RPSM_EVENT_PLOGI_COMP	= 3,	/*  PLOGI completed to rport	*/
-	RPSM_EVENT_LOGO_RCVD	= 4,	/*  LOGO from remote device	*/
-	RPSM_EVENT_LOGO_IMP	= 5,	/*  implicit logo for SLER	*/
-	RPSM_EVENT_FCXP_SENT	= 6,	/*  Frame from has been sent	*/
-	RPSM_EVENT_DELETE	= 7,	/*  RPORT delete request	*/
-	RPSM_EVENT_SCN		= 8,	/*  state change notification	*/
-	RPSM_EVENT_ACCEPTED	= 9,	/*  Good response from remote device */
-	RPSM_EVENT_FAILED	= 10,	/*  Request to rport failed.	*/
-	RPSM_EVENT_TIMEOUT	= 11,	/*  Rport SM timeout event	*/
-	RPSM_EVENT_HCB_ONLINE  = 12,	/*  BFA rport online callback	*/
-	RPSM_EVENT_HCB_OFFLINE = 13,	/*  BFA rport offline callback	*/
-	RPSM_EVENT_FC4_OFFLINE = 14,	/*  FC-4 offline complete	*/
-	RPSM_EVENT_ADDRESS_CHANGE = 15,	/*  Rport's PID has changed	*/
-	RPSM_EVENT_ADDRESS_DISC = 16,	/*  Need to Discover rport's PID */
-	RPSM_EVENT_PRLO_RCVD   = 17,	/*  PRLO from remote device	*/
-	RPSM_EVENT_PLOGI_RETRY = 18,	/*  Retry PLOGI continously */
-};
 
 static void	bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
 					enum rport_event event);
@@ -498,24 +474,24 @@
 
 	case RPSM_EVENT_LOGO_RCVD:
 		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-		bfa_rport_offline(rport->bfa_rport);
+		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
 		break;
 
 	case RPSM_EVENT_LOGO_IMP:
 	case RPSM_EVENT_ADDRESS_CHANGE:
 		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		bfa_rport_offline(rport->bfa_rport);
+		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
 		break;
 
 	case RPSM_EVENT_PLOGI_RCVD:
 		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_rport_offline(rport->bfa_rport);
+		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
 		bfa_fcs_rport_send_plogiacc(rport, NULL);
 		break;
 
 	case RPSM_EVENT_DELETE:
 		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		bfa_rport_offline(rport->bfa_rport);
+		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
 		break;
 
 	case RPSM_EVENT_SCN:
@@ -824,7 +800,7 @@
 	switch (event) {
 	case RPSM_EVENT_FC4_OFFLINE:
 		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-		bfa_rport_offline(rport->bfa_rport);
+		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
 		break;
 
 	case RPSM_EVENT_DELETE:
@@ -856,7 +832,7 @@
 	switch (event) {
 	case RPSM_EVENT_FC4_OFFLINE:
 		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		bfa_rport_offline(rport->bfa_rport);
+		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
 		break;
 
 	default:
@@ -878,7 +854,7 @@
 	switch (event) {
 	case RPSM_EVENT_FC4_OFFLINE:
 		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		bfa_rport_offline(rport->bfa_rport);
+		bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
 		break;
 
 	case RPSM_EVENT_SCN:
@@ -1459,7 +1435,7 @@
 			twin->stats.plogi_rcvd	  += rport->stats.plogi_rcvd;
 			twin->stats.plogi_accs++;
 
-			bfa_fcs_rport_delete(rport);
+			bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
 
 			bfa_fcs_rport_update(twin, plogi_rsp);
 			twin->pid = rsp_fchs->s_id;
@@ -1992,13 +1968,14 @@
 	/*
 	 * allocate FC-4s
 	 */
-	bfa_assert(bfa_fcs_lport_is_initiator(port));
+	WARN_ON(!bfa_fcs_lport_is_initiator(port));
 
 	if (bfa_fcs_lport_is_initiator(port)) {
 		rport->itnim = bfa_fcs_itnim_create(rport);
 		if (!rport->itnim) {
 			bfa_trc(fcs, rpid);
-			bfa_rport_delete(rport->bfa_rport);
+			bfa_sm_send_event(rport->bfa_rport,
+						BFA_RPORT_SM_DELETE);
 			kfree(rport_drv);
 			return NULL;
 		}
@@ -2032,7 +2009,7 @@
 			bfa_fcs_rpf_rport_offline(rport);
 	}
 
-	bfa_rport_delete(rport->bfa_rport);
+	bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
 	bfa_fcs_lport_del_rport(port, rport);
 	kfree(rport->rp_drv);
 }
@@ -2307,40 +2284,8 @@
 	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
 }
 
-/*
- * Called by bport/vport to delete a remote port instance.
- *
- * Rport delete is called under the following conditions:
- *		- vport is deleted
- *		- vf is deleted
- *		- explicit request from OS to delete rport
- */
-void
-bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
-}
 
 /*
- * Called by bport/vport to  when a target goes offline.
- *
- */
-void
-bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/*
- * Called by bport in n2n when a target (attached port) becomes online.
- *
- */
-void
-bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
-}
-/*
  *	Called by bport/vport to notify SCN for the remote port
  */
 void
@@ -2350,23 +2295,6 @@
 	bfa_sm_send_event(rport, RPSM_EVENT_SCN);
 }
 
-/*
- *	Called by	fcpim to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
-
-/*
- *	Called by fcptm to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
 
 /*
  *	brief
@@ -2465,15 +2393,6 @@
  *		Called to process any unsolicted frames from this remote port
  */
 void
-bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/*
- *		Called to process any unsolicted frames from this remote port
- */
-void
 bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
 			struct fchs_s *fchs, u16 len)
 {
@@ -2586,6 +2505,7 @@
 	return bfa_sm_to_state(rport_sm_table, rport->sm);
 }
 
+
 /*
  *	brief
  *		 Called by the Driver to set rport delete/ageout timeout
@@ -2602,7 +2522,7 @@
 		bfa_fcs_rport_del_timeout = rport_tmo * 1000;
 }
 void
-bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)
+bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
 {
 	bfa_trc(rport->fcs, rport->pid);
 
@@ -2621,106 +2541,6 @@
  *  fcs_rport_api FCS rport API.
  */
 
-/*
- *	Direct API to add a target by port wwn. This interface is used, for
- *	example, by bios when target pwwn is known from boot lun configuration.
- */
-bfa_status_t
-bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
-		struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv)
-{
-	bfa_trc(port->fcs, *pwwn);
-
-	return BFA_STATUS_OK;
-}
-
-/*
- *	Direct API to remove a target and its associated resources. This
- *	interface is used, for example, by driver to remove target
- *	ports from the target list for a VM.
- */
-bfa_status_t
-bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
-{
-
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(rport_in->fcs, rport_in->pwwn);
-
-	rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
-	if (rport == NULL) {
-		/*
-		 * TBD Error handling
-		 */
-		bfa_trc(rport_in->fcs, rport_in->pid);
-		return BFA_STATUS_UNKNOWN_RWWN;
-	}
-
-	/*
-	 * TBD if this remote port is online, send a logo
-	 */
-	return BFA_STATUS_OK;
-
-}
-
-/*
- *	Remote device status for display/debug.
- */
-void
-bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_attr_s *rport_attr)
-{
-	struct bfa_rport_qos_attr_s qos_attr;
-	bfa_fcs_lport_t *port = rport->port;
-	bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
-
-	memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
-
-	rport_attr->pid = rport->pid;
-	rport_attr->pwwn = rport->pwwn;
-	rport_attr->nwwn = rport->nwwn;
-	rport_attr->cos_supported = rport->fc_cos;
-	rport_attr->df_sz = rport->maxfrsize;
-	rport_attr->state = bfa_fcs_rport_get_state(rport);
-	rport_attr->fc_cos = rport->fc_cos;
-	rport_attr->cisc = rport->cisc;
-	rport_attr->scsi_function = rport->scsi_function;
-	rport_attr->curr_speed  = rport->rpf.rpsc_speed;
-	rport_attr->assigned_speed  = rport->rpf.assigned_speed;
-
-	bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
-	rport_attr->qos_attr = qos_attr;
-
-	rport_attr->trl_enforced = BFA_FALSE;
-	if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
-		if (rport_speed == BFA_PORT_SPEED_UNKNOWN) {
-			/* Use default ratelim speed setting */
-			rport_speed =
-				bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
-		}
-
-		if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
-			rport_attr->trl_enforced = BFA_TRUE;
-	}
-}
-
-/*
- *	Per remote device statistics.
- */
-void
-bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_stats_s *stats)
-{
-	*stats = rport->stats;
-}
-
-void
-bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
-{
-	memset((char *)&rport->stats, 0,
-			sizeof(struct bfa_rport_stats_s));
-}
-
 struct bfa_fcs_rport_s *
 bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
 {
@@ -2752,22 +2572,6 @@
 }
 
 /*
- * This API is to set the Rport's speed. Should be used when RPSC is not
- * supported by the rport.
- */
-void
-bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed)
-{
-	rport->rpf.assigned_speed  = speed;
-
-	/* Set this speed in f/w only if the RPSC speed is not available */
-	if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
-		bfa_rport_speed(rport->bfa_rport, speed);
-}
-
-
-
-/*
  * Remote port features (RPF) implementation.
  */
 
@@ -2827,7 +2631,7 @@
 	case RPFSM_EVENT_RPORT_ONLINE:
 		/* Send RPSC2 to a Brocade fabric only. */
 		if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
-			((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
+			((rport->port->fabric->lps->brcd_switch) ||
 			(bfa_fcs_fabric_get_switch_oui(fabric) ==
 						BFA_FCS_BRCD_SWITCH_OUI))) {
 			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
@@ -3093,7 +2897,7 @@
 		num_ents = be16_to_cpu(rpsc2_acc->num_pids);
 		bfa_trc(rport->fcs, num_ents);
 		if (num_ents > 0) {
-			bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
+			WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid);
 			bfa_trc(rport->fcs,
 				be16_to_cpu(rpsc2_acc->port_info[0].pid));
 			bfa_trc(rport->fcs,
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
index d8464ae..977e681 100644
--- a/drivers/scsi/bfa/bfa_hw_cb.c
+++ b/drivers/scsi/bfa/bfa_hw_cb.c
@@ -15,6 +15,7 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_modules.h"
 #include "bfi_cbreg.h"
 
@@ -110,7 +111,7 @@
 {
 	int i;
 
-	bfa_assert((nvecs == 1) || (nvecs == __HFN_NUMINTS));
+	WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
 
 	bfa->msix.nvecs = nvecs;
 	if (nvecs == 1) {
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
index b0efbc7..21018d9 100644
--- a/drivers/scsi/bfa/bfa_hw_ct.c
+++ b/drivers/scsi/bfa/bfa_hw_ct.c
@@ -15,6 +15,7 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_modules.h"
 #include "bfi_ctreg.h"
 
@@ -116,7 +117,7 @@
 void
 bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs)
 {
-	bfa_assert((nvecs == 1) || (nvecs == BFA_MSIX_CT_MAX));
+	WARN_ON((nvecs != 1) && (nvecs != BFA_MSIX_CT_MAX));
 	bfa_trc(bfa, nvecs);
 
 	bfa->msix.nvecs = nvecs;
@@ -143,7 +144,7 @@
 	for (; i <= BFA_MSIX_RME_Q3; i++)
 		bfa->msix.handler[i] = bfa_msix_rspq;
 
-	bfa_assert(i == BFA_MSIX_LPU_ERR);
+	WARN_ON(i != BFA_MSIX_LPU_ERR);
 	bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err;
 }
 
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 9f4aa39..c1f72c4 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -15,11 +15,11 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_ioc.h"
 #include "bfi_ctreg.h"
 #include "bfa_defs.h"
 #include "bfa_defs_svc.h"
-#include "bfad_drv.h"
 
 BFA_TRC_FILE(CNA, IOC);
 
@@ -29,7 +29,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_HWINIT_MAX	5
 #define BFA_IOC_TOV_RECOVER	 BFA_IOC_HB_TOV
 
 #define bfa_ioc_timer_start(__ioc)					\
@@ -42,11 +42,6 @@
 			bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
 #define bfa_hb_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->hb_timer)
 
-#define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS)
-#define BFA_DBG_FWTRC_LEN					\
-	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\
-	 (sizeof(struct bfa_trc_mod_s) -			\
-	  BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
 #define BFA_DBG_FWTRC_OFF(_fn)	(BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
 
 /*
@@ -59,17 +54,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))
-
-#ifdef BFA_IOC_IS_UEFI
-#define bfa_ioc_is_bios_optrom(__ioc) (0)
-#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI
-#else
-#define bfa_ioc_is_bios_optrom(__ioc)	\
-	(bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
-#define bfa_ioc_is_uefi(__ioc) (0)
-#endif
+#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)) || \
@@ -81,29 +75,22 @@
  * forward declarations
  */
 static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
-static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
 static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
 static void bfa_ioc_timeout(void *ioc);
 static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
 static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
 static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
-static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
-static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
 static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
 static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
 static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
 static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
 static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
 static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
-static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc);
-static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc);
-static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc);
+static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
+static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
 static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
 
-/*
- *  hal_ioc_sm
- */
 
 /*
  * IOC state machine definitions/declarations
@@ -116,10 +103,11 @@
 	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_FAILED		= 8,	/*  failure notice by iocpf sm	*/
-	IOC_E_HBFAIL		= 9,	/*  heartbeat failure		*/
-	IOC_E_HWERROR		= 10,	/*  hardware error interrupt	*/
-	IOC_E_TIMEOUT		= 11,	/*  timeout			*/
+	IOC_E_INITFAILED	= 8,	/*  failure notice by iocpf sm	*/
+	IOC_E_PFFAILED		= 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_s, enum ioc_event);
@@ -127,7 +115,7 @@
 bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
@@ -138,7 +126,7 @@
 	{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_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},
@@ -165,12 +153,6 @@
 /*
  * Forward declareations for iocpf state machine
  */
-static void bfa_iocpf_enable(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_disable(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_fail(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc);
-static void bfa_iocpf_stop(struct bfa_ioc_s *ioc);
 static void bfa_iocpf_timeout(void *ioc_arg);
 static void bfa_iocpf_sem_timeout(void *ioc_arg);
 
@@ -213,9 +195,14 @@
 bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
 bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
 bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s,
+						enum iocpf_event);
 bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event);
 bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
 bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s,
+						enum iocpf_event);
 bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
 
 static struct bfa_sm_table_s iocpf_sm_table[] = {
@@ -226,9 +213,12 @@
 	{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},
 };
 
@@ -301,7 +291,7 @@
 static void
 bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
 {
-	bfa_iocpf_enable(ioc);
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
 }
 
 /*
@@ -318,13 +308,13 @@
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_FAILED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
-		break;
-
+	case IOC_E_PFFAILED:
+		/* !!! fall through !!! */
 	case IOC_E_HWERROR:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
-		bfa_iocpf_initfail(ioc);
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		if (event != IOC_E_PFFAILED)
+			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
 		break;
 
 	case IOC_E_DISABLE:
@@ -333,7 +323,7 @@
 
 	case IOC_E_DETACH:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		bfa_iocpf_stop(ioc);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
 		break;
 
 	case IOC_E_ENABLE:
@@ -367,18 +357,16 @@
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 		break;
 
-	case IOC_E_FAILED:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
 		break;
-
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
 		bfa_ioc_timer_stop(ioc);
-		/* fall through */
-
+		/* !!! fall through !!! */
 	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
-		bfa_iocpf_getattrfail(ioc);
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
+		if (event != IOC_E_PFFAILED)
+			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
 		break;
 
 	case IOC_E_DISABLE:
@@ -415,22 +403,24 @@
 		break;
 
 	case IOC_E_DISABLE:
-		bfa_ioc_hb_stop(ioc);
+		bfa_hb_timer_stop(ioc);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
-	case IOC_E_FAILED:
-		bfa_ioc_hb_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-		break;
-
+	case IOC_E_PFFAILED:
 	case IOC_E_HWERROR:
-		bfa_ioc_hb_stop(ioc);
+		bfa_hb_timer_stop(ioc);
 		/* !!! fall through !!! */
-
 	case IOC_E_HBFAIL:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
-		bfa_iocpf_fail(ioc);
+		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_PFFAILED)
+			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
 		break;
 
 	default:
@@ -443,7 +433,7 @@
 bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
 {
 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
-	bfa_iocpf_disable(ioc);
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
 	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
 }
 
@@ -466,7 +456,7 @@
 		 * after iocpf sm completes failure processing and
 		 * moves to disabled state.
 		 */
-		bfa_iocpf_fail(ioc);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
 		break;
 
 	default:
@@ -499,7 +489,7 @@
 
 	case IOC_E_DETACH:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		bfa_iocpf_stop(ioc);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
 		break;
 
 	default:
@@ -509,16 +499,16 @@
 
 
 static void
-bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
+bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)
 {
-	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	bfa_trc(ioc, 0);
 }
 
 /*
- * Hardware initialization failed.
+ * Hardware initialization retry.
  */
 static void
-bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
 {
 	bfa_trc(ioc, event);
 
@@ -527,11 +517,21 @@
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_FAILED:
+	case IOC_E_PFFAILED:
+	case IOC_E_HWERROR:
 		/*
-		 * Initialization failure during iocpf init retry.
+		 * Initialization retry failed.
 		 */
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		if (event != IOC_E_PFFAILED)
+			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
+		break;
+
+	case IOC_E_INITFAILED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		break;
+
+	case IOC_E_ENABLE:
 		break;
 
 	case IOC_E_DISABLE:
@@ -540,7 +540,7 @@
 
 	case IOC_E_DETACH:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
-		bfa_iocpf_stop(ioc);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
 		break;
 
 	default:
@@ -552,21 +552,7 @@
 static void
 bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
 {
-	struct list_head			*qe;
-	struct bfa_ioc_hbfail_notify_s	*notify;
-	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
-
-	/*
-	 * 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_s *) qe;
-		notify->cbfn(notify->cbarg);
-	}
-
-	BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
-		"Heart Beat of IOC has failed\n");
+	bfa_trc(ioc, 0);
 }
 
 /*
@@ -579,23 +565,19 @@
 
 	switch (event) {
 
-	case IOC_E_FAILED:
-		/*
-		 * Initialization failure during iocpf recovery.
-		 * !!! Fall through !!!
-		 */
 	case IOC_E_ENABLE:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		break;
 
-	case IOC_E_ENABLED:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
-		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_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
+		break;
+
 	case IOC_E_HWERROR:
 		/*
 		 * HB failure notification, ignore.
@@ -606,13 +588,10 @@
 	}
 }
 
-
-
 /*
  * IOCPF State Machine
  */
 
-
 /*
  * Reset entry actions -- initialize state machine
  */
@@ -668,22 +647,29 @@
 	switch (event) {
 	case IOCPF_E_SEMLOCKED:
 		if (bfa_ioc_firmware_lock(ioc)) {
-			iocpf->retry_count = 0;
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+			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);
+				writel(1, ioc->ioc_regs.ioc_sem_reg);
+				bfa_sem_timer_start(ioc);
+			}
 		} else {
-			bfa_ioc_hw_sem_release(ioc);
+			writel(1, ioc->ioc_regs.ioc_sem_reg);
 			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
 		}
 		break;
 
 	case IOCPF_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_sem_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		bfa_ioc_pf_disabled(ioc);
+		bfa_fsm_send_event(ioc, IOC_E_DISABLED);
 		break;
 
 	case IOCPF_E_STOP:
-		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_sem_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 		break;
 
@@ -726,7 +712,7 @@
 	case IOCPF_E_DISABLE:
 		bfa_iocpf_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
-		bfa_ioc_pf_disabled(ioc);
+		bfa_fsm_send_event(ioc, IOC_E_DISABLED);
 		break;
 
 	case IOCPF_E_STOP:
@@ -760,13 +746,18 @@
 
 	switch (event) {
 	case IOCPF_E_SEMLOCKED:
-		iocpf->retry_count = 0;
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+		if (bfa_ioc_sync_complete(ioc)) {
+			bfa_ioc_sync_join(ioc);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+		} else {
+			writel(1, ioc->ioc_regs.ioc_sem_reg);
+			bfa_sem_timer_start(ioc);
+		}
 		break;
 
 	case IOCPF_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		bfa_sem_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 		break;
 
 	default:
@@ -774,12 +765,11 @@
 	}
 }
 
-
 static void
 bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
 {
 	bfa_iocpf_timer_start(iocpf->ioc);
-	bfa_ioc_reset(iocpf->ioc, BFA_FALSE);
+	bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
 }
 
 /*
@@ -806,23 +796,16 @@
 		 */
 
 	case IOCPF_E_TIMEOUT:
-		iocpf->retry_count++;
-		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
-			bfa_iocpf_timer_start(ioc);
-			bfa_ioc_reset(ioc, BFA_TRUE);
-			break;
-		}
-
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-
+		writel(1, ioc->ioc_regs.ioc_sem_reg);
 		if (event == IOCPF_E_TIMEOUT)
-			bfa_ioc_pf_failed(ioc);
+			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
 	case IOCPF_E_DISABLE:
-		bfa_ioc_hw_sem_release(ioc);
 		bfa_iocpf_timer_stop(ioc);
+		bfa_ioc_sync_leave(ioc);
+		writel(1, ioc->ioc_regs.ioc_sem_reg);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
 
@@ -831,7 +814,6 @@
 	}
 }
 
-
 static void
 bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
 {
@@ -853,7 +835,7 @@
 	switch (event) {
 	case IOCPF_E_FWRSP_ENABLE:
 		bfa_iocpf_timer_stop(ioc);
-		bfa_ioc_hw_sem_release(ioc);
+		writel(1, ioc->ioc_regs.ioc_sem_reg);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
 		break;
 
@@ -864,23 +846,15 @@
 		 */
 
 	case IOCPF_E_TIMEOUT:
-		iocpf->retry_count++;
-		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
-			writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
-			break;
-		}
-
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-
+		writel(1, ioc->ioc_regs.ioc_sem_reg);
 		if (event == IOCPF_E_TIMEOUT)
-			bfa_ioc_pf_failed(ioc);
+			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
 	case IOCPF_E_DISABLE:
 		bfa_iocpf_timer_stop(ioc);
-		bfa_ioc_hw_sem_release(ioc);
+		writel(1, ioc->ioc_regs.ioc_sem_reg);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
 		break;
 
@@ -893,12 +867,10 @@
 	}
 }
 
-
-
 static void
 bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
 {
-	bfa_ioc_pf_enabled(iocpf->ioc);
+	bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);
 }
 
 static void
@@ -914,20 +886,21 @@
 		break;
 
 	case IOCPF_E_GETATTRFAIL:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 		break;
 
 	case IOCPF_E_FAIL:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
 		break;
 
 	case IOCPF_E_FWREADY:
-		if (bfa_ioc_is_operational(ioc))
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
-		else
-			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
-
-		bfa_ioc_pf_failed(ioc);
+		if (bfa_ioc_is_operational(ioc)) {
+			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
+		} else {
+			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
+		}
 		break;
 
 	default:
@@ -935,7 +908,6 @@
 	}
 }
 
-
 static void
 bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
 {
@@ -957,7 +929,7 @@
 	case IOCPF_E_FWRSP_DISABLE:
 	case IOCPF_E_FWREADY:
 		bfa_iocpf_timer_stop(ioc);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 		break;
 
 	case IOCPF_E_FAIL:
@@ -968,7 +940,7 @@
 
 	case IOCPF_E_TIMEOUT:
 		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 		break;
 
 	case IOCPF_E_FWRSP_ENABLE:
@@ -979,13 +951,44 @@
 	}
 }
 
+static void
+bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/*
+ * IOC hb ack request is being removed.
+ */
+static void
+bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		bfa_ioc_sync_leave(ioc);
+		writel(1, ioc->ioc_regs.ioc_sem_reg);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_FAIL:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
 /*
  * IOC disable completion entry.
  */
 static void
 bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
 {
-	bfa_ioc_pf_disabled(iocpf->ioc);
+	bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
 }
 
 static void
@@ -997,6 +1000,7 @@
 
 	switch (event) {
 	case IOCPF_E_ENABLE:
+		iocpf->retry_count = 0;
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
 		break;
 
@@ -1010,11 +1014,64 @@
 	}
 }
 
+static void
+bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/*
+ * Hardware initialization failed.
+ */
+static void
+bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	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);
+			writel(1, ioc->ioc_regs.ioc_sem_reg);
+			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 {
+				writel(1, ioc->ioc_regs.ioc_sem_reg);
+				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+			}
+		}
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_sem_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_sem_timer_stop(ioc);
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	case IOCPF_E_FAIL:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
 
 static void
 bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
 {
-	bfa_iocpf_timer_start(iocpf->ioc);
+	bfa_fsm_send_event(iocpf->ioc, IOC_E_INITFAILED);
 }
 
 /*
@@ -1029,47 +1086,77 @@
 
 	switch (event) {
 	case IOCPF_E_DISABLE:
-		bfa_iocpf_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
 
 	case IOCPF_E_STOP:
-		bfa_iocpf_timer_stop(ioc);
 		bfa_ioc_firmware_unlock(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 		break;
 
-	case IOCPF_E_TIMEOUT:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-		break;
-
 	default:
 		bfa_sm_fault(ioc, event);
 	}
 }
 
-
 static void
-bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
+bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
 {
 	/*
 	 * Mark IOC as failed in hardware and stop firmware.
 	 */
 	bfa_ioc_lpu_stop(iocpf->ioc);
-	writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate);
-
-	/*
-	 * Notify other functions on HB failure.
-	 */
-	bfa_ioc_notify_hbfail(iocpf->ioc);
 
 	/*
 	 * Flush any queued up mailbox requests.
 	 */
 	bfa_ioc_mbox_hbfail(iocpf->ioc);
 
-	if (iocpf->auto_recover)
-		bfa_iocpf_recovery_timer_start(iocpf->ioc);
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	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);
+			writel(1, ioc->ioc_regs.ioc_sem_reg);
+			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 {
+				writel(1, ioc->ioc_regs.ioc_sem_reg);
+				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+			}
+		}
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_sem_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
+		break;
+
+	case IOCPF_E_FAIL:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+static void
+bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
+{
 }
 
 /*
@@ -1084,24 +1171,16 @@
 
 	switch (event) {
 	case IOCPF_E_DISABLE:
-		if (iocpf->auto_recover)
-			bfa_iocpf_timer_stop(ioc);
 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 		break;
 
-	case IOCPF_E_TIMEOUT:
-		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
-		break;
-
 	default:
 		bfa_sm_fault(ioc, event);
 	}
 }
 
-
-
 /*
- *  hal_ioc_pvt BFA IOC private functions
+ *  BFA IOC private functions
  */
 
 static void
@@ -1139,16 +1218,10 @@
 	if (r32 == 0)
 		return BFA_TRUE;
 
-	bfa_assert(cnt < BFA_SEM_SPINCNT);
+	WARN_ON(cnt >= BFA_SEM_SPINCNT);
 	return BFA_FALSE;
 }
 
-void
-bfa_ioc_sem_release(void __iomem *sem_reg)
-{
-	writel(1, sem_reg);
-}
-
 static void
 bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
 {
@@ -1167,18 +1240,6 @@
 	bfa_sem_timer_start(ioc);
 }
 
-void
-bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc)
-{
-	writel(1, ioc->ioc_regs.ioc_sem_reg);
-}
-
-static void
-bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
-{
-	bfa_sem_timer_stop(ioc);
-}
-
 /*
  * Initialize LPU local memory (aka secondary memory / SRAM)
  */
@@ -1212,7 +1273,7 @@
 	 * If memory initialization is not successful, IOC timeout will catch
 	 * such failures.
 	 */
-	bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
+	WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
 	bfa_trc(ioc, pss_ctl);
 
 	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
@@ -1258,8 +1319,8 @@
 	int		i;
 	u32	*fwsig = (u32 *) fwhdr;
 
-	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
-	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+	pgoff = PSS_SMEM_PGOFF(loff);
 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
 
 	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
@@ -1304,12 +1365,6 @@
 {
 	struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
 
-	/*
-	 * If bios/efi boot (flash based) -- return true
-	 */
-	if (bfa_ioc_is_bios_optrom(ioc))
-		return BFA_TRUE;
-
 	bfa_ioc_fwver_get(ioc, &fwhdr);
 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
 		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
@@ -1342,7 +1397,6 @@
 		writel(1, ioc->ioc_regs.lpu_mbox_cmd);
 }
 
-
 static void
 bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 {
@@ -1362,22 +1416,6 @@
 	boot_env = BFI_BOOT_LOADER_OS;
 
 	/*
-	 * Flash based firmware boot BIOS env.
-	 */
-	if (bfa_ioc_is_bios_optrom(ioc)) {
-		boot_type = BFI_BOOT_TYPE_FLASH;
-		boot_env = BFI_BOOT_LOADER_BIOS;
-	}
-
-	/*
-	 * Flash based firmware boot UEFI env.
-	 */
-	if (bfa_ioc_is_uefi(ioc)) {
-		boot_type = BFI_BOOT_TYPE_FLASH;
-		boot_env = BFI_BOOT_LOADER_UEFI;
-	}
-
-	/*
 	 * check if firmware is valid
 	 */
 	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
@@ -1405,8 +1443,7 @@
 	 * convergence, IOC will be in operational state when 2nd driver
 	 * is loaded.
 	 */
-	if (ioc_fwstate == BFI_IOC_DISABLED ||
-	    (!bfa_ioc_is_bios_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
@@ -1442,7 +1479,7 @@
 	bfa_trc(ioc, msgp[0]);
 	bfa_trc(ioc, len);
 
-	bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
+	WARN_ON(len > BFI_IOC_MSGLEN_MAX);
 
 	/*
 	 * first write msg to mailbox registers
@@ -1465,12 +1502,12 @@
 bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
 {
 	struct bfi_ioc_ctrl_req_s enable_req;
-	struct bfa_timeval_s tv;
+	struct timeval tv;
 
 	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
 		    bfa_ioc_portid(ioc));
 	enable_req.ioc_class = ioc->ioc_mc;
-	bfa_os_gettimeofday(&tv);
+	do_gettimeofday(&tv);
 	enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
 	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
 }
@@ -1504,7 +1541,6 @@
 
 	hb_count = readl(ioc->ioc_regs.heartbeat);
 	if (ioc->hb_count == hb_count) {
-		printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
 		bfa_ioc_recover(ioc);
 		return;
 	} else {
@@ -1522,13 +1558,6 @@
 	bfa_hb_timer_start(ioc);
 }
 
-static void
-bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
-{
-	bfa_hb_timer_stop(ioc);
-}
-
-
 /*
  *	Initiate a full firmware download.
  */
@@ -1550,8 +1579,8 @@
 	bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
 	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
 
-	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
-	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+	pgoff = PSS_SMEM_PGOFF(loff);
 
 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
 
@@ -1581,7 +1610,8 @@
 		}
 	}
 
-	writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
+	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
+			ioc->ioc_regs.host_page_num_fn);
 
 	/*
 	 * Set boot type and boot param at the end.
@@ -1592,11 +1622,6 @@
 			swab32(boot_env));
 }
 
-static void
-bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force)
-{
-	bfa_ioc_hwinit(ioc, force);
-}
 
 /*
  * Update BFA configuration from firmware configuration.
@@ -1683,12 +1708,13 @@
 static bfa_status_t
 bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
 {
-	u32 pgnum, loff, r32;
+	u32 pgnum, loff;
+	__be32 r32;
 	int i, len;
 	u32 *buf = tbuf;
 
-	pgnum = bfa_ioc_smem_pgnum(ioc, soff);
-	loff = bfa_ioc_smem_pgoff(ioc, soff);
+	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
+	loff = PSS_SMEM_PGOFF(soff);
 	bfa_trc(ioc, pgnum);
 	bfa_trc(ioc, loff);
 	bfa_trc(ioc, sz);
@@ -1719,11 +1745,12 @@
 			writel(pgnum, ioc->ioc_regs.host_page_num_fn);
 		}
 	}
-	writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
+	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
+			ioc->ioc_regs.host_page_num_fn);
 	/*
 	 *  release semaphore.
 	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 
 	bfa_trc(ioc, pgnum);
 	return BFA_STATUS_OK;
@@ -1742,8 +1769,8 @@
 	int i, len;
 	u32 pgnum, loff;
 
-	pgnum = bfa_ioc_smem_pgnum(ioc, soff);
-	loff = bfa_ioc_smem_pgoff(ioc, soff);
+	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
+	loff = PSS_SMEM_PGOFF(soff);
 	bfa_trc(ioc, pgnum);
 	bfa_trc(ioc, loff);
 	bfa_trc(ioc, sz);
@@ -1773,35 +1800,38 @@
 			writel(pgnum, ioc->ioc_regs.host_page_num_fn);
 		}
 	}
-	writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
+	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
+			ioc->ioc_regs.host_page_num_fn);
 
 	/*
 	 *  release semaphore.
 	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 	bfa_trc(ioc, pgnum);
 	return BFA_STATUS_OK;
 }
 
-/*
- * hal iocpf to ioc interface
- */
 static void
-bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc)
+bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
 {
-	bfa_fsm_send_event(ioc, IOC_E_ENABLED);
-}
+	struct list_head		*qe;
+	struct bfa_ioc_hbfail_notify_s	*notify;
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 
-static void
-bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_DISABLED);
-}
+	/*
+	 * 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_s *) qe;
+		notify->cbfn(notify->cbarg);
+	}
 
-static void
-bfa_ioc_pf_failed(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(ioc, IOC_E_FAILED);
+	bfa_ioc_debug_save_ftrc(ioc);
+
+	BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
+		"Heart Beat of IOC has failed\n");
+
 }
 
 static void
@@ -1817,12 +1847,6 @@
 		"with the driver version\n");
 }
 
-
-
-/*
- *  hal_ioc_public
- */
-
 bfa_status_t
 bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
 {
@@ -1838,7 +1862,7 @@
 	/*
 	 *  release semaphore.
 	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
 
 	return BFA_STATUS_OK;
 }
@@ -1909,7 +1933,7 @@
 void
 bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
 {
-	u32	*msgp = mbmsg;
+	__be32	*msgp = mbmsg;
 	u32	r32;
 	int		i;
 
@@ -1962,7 +1986,7 @@
 
 	default:
 		bfa_trc(ioc, msg->mh.msg_id);
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
@@ -2043,15 +2067,6 @@
 	ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
 }
 
-/*
- * Return size of dma memory required.
- */
-u32
-bfa_ioc_meminfo(void)
-{
-	return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
-}
-
 void
 bfa_ioc_enable(struct bfa_ioc_s *ioc)
 {
@@ -2068,18 +2083,6 @@
 	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
 }
 
-/*
- * Returns memory required for saving firmware trace in case of crash.
- * Driver must call this interface to allocate memory required for
- * automatic saving of firmware trace. Driver should call
- * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this
- * trace memory.
- */
-int
-bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
-{
-	return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
-}
 
 /*
  * Initialize memory for saving firmware trace. Driver must initialize
@@ -2089,19 +2092,7 @@
 bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
 {
 	ioc->dbg_fwsave	    = dbg_fwsave;
-	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover);
-}
-
-u32
-bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr)
-{
-	return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
-}
-
-u32
-bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr)
-{
-	return PSS_SMEM_PGOFF(fmaddr);
+	ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
 }
 
 /*
@@ -2265,14 +2256,13 @@
 }
 
 /*
- * Add to IOC heartbeat failure notification queue. To be used by common
- * modules such as cee, port, diag.
+ * Reset IOC fwstate registers.
  */
 void
-bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
-			struct bfa_ioc_hbfail_notify_s *notify)
+bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)
 {
-	list_add_tail(&notify->qe, &ioc->hb_notify_q);
+	writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+	writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
 }
 
 #define BFA_MFG_NAME "Brocade"
@@ -2306,7 +2296,7 @@
 	else
 		ad_attr->prototype = 0;
 
-	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
+	ad_attr->pwwn = ioc->attr->pwwn;
 	ad_attr->mac  = bfa_ioc_get_mac(ioc);
 
 	ad_attr->pcie_gen = ioc_attr->pcie_gen;
@@ -2317,7 +2307,8 @@
 	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
 
 	ad_attr->cna_capable = ioc->cna;
-	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
+	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna &&
+				!ad_attr->is_mezz;
 }
 
 enum bfa_ioc_type_e
@@ -2330,7 +2321,7 @@
 	else if (ioc->ioc_mc == BFI_MC_LL)
 		return BFA_IOC_TYPE_LL;
 	else {
-		bfa_assert(ioc->ioc_mc == BFI_MC_LL);
+		WARN_ON(ioc->ioc_mc != BFI_MC_LL);
 		return BFA_IOC_TYPE_LL;
 	}
 }
@@ -2354,7 +2345,7 @@
 void
 bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
 {
-	bfa_assert(chip_rev);
+	WARN_ON(!chip_rev);
 
 	memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
 
@@ -2386,7 +2377,7 @@
 {
 	struct bfi_ioc_attr_s	*ioc_attr;
 
-	bfa_assert(model);
+	WARN_ON(!model);
 	memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
 
 	ioc_attr = ioc->attr;
@@ -2455,27 +2446,6 @@
 	bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
 }
 
-/*
- *  hal_wwn_public
- */
-wwn_t
-bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
-{
-	return ioc->attr->pwwn;
-}
-
-wwn_t
-bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc)
-{
-	return ioc->attr->nwwn;
-}
-
-u64
-bfa_ioc_get_adid(struct bfa_ioc_s *ioc)
-{
-	return ioc->attr->mfg_pwwn;
-}
-
 mac_t
 bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
 {
@@ -2488,18 +2458,6 @@
 		return ioc->attr->mac;
 }
 
-wwn_t
-bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc)
-{
-	return ioc->attr->mfg_pwwn;
-}
-
-wwn_t
-bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc)
-{
-	return ioc->attr->mfg_nwwn;
-}
-
 mac_t
 bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
 {
@@ -2541,14 +2499,6 @@
 	return BFA_STATUS_OK;
 }
 
-/*
- * Clear saved firmware trace
- */
-void
-bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc)
-{
-	ioc->dbg_fwsave_once = BFA_TRUE;
-}
 
 /*
  * Retrieve saved firmware trace from a prior IOC failure.
@@ -2701,13 +2651,16 @@
  * Save firmware trace if configured.
  */
 static void
-bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
+bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
 {
 	int		tlen;
 
-	if (ioc->dbg_fwsave_len) {
-		tlen = ioc->dbg_fwsave_len;
-		bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
+	if (ioc->dbg_fwsave_once) {
+		ioc->dbg_fwsave_once = BFA_FALSE;
+		if (ioc->dbg_fwsave_len) {
+			tlen = ioc->dbg_fwsave_len;
+			bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
+		}
 	}
 }
 
@@ -2717,11 +2670,6 @@
 static void
 bfa_ioc_recover(struct bfa_ioc_s *ioc)
 {
-	if (ioc->dbg_fwsave_once) {
-		ioc->dbg_fwsave_once = BFA_FALSE;
-		bfa_ioc_debug_save(ioc);
-	}
-
 	bfa_ioc_stats(ioc, ioc_hbfails);
 	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
 }
@@ -2734,45 +2682,8 @@
 }
 
 /*
- *  hal_iocpf_pvt BFA IOC PF private functions
+ *  BFA IOC PF private functions
  */
-
-static void
-bfa_iocpf_enable(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
-}
-
-static void
-bfa_iocpf_disable(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
-}
-
-static void
-bfa_iocpf_fail(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
-}
-
-static void
-bfa_iocpf_initfail(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
-}
-
-static void
-bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
-}
-
-static void
-bfa_iocpf_stop(struct bfa_ioc_s *ioc)
-{
-	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
-}
-
 static void
 bfa_iocpf_timeout(void *ioc_arg)
 {
@@ -2794,12 +2705,6 @@
  *  bfa timer function
  */
 void
-bfa_timer_init(struct bfa_timer_mod_s *mod)
-{
-	INIT_LIST_HEAD(&mod->timer_q);
-}
-
-void
 bfa_timer_beat(struct bfa_timer_mod_s *mod)
 {
 	struct list_head *qh = &mod->timer_q;
@@ -2843,8 +2748,8 @@
 		    void (*timercb) (void *), void *arg, unsigned int timeout)
 {
 
-	bfa_assert(timercb != NULL);
-	bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
+	WARN_ON(timercb == NULL);
+	WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer));
 
 	timer->timeout = timeout;
 	timer->timercb = timercb;
@@ -2859,7 +2764,7 @@
 void
 bfa_timer_stop(struct bfa_timer_s *timer)
 {
-	bfa_assert(!list_empty(&timer->qe));
+	WARN_ON(list_empty(&timer->qe));
 
 	list_del(&timer->qe);
 }
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 9c407a8..ec9cf08 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -18,10 +18,15 @@
 #ifndef __BFA_IOC_H__
 #define __BFA_IOC_H__
 
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 #include "bfa_cs.h"
 #include "bfi.h"
 
+#define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS)
+#define BFA_DBG_FWTRC_LEN					\
+	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\
+	(sizeof(struct bfa_trc_mod_s) -				\
+	BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
 /*
  * BFA timer declarations
  */
@@ -47,7 +52,6 @@
 #define BFA_TIMER_FREQ 200 /* specified in millisecs */
 
 void bfa_timer_beat(struct bfa_timer_mod_s *mod);
-void bfa_timer_init(struct bfa_timer_mod_s *mod);
 void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
 			bfa_timer_cbfn_t timercb, void *arg,
 			unsigned int timeout);
@@ -70,7 +74,7 @@
 #define bfa_swap_words(_x)  (	\
 	((_x) << 32) | ((_x) >> 32))
 
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 #define bfa_sge_to_be(_x)
 #define bfa_sge_to_le(_x)	bfa_sge_word_swap(_x)
 #define bfa_sgaddr_le(_x)	bfa_swap_words(_x)
@@ -115,8 +119,8 @@
 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) (bfa_os_u32(pa));
+	dma_addr->a32.addr_lo = (__be32) pa;
+	dma_addr->a32.addr_hi = (__be32) (pa >> 32);
 }
 
 
@@ -125,8 +129,8 @@
 static inline void
 __bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
 {
-	dma_addr->a32.addr_lo = (u32) cpu_to_be32(pa);
-	dma_addr->a32.addr_hi = (u32) cpu_to_be32(bfa_os_u32(pa));
+	dma_addr->a32.addr_lo = cpu_to_be32(pa);
+	dma_addr->a32.addr_hi = cpu_to_be32(pa >> 32);
 }
 
 struct bfa_ioc_regs_s {
@@ -145,8 +149,11 @@
 	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;
@@ -254,8 +261,12 @@
 	void		(*ioc_map_port)	(struct bfa_ioc_s *ioc);
 	void		(*ioc_isr_mode_set)	(struct bfa_ioc_s *ioc,
 					bfa_boolean_t msix);
-	void		(*ioc_notify_hbfail)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_notify_fail)	(struct bfa_ioc_s *ioc);
 	void		(*ioc_ownership_reset)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_sync_join)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_sync_leave)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_sync_ack)		(struct bfa_ioc_s *ioc);
+	bfa_boolean_t	(*ioc_sync_complete)	(struct bfa_ioc_s *ioc);
 };
 
 #define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
@@ -325,7 +336,6 @@
 void bfa_ioc_detach(struct bfa_ioc_s *ioc);
 void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
 		enum bfi_mclass mc);
-u32 bfa_ioc_meminfo(void);
 void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa);
 void bfa_ioc_enable(struct bfa_ioc_s *ioc);
 void bfa_ioc_disable(struct bfa_ioc_s *ioc);
@@ -340,6 +350,7 @@
 bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
+void bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc);
 enum bfa_ioc_type_e bfa_ioc_get_type(struct bfa_ioc_s *ioc);
 void bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num);
 void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver);
@@ -353,24 +364,16 @@
 void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr);
 void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
 		struct bfa_adapter_attr_s *ad_attr);
-int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover);
 void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave);
 bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata,
 		int *trclen);
-void bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc);
 bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
 				 int *trclen);
 bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
 	u32 *offset, int *buflen);
-u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
-u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
 void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc);
-void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
-	struct bfa_ioc_hbfail_notify_s *notify);
 bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg);
-void bfa_ioc_sem_release(void __iomem *sem_reg);
-void bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc);
 void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,
 			struct bfi_ioc_image_hdr_s *fwhdr);
 bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
@@ -381,13 +384,8 @@
 /*
  * bfa mfg wwn API functions
  */
-wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc);
-wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc);
 mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc);
-wwn_t bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc);
-wwn_t bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc);
 mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc);
-u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);
 
 /*
  * F/W Image Size & Chunk
@@ -421,7 +419,7 @@
 		return bfi_image_ct_cna_get_chunk(off);	break;
 	case BFI_IMAGE_CB_FC:
 		return bfi_image_cb_fc_get_chunk(off);	break;
-	default: return 0;
+	default: return NULL;
 	}
 }
 
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 9099450..e4a0713 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -15,6 +15,7 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_ioc.h"
 #include "bfi_cbreg.h"
 #include "bfa_defs.h"
@@ -29,10 +30,14 @@
 static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);
 static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc);
 static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
-static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc);
 static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc);
+static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc);
+static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc);
 
-struct bfa_ioc_hwif_s hwif_cb;
+static struct bfa_ioc_hwif_s hwif_cb;
 
 /*
  * Called from bfa_ioc_attach() to map asic specific calls.
@@ -46,8 +51,12 @@
 	hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init;
 	hwif_cb.ioc_map_port = bfa_ioc_cb_map_port;
 	hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set;
-	hwif_cb.ioc_notify_hbfail = bfa_ioc_cb_notify_hbfail;
+	hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail;
 	hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset;
+	hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join;
+	hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave;
+	hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack;
+	hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete;
 
 	ioc->ioc_hwif = &hwif_cb;
 }
@@ -58,6 +67,21 @@
 static bfa_boolean_t
 bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
 {
+	struct bfi_ioc_image_hdr_s fwhdr;
+	uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	if (fwstate == BFI_IOC_UNINIT)
+		return BFA_TRUE;
+
+	bfa_ioc_fwver_get(ioc, &fwhdr);
+
+	if (swab32(fwhdr.exec) == BFI_BOOT_TYPE_NORMAL)
+		return BFA_TRUE;
+
+	bfa_trc(ioc, fwstate);
+	bfa_trc(ioc, fwhdr.exec);
+	writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+
 	return BFA_TRUE;
 }
 
@@ -70,7 +94,7 @@
  * Notify other functions on HB failure.
  */
 static void
-bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)
 {
 	writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
 	readl(ioc->ioc_regs.err_set);
@@ -108,9 +132,11 @@
 	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;
 	} 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);
 	}
 
 	/*
@@ -181,10 +207,71 @@
 	 * will lock it instead of clearing it.
 	 */
 	readl(ioc->ioc_regs.ioc_sem_reg);
-	bfa_ioc_hw_sem_release(ioc);
+	writel(1, ioc->ioc_regs.ioc_sem_reg);
 }
 
+/*
+ * Synchronized IOC failure processing routines
+ */
+static void
+bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc)
+{
+}
 
+static void
+bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc)
+{
+}
+
+static void
+bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc)
+{
+	writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+}
+
+static bfa_boolean_t
+bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
+{
+	uint32_t fwstate, alt_fwstate;
+	fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+	/*
+	 * At this point, this IOC is hoding the hw sem in the
+	 * start path (fwcheck) OR in the disable/enable path
+	 * OR to check if the other IOC has acknowledged failure.
+	 *
+	 * So, this IOC can be in UNINIT, INITING, DISABLED, FAIL
+	 * or in MEMTEST states. In a normal scenario, this IOC
+	 * can not be in OP state when this function is called.
+	 *
+	 * However, this IOC could still be in OP state when
+	 * the OS driver is starting up, if the OptROM code has
+	 * left it in that state.
+	 *
+	 * If we had marked this IOC's fwstate as BFI_IOC_FAIL
+	 * in the failure case and now, if the fwstate is not
+	 * BFI_IOC_FAIL it implies that the other PCI fn have
+	 * reinitialized the ASIC or this IOC got disabled, so
+	 * return TRUE.
+	 */
+	if (fwstate == BFI_IOC_UNINIT ||
+		fwstate == BFI_IOC_INITING ||
+		fwstate == BFI_IOC_DISABLED ||
+		fwstate == BFI_IOC_MEMTEST ||
+		fwstate == BFI_IOC_OP)
+		return BFA_TRUE;
+	else {
+		alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate);
+		if (alt_fwstate == BFI_IOC_FAIL ||
+			alt_fwstate == BFI_IOC_DISABLED ||
+			alt_fwstate == BFI_IOC_UNINIT ||
+			alt_fwstate == BFI_IOC_INITING ||
+			alt_fwstate == BFI_IOC_MEMTEST)
+			return BFA_TRUE;
+		else
+			return BFA_FALSE;
+	}
+}
 
 bfa_status_t
 bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode)
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 115730c..008d129 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -15,12 +15,22 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_ioc.h"
 #include "bfi_ctreg.h"
 #include "bfa_defs.h"
 
 BFA_TRC_FILE(CNA, IOC_CT);
 
+#define bfa_ioc_ct_sync_pos(__ioc)      \
+		((uint32_t) (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
  */
@@ -29,10 +39,14 @@
 static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
-static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc);
+static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc);
+static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc);
 
-struct bfa_ioc_hwif_s hwif_ct;
+static struct bfa_ioc_hwif_s hwif_ct;
 
 /*
  * Called from bfa_ioc_attach() to map asic specific calls.
@@ -46,8 +60,12 @@
 	hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
 	hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
 	hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
-	hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail;
+	hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
 	hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+	hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
+	hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
+	hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
+	hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete;
 
 	ioc->ioc_hwif = &hwif_ct;
 }
@@ -83,7 +101,8 @@
 	 */
 	if (usecnt == 0) {
 		writel(1, ioc->ioc_regs.ioc_usage_reg);
-		bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+		writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
+		writel(0, ioc->ioc_regs.ioc_fail_sync);
 		bfa_trc(ioc, usecnt);
 		return BFA_TRUE;
 	}
@@ -94,14 +113,14 @@
 	/*
 	 * Use count cannot be non-zero and chip in uninitialized state.
 	 */
-	bfa_assert(ioc_fwstate != BFI_IOC_UNINIT);
+	WARN_ON(ioc_fwstate == BFI_IOC_UNINIT);
 
 	/*
 	 * Check if another driver with a different firmware is active
 	 */
 	bfa_ioc_fwver_get(ioc, &fwhdr);
 	if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
-		bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+		writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 		bfa_trc(ioc, usecnt);
 		return BFA_FALSE;
 	}
@@ -111,7 +130,7 @@
 	 */
 	usecnt++;
 	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+	writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 	bfa_trc(ioc, usecnt);
 	return BFA_TRUE;
 }
@@ -139,25 +158,27 @@
 	 */
 	bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
 	usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
-	bfa_assert(usecnt > 0);
+	WARN_ON(usecnt <= 0);
 
 	usecnt--;
 	writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
 	bfa_trc(ioc, usecnt);
 
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+	writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 }
 
 /*
  * Notify other functions on HB failure.
  */
 static void
-bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc)
+bfa_ioc_ct_notify_fail(struct bfa_ioc_s *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);
@@ -209,15 +230,19 @@
 	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;
 	}
 
 	/*
@@ -235,6 +260,7 @@
 	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
@@ -313,7 +339,7 @@
 	if (ioc->cna) {
 		bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
 		writel(0, ioc->ioc_regs.ioc_usage_reg);
-		bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+		writel(1, ioc->ioc_regs.ioc_usage_sem_reg);
 	}
 
 	/*
@@ -322,10 +348,80 @@
 	 * will lock it instead of clearing it.
 	 */
 	readl(ioc->ioc_regs.ioc_sem_reg);
-	bfa_ioc_hw_sem_release(ioc);
+	writel(1, ioc->ioc_regs.ioc_sem_reg);
 }
 
+/*
+ * Synchronized IOC failure processing routines
+ */
+static void
+bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc)
+{
+	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+	uint32_t 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_s *ioc)
+{
+	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+	uint32_t 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_s *ioc)
+{
+	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+
+	writel((r32 | bfa_ioc_ct_sync_pos(ioc)),
+		ioc->ioc_regs.ioc_fail_sync);
+}
+
+static bfa_boolean_t
+bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc)
+{
+	uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+	uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+	uint32_t sync_ackd = bfa_ioc_ct_get_sync_ackd(r32);
+	uint32_t tmp_ackd;
+
+	if (sync_ackd == 0)
+		return BFA_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 BFA_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 BFA_FALSE;
+}
 
 /*
  * Check the firmware state to know if pll_init has been completed already
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index 15407ab..ab79ff6 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -99,7 +99,6 @@
 	void (*iocdisable) (struct bfa_s *bfa);
 };
 
-extern struct bfa_module_s *hal_mods[];
 
 struct bfa_s {
 	void			*bfad;		/*  BFA driver instance    */
@@ -116,8 +115,6 @@
 	struct bfa_msix_s	msix;
 };
 
-extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
-extern bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[];
 extern bfa_boolean_t bfa_auto_recover;
 extern struct bfa_module_s hal_mod_sgpg;
 extern struct bfa_module_s hal_mod_fcport;
diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h
deleted file mode 100644
index 65df62e..0000000
--- a/drivers/scsi/bfa/bfa_os_inc.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_OS_INC_H__
-#define __BFA_OS_INC_H__
-
-#include <linux/types.h>
-#include <linux/version.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/idr.h>
-#include <linux/interrupt.h>
-#include <linux/cdev.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/vmalloc.h>
-#include <linux/workqueue.h>
-#include <linux/bitops.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_transport_fc.h>
-#include <scsi/scsi_transport.h>
-
-#ifdef __BIG_ENDIAN
-#define __BIGENDIAN
-#endif
-
-static inline u64 bfa_os_get_log_time(void)
-{
-	u64 system_time = 0;
-	struct timeval tv;
-	do_gettimeofday(&tv);
-
-	/* We are interested in seconds only. */
-	system_time = tv.tv_sec;
-	return system_time;
-}
-
-#define bfa_io_lat_clock_res_div HZ
-#define bfa_io_lat_clock_res_mul 1000
-
-#define BFA_LOG(level, bfad, mask, fmt, arg...)				\
-do {									\
-	if (((mask) == 4) || (level[1] <= '4'))				\
-		dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg);	\
-} while (0)
-
-#define bfa_swap_3b(_x)				\
-	((((_x) & 0xff) << 16) |		\
-	((_x) & 0x00ff00) |			\
-	(((_x) & 0xff0000) >> 16))
-
-#define bfa_os_swap_sgaddr(_x)  ((u64)(                                 \
-	(((u64)(_x) & (u64)0x00000000000000ffull) << 32)        |       \
-	(((u64)(_x) & (u64)0x000000000000ff00ull) << 32)        |       \
-	(((u64)(_x) & (u64)0x0000000000ff0000ull) << 32)        |       \
-	(((u64)(_x) & (u64)0x00000000ff000000ull) << 32)        |       \
-	(((u64)(_x) & (u64)0x000000ff00000000ull) >> 32)        |       \
-	(((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32)        |       \
-	(((u64)(_x) & (u64)0x00ff000000000000ull) >> 32)        |       \
-	(((u64)(_x) & (u64)0xff00000000000000ull) >> 32)))
-
-#ifndef __BIGENDIAN
-#define bfa_os_hton3b(_x)  bfa_swap_3b(_x)
-#define bfa_os_sgaddr(_x)  (_x)
-#else
-#define bfa_os_hton3b(_x)  (_x)
-#define bfa_os_sgaddr(_x)  bfa_os_swap_sgaddr(_x)
-#endif
-
-#define bfa_os_ntoh3b(_x)  bfa_os_hton3b(_x)
-#define bfa_os_u32(__pa64) ((__pa64) >> 32)
-
-#define BFA_TRC_TS(_trcm)				\
-	({						\
-		struct timeval tv;			\
-							\
-		do_gettimeofday(&tv);			\
-		(tv.tv_sec*1000000+tv.tv_usec);		\
-	 })
-
-#define boolean_t int
-
-/*
- * For current time stamp, OS API will fill-in
- */
-struct bfa_timeval_s {
-	u32	tv_sec;		/*  seconds        */
-	u32	tv_usec;	/*  microseconds   */
-};
-
-static inline void
-bfa_os_gettimeofday(struct bfa_timeval_s *tv)
-{
-	struct timeval  tmp_tv;
-
-	do_gettimeofday(&tmp_tv);
-	tv->tv_sec = (u32) tmp_tv.tv_sec;
-	tv->tv_usec = (u32) tmp_tv.tv_usec;
-}
-
-static inline void
-wwn2str(char *wwn_str, u64 wwn)
-{
-	union {
-		u64 wwn;
-		u8 byte[8];
-	} w;
-
-	w.wwn = wwn;
-	sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0],
-		w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5],
-		w.byte[6], w.byte[7]);
-}
-
-static inline void
-fcid2str(char *fcid_str, u32 fcid)
-{
-	union {
-		u32 fcid;
-		u8 byte[4];
-	} f;
-
-	f.fcid = fcid;
-	sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]);
-}
-
-#endif /* __BFA_OS_INC_H__ */
diff --git a/drivers/scsi/bfa/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h
index 501f0ed..1c9baa6 100644
--- a/drivers/scsi/bfa/bfa_plog.h
+++ b/drivers/scsi/bfa/bfa_plog.h
@@ -151,9 +151,5 @@
 void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
 			enum bfa_plog_eid event, u16 misc,
 			struct fchs_s *fchdr, u32 pld_w0);
-void bfa_plog_clear(struct bfa_plog_s *plog);
-void bfa_plog_enable(struct bfa_plog_s *plog);
-void bfa_plog_disable(struct bfa_plog_s *plog);
-bfa_boolean_t	bfa_plog_get_setting(struct bfa_plog_s *plog);
 
 #endif /* __BFA_PORTLOG_H__ */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index fff9622..3f8e9d6 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -15,6 +15,7 @@
  * General Public License for more details.
  */
 
+#include "bfad_drv.h"
 #include "bfa_defs_svc.h"
 #include "bfa_port.h"
 #include "bfi.h"
@@ -29,14 +30,14 @@
 bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
 {
 	u32    *dip = (u32 *) stats;
-	u32    t0, t1;
+	__be32    t0, t1;
 	int	    i;
 
 	for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32);
 		i += 2) {
 		t0 = dip[i];
 		t1 = dip[i + 1];
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 		dip[i] = be32_to_cpu(t0);
 		dip[i + 1] = be32_to_cpu(t1);
 #else
@@ -96,13 +97,13 @@
 	port->stats_busy = BFA_FALSE;
 
 	if (status == BFA_STATUS_OK) {
-		struct bfa_timeval_s tv;
+		struct timeval tv;
 
 		memcpy(port->stats, port->stats_dma.kva,
 		       sizeof(union bfa_port_stats_u));
 		bfa_port_stats_swap(port, port->stats);
 
-		bfa_os_gettimeofday(&tv);
+		do_gettimeofday(&tv);
 		port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time;
 	}
 
@@ -124,7 +125,7 @@
 static void
 bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
 {
-	struct bfa_timeval_s tv;
+	struct timeval tv;
 
 	port->stats_status = status;
 	port->stats_busy   = BFA_FALSE;
@@ -132,7 +133,7 @@
 	/*
 	* re-initialize time stamp for stats reset
 	*/
-	bfa_os_gettimeofday(&tv);
+	do_gettimeofday(&tv);
 	port->stats_reset_time = tv.tv_sec;
 
 	if (port->stats_cbfn) {
@@ -185,7 +186,7 @@
 		break;
 
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
@@ -432,9 +433,9 @@
 bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
 		 void *dev, struct bfa_trc_mod_s *trcmod)
 {
-	struct bfa_timeval_s tv;
+	struct timeval tv;
 
-	bfa_assert(port);
+	WARN_ON(!port);
 
 	port->dev    = dev;
 	port->ioc    = ioc;
@@ -447,27 +448,13 @@
 
 	bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port);
 	bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port);
-	bfa_ioc_hbfail_register(port->ioc, &port->hbfail);
+	list_add_tail(&port->hbfail.qe, &port->ioc->hb_notify_q);
 
 	/*
 	 * initialize time stamp for stats reset
 	 */
-	bfa_os_gettimeofday(&tv);
+	do_gettimeofday(&tv);
 	port->stats_reset_time = tv.tv_sec;
 
 	bfa_trc(port, 0);
 }
-
-/*
- * bfa_port_detach()
- *
- *
- * @param[in] port - Pointer to the Port module data structure
- *
- * @return void
- */
-void
-bfa_port_detach(struct bfa_port_s *port)
-{
-	bfa_trc(port, 0);
-}
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
index dbce9df..c4ee9db 100644
--- a/drivers/scsi/bfa/bfa_port.h
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -48,7 +48,6 @@
 
 void	     bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
 				void *dev, struct bfa_trc_mod_s *trcmod);
-void	     bfa_port_detach(struct bfa_port_s *port);
 void	     bfa_port_hbfail(void *arg);
 
 bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 37e16ac..1d34921 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -15,11 +15,10 @@
  * General Public License for more details.
  */
 
-#include "bfa_os_inc.h"
+#include "bfad_drv.h"
 #include "bfa_plog.h"
 #include "bfa_cs.h"
 #include "bfa_modules.h"
-#include "bfad_drv.h"
 
 BFA_TRC_FILE(HAL, FCXP);
 BFA_MODULE(fcxp);
@@ -41,19 +40,6 @@
 #define BFA_LPS_MAX_VPORTS_SUPP_CB  255
 #define BFA_LPS_MAX_VPORTS_SUPP_CT  190
 
-/*
- *  lps_pvt BFA LPS private functions
- */
-
-enum bfa_lps_event {
-	BFA_LPS_SM_LOGIN	= 1,	/* login request from user	*/
-	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user	*/
-	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout	*/
-	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue	*/
-	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user		*/
-	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline		*/
-	BFA_LPS_SM_RX_CVL	= 7,	/* Rx clear virtual link	*/
-};
 
 /*
  * FC PORT related definitions
@@ -66,7 +52,6 @@
 	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
 	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
 
-
 /*
  * BFA port state machine events
  */
@@ -113,19 +98,6 @@
 		}							\
 } while (0)
 
-
-enum bfa_rport_event {
-	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event		*/
-	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport	*/
-	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online		*/
-	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline		*/
-	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response		*/
-	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure		*/
-	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware	*/
-	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed		*/
-	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue	*/
-};
-
 /*
  * forward declarations FCXP related functions
  */
@@ -159,6 +131,7 @@
 static void bfa_lps_free(struct bfa_lps_s *lps);
 static void bfa_lps_send_login(struct bfa_lps_s *lps);
 static void bfa_lps_send_logout(struct bfa_lps_s *lps);
+static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
 static void bfa_lps_login_comp(struct bfa_lps_s *lps);
 static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
 static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
@@ -171,6 +144,8 @@
 static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
 					event);
 static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
+					enum bfa_lps_event event);
 static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
 static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
 					event);
@@ -312,6 +287,18 @@
 	return 0;
 }
 
+static u64
+bfa_get_log_time(void)
+{
+	u64 system_time = 0;
+	struct timeval tv;
+	do_gettimeofday(&tv);
+
+	/* We are interested in seconds only. */
+	system_time = tv.tv_sec;
+	return system_time;
+}
+
 static void
 bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
 {
@@ -322,7 +309,7 @@
 		return;
 
 	if (plkd_validate_logrec(pl_rec)) {
-		bfa_assert(0);
+		WARN_ON(1);
 		return;
 	}
 
@@ -332,7 +319,7 @@
 
 	memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
 
-	pl_recp->tv = bfa_os_get_log_time();
+	pl_recp->tv = bfa_get_log_time();
 	BFA_PL_LOG_REC_INCR(plog->tail);
 
 	if (plog->head == plog->tail)
@@ -437,29 +424,6 @@
 	}
 }
 
-void
-bfa_plog_clear(struct bfa_plog_s *plog)
-{
-	plog->head = plog->tail = 0;
-}
-
-void
-bfa_plog_enable(struct bfa_plog_s *plog)
-{
-	plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_disable(struct bfa_plog_s *plog)
-{
-	plog->plog_enabled = 0;
-}
-
-bfa_boolean_t
-bfa_plog_get_setting(struct bfa_plog_s *plog)
-{
-	return (bfa_boolean_t)plog->plog_enabled;
-}
 
 /*
  *  fcxp_pvt BFA FCXP private functions
@@ -637,15 +601,15 @@
 	       bfa_fcxp_get_sglen_t sglen_cbfn)
 {
 
-	bfa_assert(bfa != NULL);
+	WARN_ON(bfa == NULL);
 
 	bfa_trc(bfa, fcxp->fcxp_tag);
 
 	if (n_sgles == 0) {
 		*use_ibuf = 1;
 	} else {
-		bfa_assert(*sga_cbfn != NULL);
-		bfa_assert(*sglen_cbfn != NULL);
+		WARN_ON(*sga_cbfn == NULL);
+		WARN_ON(*sglen_cbfn == NULL);
 
 		*use_ibuf = 0;
 		*r_sga_cbfn = sga_cbfn;
@@ -657,7 +621,7 @@
 		 * alloc required sgpgs
 		 */
 		if (n_sgles > BFI_SGE_INLINE)
-			bfa_assert(0);
+			WARN_ON(1);
 	}
 
 }
@@ -671,7 +635,7 @@
 	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
 {
 
-	bfa_assert(bfa != NULL);
+	WARN_ON(bfa == NULL);
 
 	bfa_trc(bfa, fcxp->fcxp_tag);
 
@@ -708,7 +672,7 @@
 		return;
 	}
 
-	bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
+	WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
 	list_del(&fcxp->qe);
 	list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
 }
@@ -757,7 +721,7 @@
 
 	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
 
-	bfa_assert(fcxp->send_cbfn != NULL);
+	WARN_ON(fcxp->send_cbfn == NULL);
 
 	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
 
@@ -913,13 +877,13 @@
 					BFA_FCXP_REQ_PLD_PA(fcxp));
 	} else {
 		if (fcxp->nreq_sgles > 0) {
-			bfa_assert(fcxp->nreq_sgles == 1);
+			WARN_ON(fcxp->nreq_sgles != 1);
 			hal_fcxp_set_local_sges(send_req->req_sge,
 						reqi->req_tot_len,
 						fcxp->req_sga_cbfn(fcxp->caller,
 								   0));
 		} else {
-			bfa_assert(reqi->req_tot_len == 0);
+			WARN_ON(reqi->req_tot_len != 0);
 			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
 		}
 	}
@@ -928,20 +892,20 @@
 	 * setup rsp sgles
 	 */
 	if (fcxp->use_irspbuf == 1) {
-		bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
+		WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
 
 		hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
 					BFA_FCXP_RSP_PLD_PA(fcxp));
 
 	} else {
 		if (fcxp->nrsp_sgles > 0) {
-			bfa_assert(fcxp->nrsp_sgles == 1);
+			WARN_ON(fcxp->nrsp_sgles != 1);
 			hal_fcxp_set_local_sges(send_req->rsp_sge,
 						rspi->rsp_maxlen,
 						fcxp->rsp_sga_cbfn(fcxp->caller,
 								   0));
 		} else {
-			bfa_assert(rspi->rsp_maxlen == 0);
+			WARN_ON(rspi->rsp_maxlen != 0);
 			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
 		}
 	}
@@ -955,10 +919,6 @@
 }
 
 /*
- *  hal_fcxp_api BFA FCXP API
- */
-
-/*
  * Allocate an FCXP instance to send a response or to send a request
  * that has a response. Request/response buffers are allocated by caller.
  *
@@ -990,7 +950,7 @@
 {
 	struct bfa_fcxp_s *fcxp = NULL;
 
-	bfa_assert(bfa != NULL);
+	WARN_ON(bfa == NULL);
 
 	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
 	if (fcxp == NULL)
@@ -1017,7 +977,7 @@
 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 	void	*reqbuf;
 
-	bfa_assert(fcxp->use_ireqbuf == 1);
+	WARN_ON(fcxp->use_ireqbuf != 1);
 	reqbuf = ((u8 *)mod->req_pld_list_kva) +
 		fcxp->fcxp_tag * mod->req_pld_sz;
 	return reqbuf;
@@ -1044,7 +1004,7 @@
 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 	void	*rspbuf;
 
-	bfa_assert(fcxp->use_irspbuf == 1);
+	WARN_ON(fcxp->use_irspbuf != 1);
 
 	rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
 		fcxp->fcxp_tag * mod->rsp_pld_sz;
@@ -1052,7 +1012,7 @@
 }
 
 /*
- *		Free the BFA FCXP
+ * Free the BFA FCXP
  *
  * @param[in]	fcxp			BFA fcxp pointer
  *
@@ -1063,7 +1023,7 @@
 {
 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 
-	bfa_assert(fcxp != NULL);
+	WARN_ON(fcxp == NULL);
 	bfa_trc(mod->bfa, fcxp->fcxp_tag);
 	bfa_fcxp_put(fcxp);
 }
@@ -1142,7 +1102,7 @@
 bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
 {
 	bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
-	bfa_assert(0);
+	WARN_ON(1);
 	return BFA_STATUS_OK;
 }
 
@@ -1157,7 +1117,7 @@
 {
 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 
-	bfa_assert(list_empty(&mod->fcxp_free_q));
+	WARN_ON(!list_empty(&mod->fcxp_free_q));
 
 	wqe->alloc_cbfn = alloc_cbfn;
 	wqe->alloc_cbarg = alloc_cbarg;
@@ -1178,7 +1138,7 @@
 {
 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
 
-	bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
+	WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe));
 	list_del(&wqe->qe);
 }
 
@@ -1199,12 +1159,6 @@
 	fcxp->send_cbfn = bfa_fcxp_null_comp;
 }
 
-
-
-/*
- *  hal_fcxp_public BFA FCXP public functions
- */
-
 void
 bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
 {
@@ -1215,7 +1169,7 @@
 
 	default:
 		bfa_trc(bfa, msg->mhdr.msg_id);
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
@@ -1303,6 +1257,12 @@
 			else
 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
 					BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
+			/* If N2N, send the assigned PID to FW */
+			bfa_trc(lps->bfa, lps->fport);
+			bfa_trc(lps->bfa, lps->lp_pid);
+
+			if (!lps->fport && lps->lp_pid)
+				bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
 		} else {
 			bfa_sm_set_state(lps, bfa_lps_sm_init);
 			if (lps->fdisc)
@@ -1321,6 +1281,11 @@
 		bfa_sm_set_state(lps, bfa_lps_sm_init);
 		break;
 
+	case BFA_LPS_SM_SET_N2N_PID:
+		bfa_trc(lps->bfa, lps->fport);
+		bfa_trc(lps->bfa, lps->lp_pid);
+		break;
+
 	default:
 		bfa_sm_fault(lps->bfa, event);
 	}
@@ -1389,6 +1354,14 @@
 			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
 		break;
 
+	case BFA_LPS_SM_SET_N2N_PID:
+		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+			bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
+			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+		} else
+			bfa_lps_send_set_n2n_pid(lps);
+		break;
+
 	case BFA_LPS_SM_OFFLINE:
 	case BFA_LPS_SM_DELETE:
 		bfa_sm_set_state(lps, bfa_lps_sm_init);
@@ -1400,6 +1373,48 @@
 }
 
 /*
+ * login complete
+ */
+static void
+bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_RESUME:
+		bfa_sm_set_state(lps, bfa_lps_sm_online);
+		bfa_lps_send_set_n2n_pid(lps);
+		break;
+
+	case BFA_LPS_SM_LOGOUT:
+		bfa_sm_set_state(lps, bfa_lps_sm_logowait);
+		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+			BFA_PL_EID_LOGO, 0, "Logout");
+		break;
+
+	case BFA_LPS_SM_RX_CVL:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_reqq_wcancel(&lps->wqe);
+
+		/* Let the vport module know about this event */
+		bfa_lps_cvl_event(lps);
+		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+	case BFA_LPS_SM_DELETE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_reqq_wcancel(&lps->wqe);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/*
  * logout in progress - awaiting firmware response
  */
 static void
@@ -1540,15 +1555,16 @@
 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
 	struct bfa_lps_s	*lps;
 
-	bfa_assert(rsp->lp_tag < mod->num_lps);
+	WARN_ON(rsp->lp_tag >= mod->num_lps);
 	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
 
 	lps->status = rsp->status;
 	switch (rsp->status) {
 	case BFA_STATUS_OK:
 		lps->fport	= rsp->f_port;
+		if (lps->fport)
+			lps->lp_pid = rsp->lp_pid;
 		lps->npiv_en	= rsp->npiv_en;
-		lps->lp_pid	= rsp->lp_pid;
 		lps->pr_bbcred	= be16_to_cpu(rsp->bb_credit);
 		lps->pr_pwwn	= rsp->port_name;
 		lps->pr_nwwn	= rsp->node_name;
@@ -1587,7 +1603,7 @@
 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
 	struct bfa_lps_s	*lps;
 
-	bfa_assert(rsp->lp_tag < mod->num_lps);
+	WARN_ON(rsp->lp_tag >= mod->num_lps);
 	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
 
 	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
@@ -1640,7 +1656,7 @@
 	struct bfi_lps_login_req_s	*m;
 
 	m = bfa_reqq_next(lps->bfa, lps->reqq);
-	bfa_assert(m);
+	WARN_ON(!m);
 
 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
 		bfa_lpuid(lps->bfa));
@@ -1665,7 +1681,7 @@
 	struct bfi_lps_logout_req_s *m;
 
 	m = bfa_reqq_next(lps->bfa, lps->reqq);
-	bfa_assert(m);
+	WARN_ON(!m);
 
 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
 		bfa_lpuid(lps->bfa));
@@ -1676,6 +1692,25 @@
 }
 
 /*
+ * send n2n pid set request to firmware
+ */
+static void
+bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
+{
+	struct bfi_lps_n2n_pid_req_s *m;
+
+	m = bfa_reqq_next(lps->bfa, lps->reqq);
+	WARN_ON(!m);
+
+	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
+		bfa_lpuid(lps->bfa));
+
+	m->lp_tag = lps->lp_tag;
+	m->lp_pid = lps->lp_pid;
+	bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/*
  * Indirect login completion handler for non-fcs
  */
 static void
@@ -1853,14 +1888,6 @@
 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
 }
 
-/*
- * Initiate a lport logout (flogi).
- */
-void
-bfa_lps_flogo(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
 
 /*
  * Initiate a lport FDSIC logout.
@@ -1871,24 +1898,6 @@
 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
 }
 
-/*
- * Discard a pending login request -- should be called only for
- * link down handling.
- */
-void
-bfa_lps_discard(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
-}
-
-/*
- * Return lport services tag
- */
-u8
-bfa_lps_get_tag(struct bfa_lps_s *lps)
-{
-	return lps->lp_tag;
-}
 
 /*
  * Return lport services tag given the pid
@@ -1909,55 +1918,6 @@
 	return 0;
 }
 
-/*
- * return if fabric login indicates support for NPIV
- */
-bfa_boolean_t
-bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
-{
-	return lps->npiv_en;
-}
-
-/*
- * Return TRUE if attached to F-Port, else return FALSE
- */
-bfa_boolean_t
-bfa_lps_is_fport(struct bfa_lps_s *lps)
-{
-	return lps->fport;
-}
-
-/*
- * Return TRUE if attached to a Brocade Fabric
- */
-bfa_boolean_t
-bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
-{
-	return lps->brcd_switch;
-}
-/*
- * return TRUE if authentication is required
- */
-bfa_boolean_t
-bfa_lps_is_authreq(struct bfa_lps_s *lps)
-{
-	return lps->auth_req;
-}
-
-bfa_eproto_status_t
-bfa_lps_get_extstatus(struct bfa_lps_s *lps)
-{
-	return lps->ext_status;
-}
-
-/*
- * return port id assigned to the lport
- */
-u32
-bfa_lps_get_pid(struct bfa_lps_s *lps)
-{
-	return lps->lp_pid;
-}
 
 /*
  * return port id assigned to the base lport
@@ -1971,57 +1931,16 @@
 }
 
 /*
- * Return bb_credit assigned in FLOGI response
+ * Set PID in case of n2n (which is assigned during PLOGI)
  */
-u16
-bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
+void
+bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
 {
-	return lps->pr_bbcred;
-}
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, n2n_pid);
 
-/*
- * Return peer port name
- */
-wwn_t
-bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
-{
-	return lps->pr_pwwn;
-}
-
-/*
- * Return peer node name
- */
-wwn_t
-bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
-{
-	return lps->pr_nwwn;
-}
-
-/*
- * return reason code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
-{
-	return lps->lsrjt_rsn;
-}
-
-/*
- * return explanation code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
-{
-	return lps->lsrjt_expl;
-}
-
-/*
- * Return fpma/spma MAC for lport
- */
-mac_t
-bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
-{
-	return lps->lp_mac;
+	lps->lp_pid = n2n_pid;
+	bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
 }
 
 /*
@@ -2050,7 +1969,7 @@
 
 	default:
 		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
@@ -2068,6 +1987,8 @@
 		/*
 		 * Start event after IOC is configured and BFA is started.
 		 */
+		fcport->use_flash_cfg = BFA_TRUE;
+
 		if (bfa_fcport_send_enable(fcport)) {
 			bfa_trc(fcport->bfa, BFA_TRUE);
 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
@@ -2178,7 +2099,7 @@
 		bfa_fcport_update_linkinfo(fcport);
 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
 
-		bfa_assert(fcport->event_cbfn);
+		WARN_ON(!fcport->event_cbfn);
 		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
 		break;
 
@@ -2229,7 +2150,7 @@
 	case BFA_FCPORT_SM_LINKUP:
 		bfa_fcport_update_linkinfo(fcport);
 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
-		bfa_assert(fcport->event_cbfn);
+		WARN_ON(!fcport->event_cbfn);
 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
 				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
 		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
@@ -2803,12 +2724,6 @@
 	}
 }
 
-
-
-/*
- *  hal_port_private
- */
-
 static void
 __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
 {
@@ -2839,7 +2754,7 @@
 		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
 		break;
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
@@ -2906,7 +2821,7 @@
 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
 	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
 	struct bfa_fcport_ln_s *ln = &fcport->ln;
-	struct bfa_timeval_s tv;
+	struct timeval tv;
 
 	memset(fcport, 0, sizeof(struct bfa_fcport_s));
 	fcport->bfa = bfa;
@@ -2920,7 +2835,7 @@
 	/*
 	 * initialize time stamp for stats reset
 	 */
-	bfa_os_gettimeofday(&tv);
+	do_gettimeofday(&tv);
 	fcport->stats_reset_time = tv.tv_sec;
 
 	/*
@@ -3039,6 +2954,7 @@
 	m->port_cfg = fcport->cfg;
 	m->msgtag = fcport->msgtag;
 	m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
+	 m->use_flash_cfg = fcport->use_flash_cfg;
 	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
 	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
 	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
@@ -3089,8 +3005,8 @@
 static void
 bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
 {
-	fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
-	fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
+	fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
+	fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
 
 	bfa_trc(fcport->bfa, fcport->pwwn);
 	bfa_trc(fcport->bfa, fcport->nwwn);
@@ -3127,7 +3043,7 @@
 	struct bfa_qos_stats_s *s)
 {
 	u32	*dip = (u32 *) d;
-	u32	*sip = (u32 *) s;
+	__be32	*sip = (__be32 *) s;
 	int		i;
 
 	/* Now swap the 32 bit fields */
@@ -3140,12 +3056,12 @@
 	struct bfa_fcoe_stats_s *s)
 {
 	u32	*dip = (u32 *) d;
-	u32	*sip = (u32 *) s;
+	__be32	*sip = (__be32 *) s;
 	int		i;
 
 	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
 	     i = i + 2) {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 		dip[i] = be32_to_cpu(sip[i]);
 		dip[i + 1] = be32_to_cpu(sip[i + 1]);
 #else
@@ -3162,7 +3078,7 @@
 
 	if (complete) {
 		if (fcport->stats_status == BFA_STATUS_OK) {
-			struct bfa_timeval_s tv;
+			struct timeval tv;
 
 			/* Swap FC QoS or FCoE stats */
 			if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
@@ -3174,7 +3090,7 @@
 					&fcport->stats_ret->fcoe,
 					&fcport->stats->fcoe);
 
-				bfa_os_gettimeofday(&tv);
+				do_gettimeofday(&tv);
 				fcport->stats_ret->fcoe.secs_reset =
 					tv.tv_sec - fcport->stats_reset_time;
 			}
@@ -3233,12 +3149,12 @@
 	struct bfa_fcport_s *fcport = cbarg;
 
 	if (complete) {
-		struct bfa_timeval_s tv;
+		struct timeval tv;
 
 		/*
 		 * re-initialize time stamp for stats reset
 		 */
-		bfa_os_gettimeofday(&tv);
+		do_gettimeofday(&tv);
 		fcport->stats_reset_time = tv.tv_sec;
 
 		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
@@ -3303,8 +3219,8 @@
 	int link_bm = 0;
 
 	bfa_trc(fcport->bfa, fcport->cfg.trunked);
-	bfa_assert(scn->trunk_state == BFA_TRUNK_ONLINE ||
-		   scn->trunk_state == BFA_TRUNK_OFFLINE);
+	WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
+		   scn->trunk_state != BFA_TRUNK_OFFLINE);
 
 	bfa_trc(fcport->bfa, trunk->attr.state);
 	bfa_trc(fcport->bfa, scn->trunk_state);
@@ -3396,12 +3312,6 @@
 	}
 }
 
-
-
-/*
- *  hal_port_public
- */
-
 /*
  * Called to initialize port attributes
  */
@@ -3419,9 +3329,9 @@
 	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
 	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
 
-	bfa_assert(fcport->cfg.maxfrsize);
-	bfa_assert(fcport->cfg.rx_bbcredit);
-	bfa_assert(fcport->speed_sup);
+	WARN_ON(!fcport->cfg.maxfrsize);
+	WARN_ON(!fcport->cfg.rx_bbcredit);
+	WARN_ON(!fcport->speed_sup);
 }
 
 /*
@@ -3441,8 +3351,28 @@
 
 	switch (msg->mhdr.msg_id) {
 	case BFI_FCPORT_I2H_ENABLE_RSP:
-		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
+
+			if (fcport->use_flash_cfg) {
+				fcport->cfg = i2hmsg.penable_rsp->port_cfg;
+				fcport->cfg.maxfrsize =
+					cpu_to_be16(fcport->cfg.maxfrsize);
+				fcport->cfg.path_tov =
+					cpu_to_be16(fcport->cfg.path_tov);
+				fcport->cfg.q_depth =
+					cpu_to_be16(fcport->cfg.q_depth);
+
+				if (fcport->cfg.trunked)
+					fcport->trunk.attr.state =
+						BFA_TRUNK_OFFLINE;
+				else
+					fcport->trunk.attr.state =
+						BFA_TRUNK_DISABLED;
+				fcport->use_flash_cfg = BFA_FALSE;
+			}
+
 			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+		}
 		break;
 
 	case BFI_FCPORT_I2H_DISABLE_RSP:
@@ -3498,17 +3428,11 @@
 		break;
 
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 	break;
 	}
 }
 
-
-
-/*
- *  hal_port_api
- */
-
 /*
  * Registered callback for port events.
  */
@@ -3732,8 +3656,8 @@
 	attr->nwwn = fcport->nwwn;
 	attr->pwwn = fcport->pwwn;
 
-	attr->factorypwwn =  bfa_ioc_get_mfg_pwwn(&bfa->ioc);
-	attr->factorynwwn =  bfa_ioc_get_mfg_nwwn(&bfa->ioc);
+	attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
+	attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
 
 	memcpy(&attr->pport_cfg, &fcport->cfg,
 		sizeof(struct bfa_port_cfg_s));
@@ -3751,7 +3675,7 @@
 	/* beacon attributes */
 	attr->beacon = fcport->beacon;
 	attr->link_e2e_beacon = fcport->link_e2e_beacon;
-	attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
+	attr->plog_enabled = (bfa_boolean_t)fcport->bfa->plog->plog_enabled;
 	attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
 
 	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
@@ -3818,89 +3742,6 @@
 	return BFA_STATUS_OK;
 }
 
-/*
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-	bfa_cb_port_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FC mode */
-	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/*
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FC mode */
-	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-/*
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-	bfa_cb_port_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FCoE mode */
-	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/*
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FCoE mode */
-	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-void
-bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	qos_attr->state = fcport->qos_attr.state;
-	qos_attr->total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr);
-}
-
-void
-bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
-	struct bfa_qos_vc_attr_s *qos_vc_attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
-	u32 i = 0;
-
-	qos_vc_attr->total_vc_count = be16_to_cpu(bfa_vc_attr->total_vc_count);
-	qos_vc_attr->shared_credit  = be16_to_cpu(bfa_vc_attr->shared_credit);
-	qos_vc_attr->elp_opmode_flags  =
-			be32_to_cpu(bfa_vc_attr->elp_opmode_flags);
-
-	/* Individual VC info */
-	while (i < qos_vc_attr->total_vc_count) {
-		qos_vc_attr->vc_info[i].vc_credit	=
-				bfa_vc_attr->vc_info[i].vc_credit;
-		qos_vc_attr->vc_info[i].borrow_credit	=
-				bfa_vc_attr->vc_info[i].borrow_credit;
-		qos_vc_attr->vc_info[i].priority	=
-				bfa_vc_attr->vc_info[i].priority;
-		++i;
-	}
-}
 
 /*
  * Fetch port attributes.
@@ -3924,60 +3765,6 @@
 
 }
 
-void
-bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
-
-	bfa_trc(bfa, on_off);
-	bfa_trc(bfa, fcport->cfg.qos_enabled);
-
-	bfa_trc(bfa, ioc_type);
-
-	if (ioc_type == BFA_IOC_TYPE_FC) {
-		fcport->cfg.qos_enabled = on_off;
-		/*
-		 * Notify fcpim of the change in QoS state
-		 */
-		bfa_fcpim_update_ioredirect(bfa);
-	}
-}
-
-void
-bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, on_off);
-	bfa_trc(bfa, fcport->cfg.ratelimit);
-
-	fcport->cfg.ratelimit = on_off;
-	if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
-		fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
-}
-
-/*
- * Configure default minimum ratelim speed
- */
-bfa_status_t
-bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, speed);
-
-	/* Auto and speeds greater than the supported speed, are invalid */
-	if ((speed == BFA_PORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
-		bfa_trc(bfa, fcport->speed_sup);
-		return BFA_STATUS_UNSUPP_SPEED;
-	}
-
-	fcport->cfg.trl_def_speed = speed;
-
-	return BFA_STATUS_OK;
-}
-
 /*
  * Get default minimum ratelim speed
  */
@@ -3990,32 +3777,6 @@
 	return fcport->cfg.trl_def_speed;
 
 }
-void
-bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, status);
-	bfa_trc(bfa, fcport->diag_busy);
-
-	fcport->diag_busy = status;
-}
-
-void
-bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
-	bfa_boolean_t link_e2e_beacon)
-{
-	struct bfa_s *bfa = dev;
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, beacon);
-	bfa_trc(bfa, link_e2e_beacon);
-	bfa_trc(bfa, fcport->beacon);
-	bfa_trc(bfa, fcport->link_e2e_beacon);
-
-	fcport->beacon = beacon;
-	fcport->link_e2e_beacon = link_e2e_beacon;
-}
 
 bfa_boolean_t
 bfa_fcport_is_linkup(struct bfa_s *bfa)
@@ -4036,63 +3797,6 @@
 	return fcport->cfg.qos_enabled;
 }
 
-bfa_status_t
-bfa_trunk_get_attr(struct bfa_s *bfa, struct bfa_trunk_attr_s *attr)
-
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
-	bfa_trc(bfa, fcport->cfg.trunked);
-	bfa_trc(bfa, trunk->attr.state);
-	*attr = trunk->attr;
-	attr->port_id = bfa_lps_get_base_pid(bfa);
-
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_trunk_enable_cfg(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
-	bfa_trc(bfa, 1);
-	trunk->attr.state = BFA_TRUNK_OFFLINE;
-	fcport->cfg.trunked = BFA_TRUE;
-}
-
-bfa_status_t
-bfa_trunk_enable(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
-	bfa_trc(bfa, 1);
-
-	trunk->attr.state   = BFA_TRUNK_OFFLINE;
-	bfa_fcport_disable(bfa);
-	fcport->cfg.trunked = BFA_TRUE;
-	bfa_fcport_enable(bfa);
-
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_trunk_disable(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
-
-	bfa_trc(bfa, 0);
-	trunk->attr.state   = BFA_TRUNK_DISABLED;
-	bfa_fcport_disable(bfa);
-	fcport->cfg.trunked = BFA_FALSE;
-	bfa_fcport_enable(bfa);
-	return BFA_STATUS_OK;
-}
-
-
 /*
  * Rport State machine functions
  */
@@ -4606,8 +4310,8 @@
 	mod->rps_list = rp;
 	mod->num_rports = cfg->fwcfg.num_rports;
 
-	bfa_assert(mod->num_rports &&
-		   !(mod->num_rports & (mod->num_rports - 1)));
+	WARN_ON(!mod->num_rports ||
+		   (mod->num_rports & (mod->num_rports - 1)));
 
 	for (i = 0; i < mod->num_rports; i++, rp++) {
 		memset(rp, 0, sizeof(struct bfa_rport_s));
@@ -4675,7 +4379,7 @@
 {
 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
 
-	bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
+	WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
 	list_del(&rport->qe);
 	list_add_tail(&rport->qe, &mod->rp_free_q);
 }
@@ -4788,13 +4492,13 @@
 		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
 		rp->fw_handle = msg.create_rsp->fw_handle;
 		rp->qos_attr = msg.create_rsp->qos_attr;
-		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
 		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
 		break;
 
 	case BFI_RPORT_I2H_DELETE_RSP:
 		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
-		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
 		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
 		break;
 
@@ -4806,7 +4510,7 @@
 
 	default:
 		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
@@ -4828,24 +4532,18 @@
 
 	rp->bfa = bfa;
 	rp->rport_drv = rport_drv;
-	bfa_rport_clear_stats(rp);
+	memset(&rp->stats, 0, sizeof(rp->stats));
 
-	bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
+	WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
 	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
 
 	return rp;
 }
 
 void
-bfa_rport_delete(struct bfa_rport_s *rport)
-{
-	bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
-}
-
-void
 bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
 {
-	bfa_assert(rport_info->max_frmsz != 0);
+	WARN_ON(rport_info->max_frmsz == 0);
 
 	/*
 	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
@@ -4861,43 +4559,15 @@
 }
 
 void
-bfa_rport_offline(struct bfa_rport_s *rport)
-{
-	bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
-}
-
-void
 bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
 {
-	bfa_assert(speed != 0);
-	bfa_assert(speed != BFA_PORT_SPEED_AUTO);
+	WARN_ON(speed == 0);
+	WARN_ON(speed == BFA_PORT_SPEED_AUTO);
 
 	rport->rport_info.speed = speed;
 	bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
 }
 
-void
-bfa_rport_get_stats(struct bfa_rport_s *rport,
-	struct bfa_rport_hal_stats_s *stats)
-{
-	*stats = rport->stats;
-}
-
-void
-bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
-					struct bfa_rport_qos_attr_s *qos_attr)
-{
-	qos_attr->qos_priority  = rport->qos_attr.qos_priority;
-	qos_attr->qos_flow_id  = be32_to_cpu(rport->qos_attr.qos_flow_id);
-
-}
-
-void
-bfa_rport_clear_stats(struct bfa_rport_s *rport)
-{
-	memset(&rport->stats, 0, sizeof(rport->stats));
-}
-
 
 /*
  * SGPG related functions
@@ -4952,7 +4622,7 @@
 	sgpg_pa.pa = mod->sgpg_arr_pa;
 	mod->free_sgpgs = mod->num_sgpgs;
 
-	bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
+	WARN_ON(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1));
 
 	for (i = 0; i < mod->num_sgpgs; i++) {
 		memset(hsgpg, 0, sizeof(*hsgpg));
@@ -4993,12 +4663,6 @@
 {
 }
 
-
-
-/*
- *  hal_sgpg_public BFA SGPG public functions
- */
-
 bfa_status_t
 bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
 {
@@ -5006,14 +4670,12 @@
 	struct bfa_sgpg_s *hsgpg;
 	int i;
 
-	bfa_trc_fp(bfa, nsgpgs);
-
 	if (mod->free_sgpgs < nsgpgs)
 		return BFA_STATUS_ENOMEM;
 
 	for (i = 0; i < nsgpgs; i++) {
 		bfa_q_deq(&mod->sgpg_q, &hsgpg);
-		bfa_assert(hsgpg);
+		WARN_ON(!hsgpg);
 		list_add_tail(&hsgpg->qe, sgpg_q);
 	}
 
@@ -5027,10 +4689,8 @@
 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
 	struct bfa_sgpg_wqe_s *wqe;
 
-	bfa_trc_fp(bfa, nsgpg);
-
 	mod->free_sgpgs += nsgpg;
-	bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
+	WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
 
 	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
 
@@ -5060,8 +4720,8 @@
 {
 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
 
-	bfa_assert(nsgpg > 0);
-	bfa_assert(nsgpg > mod->free_sgpgs);
+	WARN_ON(nsgpg <= 0);
+	WARN_ON(nsgpg <= mod->free_sgpgs);
 
 	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
 
@@ -5072,7 +4732,7 @@
 		/*
 		 * no one else is waiting for SGPG
 		 */
-		bfa_assert(list_empty(&mod->sgpg_wait_q));
+		WARN_ON(!list_empty(&mod->sgpg_wait_q));
 		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
 		wqe->nsgpg -= mod->free_sgpgs;
 		mod->free_sgpgs = 0;
@@ -5086,7 +4746,7 @@
 {
 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
 
-	bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
+	WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
 	list_del(&wqe->qe);
 
 	if (wqe->nsgpg_total != wqe->nsgpg)
@@ -5318,7 +4978,7 @@
 	uf->data_ptr = buf;
 	uf->data_len = m->xfr_len;
 
-	bfa_assert(uf->data_len >= sizeof(struct fchs_s));
+	WARN_ON(uf->data_len < sizeof(struct fchs_s));
 
 	if (uf->data_len == sizeof(struct fchs_s)) {
 		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
@@ -5361,12 +5021,6 @@
 	bfa_uf_post_all(BFA_UF_MOD(bfa));
 }
 
-
-
-/*
- *  hal_uf_api
- */
-
 /*
  * Register handler for all unsolicted recieve frames.
  *
@@ -5414,7 +5068,7 @@
 
 	default:
 		bfa_trc(bfa, msg->mhdr.msg_id);
-		bfa_assert(0);
+		WARN_ON(1);
 	}
 }
 
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index e2349d5..331ad99 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -220,6 +220,18 @@
 /*
  * RPORT related defines
  */
+enum bfa_rport_event {
+	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event          */
+	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport  */
+	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online             */
+	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline            */
+	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response           */
+	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure             */
+	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware       */
+	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed             */
+	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue      */
+};
+
 #define BFA_RPORT_MIN	4
 
 struct bfa_rport_mod_s {
@@ -432,6 +444,7 @@
 	u8			myalpa;	/*  my ALPA in LOOP topology */
 	u8			rsvd[3];
 	struct bfa_port_cfg_s	cfg;	/*  current port configuration */
+	bfa_boolean_t		use_flash_cfg; /* get port cfg from flash */
 	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
 	struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
 	struct bfa_reqq_wait_s	reqq_wait;
@@ -500,30 +513,9 @@
 			void (*event_cbfn) (void *cbarg,
 			enum bfa_port_linkstate event), void *event_cbarg);
 bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
-void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
-void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
-bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
-					  enum bfa_port_speed speed);
 enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
 
 void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
-void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
-void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
-		       bfa_boolean_t link_e2e_beacon);
-void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
-			     struct bfa_qos_attr_s *qos_attr);
-void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
-				struct bfa_qos_vc_attr_s *qos_vc_attr);
-bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
-				      union bfa_fcport_stats_u *stats,
-				      bfa_cb_port_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
-					void *cbarg);
-bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
-				       union bfa_fcport_stats_u *stats,
-				       bfa_cb_port_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
-					 void *cbarg);
 bfa_boolean_t     bfa_fcport_is_ratelim(struct bfa_s *bfa);
 bfa_boolean_t	bfa_fcport_is_linkup(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
@@ -537,14 +529,9 @@
  * bfa rport API functions
  */
 struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
-void bfa_rport_delete(struct bfa_rport_s *rport);
 void bfa_rport_online(struct bfa_rport_s *rport,
 		      struct bfa_rport_info_s *rport_info);
-void bfa_rport_offline(struct bfa_rport_s *rport);
 void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed);
-void bfa_rport_get_stats(struct bfa_rport_s *rport,
-			 struct bfa_rport_hal_stats_s *stats);
-void bfa_rport_clear_stats(struct bfa_rport_s *rport);
 void bfa_cb_rport_online(void *rport);
 void bfa_cb_rport_offline(void *rport);
 void bfa_cb_rport_qos_scn_flowid(void *rport,
@@ -553,8 +540,6 @@
 void bfa_cb_rport_qos_scn_prio(void *rport,
 			       struct bfa_rport_qos_attr_s old_qos_attr,
 			       struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
-			    struct bfa_rport_qos_attr_s *qos_attr);
 
 /*
  * bfa fcxp API functions
@@ -619,38 +604,18 @@
 u32 bfa_lps_get_max_vport(struct bfa_s *bfa);
 struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
 void bfa_lps_delete(struct bfa_lps_s *lps);
-void bfa_lps_discard(struct bfa_lps_s *lps);
 void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
 		   u16 pdusz, wwn_t pwwn, wwn_t nwwn,
 		   bfa_boolean_t auth_en);
 void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
 		   wwn_t pwwn, wwn_t nwwn);
-void bfa_lps_flogo(struct bfa_lps_s *lps);
 void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
-bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
-u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
+void bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, u32 n2n_pid);
 u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
 u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
-u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
-mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
 void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
 void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
 void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
 void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
 
-void bfa_trunk_enable_cfg(struct bfa_s *bfa);
-bfa_status_t bfa_trunk_enable(struct bfa_s *bfa);
-bfa_status_t bfa_trunk_disable(struct bfa_s *bfa);
-bfa_status_t bfa_trunk_get_attr(struct bfa_s *bfa,
-		struct bfa_trunk_attr_s *attr);
-
 #endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 6797720..44524cf 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -32,7 +32,6 @@
 #include "bfad_drv.h"
 #include "bfad_im.h"
 #include "bfa_fcs.h"
-#include "bfa_os_inc.h"
 #include "bfa_defs.h"
 #include "bfa.h"
 
@@ -61,12 +60,12 @@
 u32	bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
 u32     *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
 
-const char *msix_name_ct[] = {
+static const char *msix_name_ct[] = {
 	"cpe0", "cpe1", "cpe2", "cpe3",
 	"rme0", "rme1", "rme2", "rme3",
 	"ctrl" };
 
-const char *msix_name_cb[] = {
+static const char *msix_name_cb[] = {
 	"cpe0", "cpe1", "cpe2", "cpe3",
 	"rme0", "rme1", "rme2", "rme3",
 	"eemc", "elpu0", "elpu1", "epss", "mlpu" };
@@ -206,7 +205,7 @@
 		}
 
 		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		bfa_init(&bfad->bfa);
+		bfa_iocfc_init(&bfad->bfa);
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 		/* Set up interrupt handler for each vectors */
@@ -533,7 +532,7 @@
 					(dma_addr_t) meminfo_elem->dma);
 				break;
 			default:
-				bfa_assert(0);
+				WARN_ON(1);
 				break;
 			}
 		}
@@ -725,7 +724,7 @@
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-	bfa_timer_tick(&bfad->bfa);
+	bfa_timer_beat(&bfad->bfa.timer_mod);
 
 	bfa_comp_deq(&bfad->bfa, &doneq);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -882,8 +881,8 @@
 		goto out_hal_mem_alloc_failure;
 	}
 
-	bfa_init_trc(&bfad->bfa, bfad->trcmod);
-	bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
+	bfad->bfa.trcmod = bfad->trcmod;
+	bfad->bfa.plog = &bfad->plog_buf;
 	bfa_plog_init(&bfad->plog_buf);
 	bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
 		     0, "Driver Attach");
@@ -893,9 +892,9 @@
 
 	/* FCS INIT */
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
+	bfad->bfa_fcs.trcmod = bfad->trcmod;
 	bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
-	bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
+	bfad->bfa_fcs.fdmi_enabled = fdmi_enable;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
@@ -913,7 +912,7 @@
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	init_completion(&bfad->comp);
-	bfa_stop(&bfad->bfa);
+	bfa_iocfc_stop(&bfad->bfa);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	wait_for_completion(&bfad->comp);
 
@@ -932,8 +931,8 @@
 	unsigned long	flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_start(&bfad->bfa);
-	bfa_fcs_start(&bfad->bfa_fcs);
+	bfa_iocfc_start(&bfad->bfa);
+	bfa_fcs_fabric_modstart(&bfad->bfa_fcs);
 	bfad->bfad_flags |= BFAD_HAL_START_DONE;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
@@ -963,7 +962,7 @@
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	init_completion(&bfad->comp);
-	bfa_stop(&bfad->bfa);
+	bfa_iocfc_stop(&bfad->bfa);
 	bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	wait_for_completion(&bfad->comp);
@@ -1102,15 +1101,15 @@
 
 	/*
 	 * If bfa_linkup_delay is set to -1 default; try to retrive the
-	 * value using the bfad_os_get_linkup_delay(); else use the
+	 * value using the bfad_get_linkup_delay(); else use the
 	 * passed in module param value as the bfa_linkup_delay.
 	 */
 	if (bfa_linkup_delay < 0) {
-		bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
-		bfad_os_rport_online_wait(bfad);
+		bfa_linkup_delay = bfad_get_linkup_delay(bfad);
+		bfad_rport_online_wait(bfad);
 		bfa_linkup_delay = -1;
 	} else
-		bfad_os_rport_online_wait(bfad);
+		bfad_rport_online_wait(bfad);
 
 	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "bfa device claimed\n");
 
@@ -1167,7 +1166,6 @@
 		spin_lock_irqsave(&bfad->bfad_lock, flags);
 		bfa_comp_free(&bfad->bfa, &doneq);
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		bfa_trc_fp(bfad, irq);
 	}
 
 	return IRQ_HANDLED;
@@ -1524,7 +1522,7 @@
 	if (strcmp(FCPI_NAME, " fcpim") == 0)
 		supported_fc4s |= BFA_LPORT_ROLE_FCP_IM;
 
-	bfa_ioc_auto_recover(ioc_auto_recover);
+	bfa_auto_recover = ioc_auto_recover;
 	bfa_fcs_rport_set_del_timeout(rport_del_timeout);
 
 	error = pci_register_driver(&bfad_pci_driver);
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index ed9fff4..a94ea42 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -25,7 +25,7 @@
 /*
  * FC transport template entry, get SCSI target port ID.
  */
-void
+static void
 bfad_im_get_starget_port_id(struct scsi_target *starget)
 {
 	struct Scsi_Host *shost;
@@ -40,7 +40,7 @@
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-	itnim = bfad_os_get_itnim(im_port, starget->id);
+	itnim = bfad_get_itnim(im_port, starget->id);
 	if (itnim)
 		fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim);
 
@@ -51,7 +51,7 @@
 /*
  * FC transport template entry, get SCSI target nwwn.
  */
-void
+static void
 bfad_im_get_starget_node_name(struct scsi_target *starget)
 {
 	struct Scsi_Host *shost;
@@ -66,7 +66,7 @@
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-	itnim = bfad_os_get_itnim(im_port, starget->id);
+	itnim = bfad_get_itnim(im_port, starget->id);
 	if (itnim)
 		node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim);
 
@@ -77,7 +77,7 @@
 /*
  * FC transport template entry, get SCSI target pwwn.
  */
-void
+static void
 bfad_im_get_starget_port_name(struct scsi_target *starget)
 {
 	struct Scsi_Host *shost;
@@ -92,7 +92,7 @@
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-	itnim = bfad_os_get_itnim(im_port, starget->id);
+	itnim = bfad_get_itnim(im_port, starget->id);
 	if (itnim)
 		port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim);
 
@@ -103,7 +103,7 @@
 /*
  * FC transport template entry, get SCSI host port ID.
  */
-void
+static void
 bfad_im_get_host_port_id(struct Scsi_Host *shost)
 {
 	struct bfad_im_port_s *im_port =
@@ -111,7 +111,7 @@
 	struct bfad_port_s    *port = im_port->port;
 
 	fc_host_port_id(shost) =
-			bfa_os_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
+			bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
 }
 
 /*
@@ -487,7 +487,7 @@
 	wait_for_completion(vport->comp_del);
 
 free_scsi_host:
-	bfad_os_scsi_host_free(bfad, im_port);
+	bfad_scsi_host_free(bfad, im_port);
 
 	kfree(vport);
 
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 1fedeeb..c66e32e 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -90,7 +90,7 @@
 	memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	rc = bfa_debug_fwtrc(&bfad->bfa,
+	rc = bfa_ioc_debug_fwtrc(&bfad->bfa.ioc,
 			fw_debug->debug_buffer,
 			&fw_debug->buffer_len);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -134,7 +134,7 @@
 	memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len);
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	rc = bfa_debug_fwsave(&bfad->bfa,
+	rc = bfa_ioc_debug_fwsave(&bfad->bfa.ioc,
 			fw_debug->debug_buffer,
 			&fw_debug->buffer_len);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -208,7 +208,7 @@
 	if (!debug || !debug->debug_buffer)
 		return 0;
 
-	return memory_read_from_buffer(buf, nbytes, pos,
+	return simple_read_from_buffer(buf, nbytes, pos,
 				debug->debug_buffer, debug->buffer_len);
 }
 
@@ -254,7 +254,7 @@
 	if (!bfad->regdata)
 		return 0;
 
-	rc = memory_read_from_buffer(buf, nbytes, pos,
+	rc = simple_read_from_buffer(buf, nbytes, pos,
 			bfad->regdata, bfad->reglen);
 
 	if ((*pos + nbytes) >= bfad->reglen) {
@@ -279,15 +279,31 @@
 	u32 *regbuf;
 	void __iomem *rb, *reg_addr;
 	unsigned long flags;
+	void *kern_buf;
 
-	rc = sscanf(buf, "%x:%x", &addr, &len);
+	kern_buf = kzalloc(nbytes, GFP_KERNEL);
+
+	if (!kern_buf) {
+		printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
+				bfad->inst_no);
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) {
+		kfree(kern_buf);
+		return -ENOMEM;
+	}
+
+	rc = sscanf(kern_buf, "%x:%x", &addr, &len);
 	if (rc < 2) {
 		printk(KERN_INFO
 			"bfad[%d]: %s failed to read user buf\n",
 			bfad->inst_no, __func__);
+		kfree(kern_buf);
 		return -EINVAL;
 	}
 
+	kfree(kern_buf);
 	kfree(bfad->regdata);
 	bfad->regdata = NULL;
 	bfad->reglen = 0;
@@ -339,14 +355,30 @@
 	int addr, val, rc;
 	void __iomem *reg_addr;
 	unsigned long flags;
+	void *kern_buf;
 
-	rc = sscanf(buf, "%x:%x", &addr, &val);
+	kern_buf = kzalloc(nbytes, GFP_KERNEL);
+
+	if (!kern_buf) {
+		printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
+				bfad->inst_no);
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) {
+		kfree(kern_buf);
+		return -ENOMEM;
+	}
+
+	rc = sscanf(kern_buf, "%x:%x", &addr, &val);
 	if (rc < 2) {
 		printk(KERN_INFO
 			"bfad[%d]: %s failed to read user buf\n",
 			bfad->inst_no, __func__);
+		kfree(kern_buf);
 		return -EINVAL;
 	}
+	kfree(kern_buf);
 
 	addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */
 
@@ -359,7 +391,7 @@
 		return -EINVAL;
 	}
 
-	reg_addr = (u32 *) ((u8 *) bfa_ioc_bar0(ioc) + addr);
+	reg_addr = (bfa_ioc_bar0(ioc)) + addr;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	writel(val, reg_addr);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index d5ce234..7f9ea90 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -26,7 +26,23 @@
 #ifndef __BFAD_DRV_H__
 #define __BFAD_DRV_H__
 
-#include "bfa_os_inc.h"
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/scsi_transport.h>
 
 #include "bfa_modules.h"
 #include "bfa_fcs.h"
@@ -39,7 +55,7 @@
 #ifdef BFA_DRIVER_VERSION
 #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
 #else
-#define BFAD_DRIVER_VERSION    "2.3.2.0"
+#define BFAD_DRIVER_VERSION    "2.3.2.3"
 #endif
 
 #define BFAD_PROTO_NAME FCPI_NAME
@@ -263,28 +279,21 @@
  */
 #define nextLowerInt(x)                         \
 do {                                            \
-	int i;                                  \
+	int __i;                                  \
 	(*x)--;					\
-	for (i = 1; i < (sizeof(int)*8); i <<= 1) \
-		(*x) = (*x) | (*x) >> i;	\
+	for (__i = 1; __i < (sizeof(int)*8); __i <<= 1) \
+		(*x) = (*x) | (*x) >> __i;	\
 	(*x)++;					\
 	(*x) = (*x) >> 1;			\
 } while (0)
 
 
-#define list_remove_head(list, entry, type, member)		\
-do {								\
-	entry = NULL;                                           \
-	if (!list_empty(list)) {                                \
-		entry = list_entry((list)->next, type, member);	\
-		list_del_init(&entry->member);			\
-	}							\
+#define BFA_LOG(level, bfad, mask, fmt, arg...)				\
+do {									\
+	if (((mask) == 4) || (level[1] <= '4'))				\
+		dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg);	\
 } while (0)
 
-#define list_get_first(list, type, member)				\
-((list_empty(list)) ? NULL :						\
-	list_entry((list)->next, type, member))
-
 bfa_status_t	bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
 				  struct bfa_lport_cfg_s *port_cfg,
 				  struct device *dev);
@@ -316,8 +325,8 @@
 
 void bfad_pci_remove(struct pci_dev *pdev);
 int bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid);
-void bfad_os_rport_online_wait(struct bfad_s *bfad);
-int bfad_os_get_linkup_delay(struct bfad_s *bfad);
+void bfad_rport_online_wait(struct bfad_s *bfad);
+int bfad_get_linkup_delay(struct bfad_s *bfad);
 int bfad_install_msix_handler(struct bfad_s *bfad);
 
 extern struct idr bfad_im_port_index;
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index fbad5e9..c2b3617 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -21,7 +21,6 @@
 
 #include "bfad_drv.h"
 #include "bfad_im.h"
-#include "bfa_cb_ioim.h"
 #include "bfa_fcs.h"
 
 BFA_TRC_FILE(LDRV, IM);
@@ -93,10 +92,10 @@
 		if (!cmnd->result && itnim &&
 			 (bfa_lun_queue_depth > cmnd->device->queue_depth)) {
 			/* Queue depth adjustment for good status completion */
-			bfad_os_ramp_up_qdepth(itnim, cmnd->device);
+			bfad_ramp_up_qdepth(itnim, cmnd->device);
 		} else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) {
 			/* qfull handling */
-			bfad_os_handle_qfull(itnim, cmnd->device);
+			bfad_handle_qfull(itnim, cmnd->device);
 		}
 	}
 
@@ -124,7 +123,7 @@
 		if (itnim_data) {
 			itnim = itnim_data->itnim;
 			if (itnim)
-				bfad_os_ramp_up_qdepth(itnim, cmnd->device);
+				bfad_ramp_up_qdepth(itnim, cmnd->device);
 		}
 	}
 
@@ -183,7 +182,7 @@
 	bfa_get_adapter_model(bfa, model);
 
 	memset(bfa_buf, 0, sizeof(bfa_buf));
-	if (ioc->ctdev)
+	if (ioc->ctdev && !ioc->fcmode)
 		snprintf(bfa_buf, sizeof(bfa_buf),
 		"Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
 		 model, bfad->pci_name, BFAD_DRIVER_VERSION);
@@ -258,6 +257,7 @@
 	struct bfa_tskim_s *tskim;
 	struct bfa_itnim_s *bfa_itnim;
 	bfa_status_t    rc = BFA_STATUS_OK;
+	struct scsi_lun scsilun;
 
 	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
 	if (!tskim) {
@@ -274,7 +274,8 @@
 	cmnd->host_scribble = NULL;
 	cmnd->SCp.Status = 0;
 	bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
-	bfa_tskim_start(tskim, bfa_itnim, (lun_t)0,
+	memset(&scsilun, 0, sizeof(scsilun));
+	bfa_tskim_start(tskim, bfa_itnim, scsilun,
 			    FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO);
 out:
 	return rc;
@@ -301,6 +302,7 @@
 	int             rc = SUCCESS;
 	unsigned long   flags;
 	enum bfi_tskim_status task_status;
+	struct scsi_lun scsilun;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	itnim = itnim_data->itnim;
@@ -327,8 +329,8 @@
 	cmnd->SCp.ptr = (char *)&wq;
 	cmnd->SCp.Status = 0;
 	bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
-	bfa_tskim_start(tskim, bfa_itnim,
-			    bfad_int_to_lun(cmnd->device->lun),
+	int_to_scsilun(cmnd->device->lun, &scsilun);
+	bfa_tskim_start(tskim, bfa_itnim, scsilun,
 			    FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
@@ -364,7 +366,7 @@
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	for (i = 0; i < MAX_FCP_TARGET; i++) {
-		itnim = bfad_os_get_itnim(im_port, i);
+		itnim = bfad_get_itnim(im_port, i);
 		if (itnim) {
 			cmnd->SCp.ptr = (char *)&wq;
 			rc = bfad_im_target_reset_send(bfad, cmnd, itnim);
@@ -447,7 +449,7 @@
 	struct bfad_im_s	*im = itnim_drv->im;
 
 	/* online to free state transtion should not happen */
-	bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE);
+	WARN_ON(itnim_drv->state == ITNIM_STATE_ONLINE);
 
 	itnim_drv->queue_work = 1;
 	/* offline request is not yet done, use the same request to free */
@@ -545,7 +547,7 @@
 
 	mutex_unlock(&bfad_mutex);
 
-	im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad);
+	im_port->shost = bfad_scsi_host_alloc(im_port, bfad);
 	if (!im_port->shost) {
 		error = 1;
 		goto out_free_idr;
@@ -571,7 +573,7 @@
 	}
 
 	/* setup host fixed attribute if the lk supports */
-	bfad_os_fc_host_init(im_port);
+	bfad_fc_host_init(im_port);
 
 	return 0;
 
@@ -662,7 +664,7 @@
 	}
 
 	/* the itnim_mapped_list must be empty at this time */
-	bfa_assert(list_empty(&im_port->itnim_mapped_list));
+	WARN_ON(!list_empty(&im_port->itnim_mapped_list));
 
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 }
@@ -682,7 +684,7 @@
 	bfad->im = im;
 	im->bfad = bfad;
 
-	if (bfad_os_thread_workq(bfad) != BFA_STATUS_OK) {
+	if (bfad_thread_workq(bfad) != BFA_STATUS_OK) {
 		kfree(im);
 		rc = BFA_STATUS_FAILED;
 	}
@@ -695,14 +697,14 @@
 bfad_im_probe_undo(struct bfad_s *bfad)
 {
 	if (bfad->im) {
-		bfad_os_destroy_workq(bfad->im);
+		bfad_destroy_workq(bfad->im);
 		kfree(bfad->im);
 		bfad->im = NULL;
 	}
 }
 
 struct Scsi_Host *
-bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
+bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
 {
 	struct scsi_host_template *sht;
 
@@ -717,7 +719,7 @@
 }
 
 void
-bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
+bfad_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
 {
 	if (!(im_port->flags & BFAD_PORT_DELETE))
 		flush_workqueue(bfad->im->drv_workq);
@@ -727,7 +729,7 @@
 }
 
 void
-bfad_os_destroy_workq(struct bfad_im_s *im)
+bfad_destroy_workq(struct bfad_im_s *im)
 {
 	if (im && im->drv_workq) {
 		flush_workqueue(im->drv_workq);
@@ -737,7 +739,7 @@
 }
 
 bfa_status_t
-bfad_os_thread_workq(struct bfad_s *bfad)
+bfad_thread_workq(struct bfad_s *bfad)
 {
 	struct bfad_im_s      *im = bfad->im;
 
@@ -841,7 +843,7 @@
 }
 
 void
-bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
+bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
 {
 	struct scsi_device *tmp_sdev;
 
@@ -869,7 +871,7 @@
 }
 
 void
-bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
+bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
 {
 	struct scsi_device *tmp_sdev;
 
@@ -883,7 +885,7 @@
 }
 
 struct bfad_itnim_s *
-bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id)
+bfad_get_itnim(struct bfad_im_port_s *im_port, int id)
 {
 	struct bfad_itnim_s   *itnim = NULL;
 
@@ -922,7 +924,7 @@
 	if (!ioc_attr)
 		return 0;
 
-	bfa_get_attr(bfa, ioc_attr);
+	bfa_ioc_get_attr(&bfa->ioc, ioc_attr);
 	if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
 		if (ioc_attr->adapter_attr.is_mezz) {
 			supported_speed |= FC_PORTSPEED_8GBIT |
@@ -944,7 +946,7 @@
 }
 
 void
-bfad_os_fc_host_init(struct bfad_im_port_s *im_port)
+bfad_fc_host_init(struct bfad_im_port_s *im_port)
 {
 	struct Scsi_Host *host = im_port->shost;
 	struct bfad_s         *bfad = im_port->bfad;
@@ -988,7 +990,7 @@
 	rport_ids.port_name =
 		cpu_to_be64(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim));
 	rport_ids.port_id =
-		bfa_os_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim));
+		bfa_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim));
 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
 
 	itnim->fc_rport = fc_rport =
@@ -1109,7 +1111,7 @@
 		kfree(itnim);
 		break;
 	default:
-		bfa_assert(0);
+		WARN_ON(1);
 		break;
 	}
 
@@ -1172,7 +1174,6 @@
 	}
 
 	cmnd->host_scribble = (char *)hal_io;
-	bfa_trc_fp(bfad, hal_io->iotag);
 	bfa_ioim_start(hal_io);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
@@ -1190,7 +1191,7 @@
 static DEF_SCSI_QCMD(bfad_im_queuecommand)
 
 void
-bfad_os_rport_online_wait(struct bfad_s *bfad)
+bfad_rport_online_wait(struct bfad_s *bfad)
 {
 	int i;
 	int rport_delay = 10;
@@ -1218,7 +1219,7 @@
 }
 
 int
-bfad_os_get_linkup_delay(struct bfad_s *bfad)
+bfad_get_linkup_delay(struct bfad_s *bfad)
 {
 	u8		nwwns = 0;
 	wwn_t		wwns[BFA_PREBOOT_BOOTLUN_MAX];
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index b038c0e..bfee63b 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -117,17 +117,17 @@
 	char            drv_workq_name[KOBJ_NAME_LEN];
 };
 
-struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port,
+struct Scsi_Host *bfad_scsi_host_alloc(struct bfad_im_port_s *im_port,
 				struct bfad_s *);
-bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad);
-void bfad_os_destroy_workq(struct bfad_im_s *im);
-void bfad_os_fc_host_init(struct bfad_im_port_s *im_port);
-void bfad_os_scsi_host_free(struct bfad_s *bfad,
+bfa_status_t bfad_thread_workq(struct bfad_s *bfad);
+void bfad_destroy_workq(struct bfad_im_s *im);
+void bfad_fc_host_init(struct bfad_im_port_s *im_port);
+void bfad_scsi_host_free(struct bfad_s *bfad,
 				 struct bfad_im_port_s *im_port);
-void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim,
+void bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim,
 				 struct scsi_device *sdev);
-void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
-struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id);
+void bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
+struct bfad_itnim_s *bfad_get_itnim(struct bfad_im_port_s *im_port, int id);
 
 extern struct scsi_host_template bfad_im_scsi_host_template;
 extern struct scsi_host_template bfad_im_vport_template;
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index 58796d1..72b69a0 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -95,8 +95,8 @@
  */
 union bfi_addr_u {
 	struct {
-		u32	addr_lo;
-		u32	addr_hi;
+		__be32	addr_lo;
+		__be32	addr_hi;
 	} a32;
 };
 
@@ -104,7 +104,7 @@
  * Scatter Gather Element
  */
 struct bfi_sge_s {
-#ifdef __BIGENDIAN
+#ifdef __BIG_ENDIAN
 	u32	flags:2,
 			rsvd:2,
 			sg_len:28;
@@ -399,7 +399,7 @@
  */
 struct bfi_pbc_blun_s {
 	wwn_t		tgt_pwwn;
-	lun_t		tgt_lun;
+	struct scsi_lun	tgt_lun;
 };
 
 /*
diff --git a/drivers/scsi/bfa/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h
index 6f03ed3..39ad42b 100644
--- a/drivers/scsi/bfa/bfi_cbreg.h
+++ b/drivers/scsi/bfa/bfi_cbreg.h
@@ -208,6 +208,7 @@
 #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_Q_DEPTH(__n) \
 	(CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH))
diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h
index 62b86a4..fc4ce4a 100644
--- a/drivers/scsi/bfa/bfi_ctreg.h
+++ b/drivers/scsi/bfa/bfi_ctreg.h
@@ -522,6 +522,7 @@
 #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))
@@ -539,22 +540,30 @@
 	(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 --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index fa9f6fb..19e888a 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -47,10 +47,10 @@
 	 */
 	union bfi_addr_u  req_cq_ba[BFI_IOC_MAX_CQS];
 	union bfi_addr_u  req_shadow_ci[BFI_IOC_MAX_CQS];
-	u16    req_cq_elems[BFI_IOC_MAX_CQS];
+	__be16    req_cq_elems[BFI_IOC_MAX_CQS];
 	union bfi_addr_u  rsp_cq_ba[BFI_IOC_MAX_CQS];
 	union bfi_addr_u  rsp_shadow_pi[BFI_IOC_MAX_CQS];
-	u16    rsp_cq_elems[BFI_IOC_MAX_CQS];
+	__be16    rsp_cq_elems[BFI_IOC_MAX_CQS];
 
 	union bfi_addr_u  stats_addr;	/*  DMA-able address for stats	  */
 	union bfi_addr_u  cfgrsp_addr;	/*  config response dma address  */
@@ -102,8 +102,8 @@
 	struct bfi_mhdr_s mh;		/*  common msg header		*/
 	u8		coalesce;	/*  enable intr coalescing	*/
 	u8		rsvd[3];
-	u16	delay;		/*  delay timer 0..1125us	*/
-	u16	latency;	/*  latency timer 0..225us	*/
+	__be16	delay;		/*  delay timer 0..1125us	*/
+	__be16	latency;	/*  latency timer 0..225us	*/
 };
 
 
@@ -188,7 +188,8 @@
 	struct bfi_mhdr_s  mh;		/*  common msg header		    */
 	u8		   status;	/*  port enable status		    */
 	u8		   rsvd[3];
-	u32	   msgtag;	/*  msgtag for reply		    */
+	struct	bfa_port_cfg_s port_cfg;/* port configuration	*/
+	u32	msgtag;			/* msgtag for reply	*/
 };
 
 /*
@@ -202,7 +203,8 @@
 	struct bfa_port_cfg_s port_cfg; /*  port configuration	    */
 	union bfi_addr_u   stats_dma_addr; /*  DMA address for stats	    */
 	u32	   msgtag;	/*  msgtag for reply		    */
-	u32	   rsvd2;
+	u8	use_flash_cfg;	/* get prot cfg from flash */
+	u8	rsvd2[3];
 };
 
 /*
@@ -210,7 +212,7 @@
  */
 struct bfi_fcport_set_svc_params_req_s {
 	struct bfi_mhdr_s  mh;		/*  msg header */
-	u16	   tx_bbcredit;	/*  Tx credits */
+	__be16	   tx_bbcredit;	/*  Tx credits */
 	u16	   rsvd;
 };
 
@@ -231,7 +233,7 @@
 	u8			state;		/* bfa_trunk_link_state_t */
 	u8			speed;		/* bfa_port_speed_t */
 	u8			rsvd;
-	u32		deskew;
+	__be32		deskew;
 };
 
 #define BFI_FCPORT_MAX_LINKS	2
@@ -284,17 +286,17 @@
  */
 struct bfi_fcxp_send_req_s {
 	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
-	u16	fcxp_tag;	/*  driver request tag		    */
-	u16	max_frmsz;	/*  max send frame size	    */
-	u16	vf_id;		/*  vsan tag if applicable	    */
+	__be16	fcxp_tag;	/*  driver request tag		    */
+	__be16	max_frmsz;	/*  max send frame size	    */
+	__be16	vf_id;		/*  vsan tag if applicable	    */
 	u16	rport_fw_hndl;	/*  FW Handle for the remote port  */
 	u8	 class;		/*  FC class used for req/rsp	    */
 	u8	 rsp_timeout;	/*  timeout in secs, 0-no response */
 	u8	 cts;		/*  continue sequence		    */
 	u8	 lp_tag;	/*  lport tag			    */
 	struct fchs_s	fchs;	/*  request FC header structure    */
-	u32	req_len;	/*  request payload length	    */
-	u32	rsp_maxlen;	/*  max response length expected   */
+	__be32	req_len;	/*  request payload length	    */
+	__be32	rsp_maxlen;	/*  max response length expected   */
 	struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];	/*  request buf    */
 	struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];	/*  response buf   */
 };
@@ -304,11 +306,11 @@
  */
 struct bfi_fcxp_send_rsp_s {
 	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
-	u16	fcxp_tag;	/*  send request tag		    */
+	__be16	fcxp_tag;	/*  send request tag		    */
 	u8	 req_status;	/*  request status		    */
 	u8	 rsvd;
-	u32	rsp_len;	/*  actual response length	    */
-	u32	residue_len;	/*  residual response length	    */
+	__be32	rsp_len;	/*  actual response length	    */
+	__be32	residue_len;	/*  residual response length	    */
 	struct fchs_s	fchs;	/*  response FC header structure   */
 };
 
@@ -325,7 +327,7 @@
 struct bfi_uf_buf_post_s {
 	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
 	u16	buf_tag;	/*  buffer tag			*/
-	u16	buf_len;	/*  total buffer length	*/
+	__be16	buf_len;	/*  total buffer length	*/
 	struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs	*/
 };
 
@@ -340,6 +342,7 @@
 enum bfi_lps_h2i_msgs {
 	BFI_LPS_H2I_LOGIN_REQ	= 1,
 	BFI_LPS_H2I_LOGOUT_REQ	= 2,
+	BFI_LPS_H2I_N2N_PID_REQ = 3,
 };
 
 enum bfi_lps_i2h_msgs {
@@ -352,7 +355,7 @@
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
 	u8		lp_tag;
 	u8		alpa;
-	u16	pdu_size;
+	__be16		pdu_size;
 	wwn_t		pwwn;
 	wwn_t		nwwn;
 	u8		fdisc;
@@ -368,7 +371,7 @@
 	u8		lsrjt_expl;
 	wwn_t		port_name;
 	wwn_t		node_name;
-	u16	bb_credit;
+	__be16		bb_credit;
 	u8		f_port;
 	u8		npiv_en;
 	u32	lp_pid:24;
@@ -399,10 +402,17 @@
 	u8		rsvd[3];
 };
 
+struct bfi_lps_n2n_pid_req_s {
+	struct bfi_mhdr_s	mh;	/*  common msg header		*/
+	u8	lp_tag;
+	u32	lp_pid:24;
+};
+
 union bfi_lps_h2i_msg_u {
 	struct bfi_mhdr_s		*msg;
 	struct bfi_lps_login_req_s	*login_req;
 	struct bfi_lps_logout_req_s	*logout_req;
+	struct bfi_lps_n2n_pid_req_s	*n2n_pid_req;
 };
 
 union bfi_lps_i2h_msg_u {
@@ -427,7 +437,7 @@
 struct bfi_rport_create_req_s {
 	struct bfi_mhdr_s  mh;		/*  common msg header		*/
 	u16	bfa_handle;	/*  host rport handle		*/
-	u16	max_frmsz;	/*  max rcv pdu size		*/
+	__be16	max_frmsz;	/*  max rcv pdu size		*/
 	u32	pid:24,	/*  remote port ID		*/
 		lp_tag:8;	/*  local port tag		*/
 	u32	local_pid:24,	/*  local port ID		*/
@@ -583,7 +593,7 @@
  */
 struct bfi_ioim_req_s {
 	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
-	u16	io_tag;		/*  I/O tag			 */
+	__be16	io_tag;		/*  I/O tag			 */
 	u16	rport_hdl;	/*  itnim/rport firmware handle */
 	struct fcp_cmnd_s	cmnd;	/*  IO request info	*/
 
@@ -689,7 +699,7 @@
  */
 struct bfi_ioim_rsp_s {
 	struct bfi_mhdr_s	mh;	/*  common msg header		*/
-	u16	io_tag;		/*  completed IO tag		 */
+	__be16	io_tag;		/*  completed IO tag		 */
 	u16	bfa_rport_hndl;	/*  releated rport handle	 */
 	u8	io_status;	/*  IO completion status	 */
 	u8	reuse_io_tag;	/*  IO tag can be reused	*/
@@ -698,13 +708,13 @@
 	u8		sns_len;	/*  scsi sense length		 */
 	u8		resid_flags;	/*  IO residue flags		 */
 	u8		rsvd_a;
-	u32	residue;	/*  IO residual length in bytes */
+	__be32	residue;	/*  IO residual length in bytes */
 	u32	rsvd_b[3];
 };
 
 struct bfi_ioim_abort_req_s {
 	struct bfi_mhdr_s  mh;	/*  Common msg header  */
-	u16	io_tag;	/*  I/O tag	*/
+	__be16	io_tag;	/*  I/O tag	*/
 	u16	abort_tag;	/*  unique request tag */
 };
 
@@ -723,9 +733,9 @@
 
 struct bfi_tskim_req_s {
 	struct bfi_mhdr_s  mh;	/*  Common msg header	*/
-	u16	tsk_tag;	/*  task management tag	*/
+	__be16	tsk_tag;	/*  task management tag	*/
 	u16	itn_fhdl;	/*  itn firmware handle	*/
-	lun_t	lun;	/*  LU number	*/
+	struct 	scsi_lun lun;	/*  LU number	*/
 	u8	tm_flags;	/*  see enum fcp_tm_cmnd	*/
 	u8	t_secs;	/*  Timeout value in seconds	*/
 	u8	rsvd[2];
@@ -733,7 +743,7 @@
 
 struct bfi_tskim_abortreq_s {
 	struct bfi_mhdr_s  mh;	/*  Common msg header	*/
-	u16	tsk_tag;	/*  task management tag	*/
+	__be16	tsk_tag;	/*  task management tag	*/
 	u16	rsvd;
 };
 
@@ -755,7 +765,7 @@
 
 struct bfi_tskim_rsp_s {
 	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
-	u16	tsk_tag;	/*  task mgmt cmnd tag		 */
+	__be16	tsk_tag;	/*  task mgmt cmnd tag		 */
 	u8	tsk_status;	/*  @ref bfi_tskim_status */
 	u8	rsvd;
 };
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 1b6f86b..30e6bdb 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,12 +1,13 @@
 /* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
  *
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 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.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
  */
 #ifndef __57XX_ISCSI_CONSTANTS_H_
 #define __57XX_ISCSI_CONSTANTS_H_
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index 36af1af..dad6c8a 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,12 +1,13 @@
 /* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
  *
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 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.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
  */
 #ifndef __57XX_ISCSI_HSI_LINUX_LE__
 #define __57XX_ISCSI_HSI_LINUX_LE__
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index a44b1b3..e1ca5fe 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,6 +1,6 @@
 /* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
  */
 
 #ifndef _BNX2I_H_
@@ -649,6 +650,7 @@
 	EP_STATE_OFLD_FAILED            = 0x8000000,
 	EP_STATE_CONNECT_FAILED         = 0x10000000,
 	EP_STATE_DISCONN_TIMEDOUT       = 0x20000000,
+	EP_STATE_OFLD_FAILED_CID_BUSY   = 0x80000000,
 };
 
 /**
@@ -717,14 +719,11 @@
  * Function Prototypes
  */
 extern void bnx2i_identify_device(struct bnx2i_hba *hba);
-extern void bnx2i_register_device(struct bnx2i_hba *hba);
 
 extern void bnx2i_ulp_init(struct cnic_dev *dev);
 extern void bnx2i_ulp_exit(struct cnic_dev *dev);
 extern void bnx2i_start(void *handle);
 extern void bnx2i_stop(void *handle);
-extern void bnx2i_reg_dev_all(void);
-extern void bnx2i_unreg_dev_all(void);
 extern struct bnx2i_hba *get_adapter_list_head(void);
 
 struct bnx2i_conn *bnx2i_get_conn_from_id(struct bnx2i_hba *hba,
@@ -761,11 +760,11 @@
 				   struct iscsi_task *mtask);
 extern void bnx2i_send_cmd_cleanup_req(struct bnx2i_hba *hba,
 				       struct bnx2i_cmd *cmd);
-extern void bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba,
-				     struct bnx2i_endpoint *ep);
-extern void bnx2i_update_iscsi_conn(struct iscsi_conn *conn);
-extern void bnx2i_send_conn_destroy(struct bnx2i_hba *hba,
+extern int bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba,
 				    struct bnx2i_endpoint *ep);
+extern void bnx2i_update_iscsi_conn(struct iscsi_conn *conn);
+extern int bnx2i_send_conn_destroy(struct bnx2i_hba *hba,
+				   struct bnx2i_endpoint *ep);
 
 extern int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba,
 			       struct bnx2i_endpoint *ep);
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 2f9622e..96505e3 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1,6 +1,6 @@
 /* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
  */
 
 #include <linux/gfp.h>
@@ -385,6 +386,7 @@
 	struct bnx2i_cmd *bnx2i_cmd;
 	struct bnx2i_tmf_request *tmfabort_wqe;
 	u32 dword;
+	u32 scsi_lun[2];
 
 	bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
 	tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
@@ -426,7 +428,10 @@
 	default:
 		tmfabort_wqe->ref_itt = RESERVED_ITT;
 	}
-	memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
+	memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
+	tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
+	tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
+
 	tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn);
 
 	tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma;
@@ -697,10 +702,11 @@
  * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE to initiate
  * 	iscsi connection context clean-up process
  */
-void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
+int bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
 {
 	struct kwqe *kwqe_arr[2];
 	struct iscsi_kwqe_conn_destroy conn_cleanup;
+	int rc = -EINVAL;
 
 	memset(&conn_cleanup, 0x00, sizeof(struct iscsi_kwqe_conn_destroy));
 
@@ -717,7 +723,9 @@
 
 	kwqe_arr[0] = (struct kwqe *) &conn_cleanup;
 	if (hba->cnic && hba->cnic->submit_kwqes)
-		hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1);
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1);
+
+	return rc;
 }
 
 
@@ -728,8 +736,8 @@
  *
  * 5706/5708/5709 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE
  */
-static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba,
-					  struct bnx2i_endpoint *ep)
+static int bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba,
+					 struct bnx2i_endpoint *ep)
 {
 	struct kwqe *kwqe_arr[2];
 	struct iscsi_kwqe_conn_offload1 ofld_req1;
@@ -737,6 +745,7 @@
 	dma_addr_t dma_addr;
 	int num_kwqes = 2;
 	u32 *ptbl;
+	int rc = -EINVAL;
 
 	ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1;
 	ofld_req1.hdr.flags =
@@ -774,7 +783,9 @@
 	ofld_req2.num_additional_wqes = 0;
 
 	if (hba->cnic && hba->cnic->submit_kwqes)
-		hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
 }
 
 
@@ -785,8 +796,8 @@
  *
  * 57710 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE
  */
-static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba,
-					   struct bnx2i_endpoint *ep)
+static int bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba,
+					  struct bnx2i_endpoint *ep)
 {
 	struct kwqe *kwqe_arr[5];
 	struct iscsi_kwqe_conn_offload1 ofld_req1;
@@ -795,6 +806,7 @@
 	dma_addr_t dma_addr;
 	int num_kwqes = 2;
 	u32 *ptbl;
+	int rc = -EINVAL;
 
 	ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1;
 	ofld_req1.hdr.flags =
@@ -840,7 +852,9 @@
 	num_kwqes += 1;
 
 	if (hba->cnic && hba->cnic->submit_kwqes)
-		hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
 }
 
 /**
@@ -851,12 +865,16 @@
  *
  * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE
  */
-void bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
+int bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
 {
+	int rc;
+
 	if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type))
-		bnx2i_5771x_send_conn_ofld_req(hba, ep);
+		rc = bnx2i_5771x_send_conn_ofld_req(hba, ep);
 	else
-		bnx2i_570x_send_conn_ofld_req(hba, ep);
+		rc = bnx2i_570x_send_conn_ofld_req(hba, ep);
+
+	return rc;
 }
 
 
@@ -1513,7 +1531,7 @@
 	task = iscsi_itt_to_task(conn,
 				 nop_in->itt & ISCSI_NOP_IN_MSG_INDEX);
 	if (task)
-		iscsi_put_task(task);
+		__iscsi_put_task(task);
 	spin_unlock(&session->lock);
 }
 
@@ -1549,11 +1567,9 @@
 	struct iscsi_task *task;
 	struct bnx2i_nop_in_msg *nop_in;
 	struct iscsi_nopin *hdr;
-	u32 itt;
 	int tgt_async_nop = 0;
 
 	nop_in = (struct bnx2i_nop_in_msg *)cqe;
-	itt = nop_in->itt & ISCSI_NOP_IN_MSG_INDEX;
 
 	spin_lock(&session->lock);
 	hdr = (struct iscsi_nopin *)&bnx2i_conn->gen_pdu.resp_hdr;
@@ -1563,7 +1579,7 @@
 	hdr->exp_cmdsn = cpu_to_be32(nop_in->exp_cmd_sn);
 	hdr->ttt = cpu_to_be32(nop_in->ttt);
 
-	if (itt == (u16) RESERVED_ITT) {
+	if (nop_in->itt == (u16) RESERVED_ITT) {
 		bnx2i_unsol_pdu_adjust_rq(bnx2i_conn);
 		hdr->itt = RESERVED_ITT;
 		tgt_async_nop = 1;
@@ -1571,7 +1587,8 @@
 	}
 
 	/* this is a response to one of our nop-outs */
-	task = iscsi_itt_to_task(conn, itt);
+	task = iscsi_itt_to_task(conn,
+			 (itt_t) (nop_in->itt & ISCSI_NOP_IN_MSG_INDEX));
 	if (task) {
 		hdr->flags = ISCSI_FLAG_CMD_FINAL;
 		hdr->itt = task->hdr->itt;
@@ -1721,9 +1738,18 @@
 		if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
 			break;
 
-		if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx)))
+		if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) {
+			if (nopin->op_code == ISCSI_OP_NOOP_IN &&
+			    nopin->itt == (u16) RESERVED_ITT) {
+				printk(KERN_ALERT "bnx2i: Unsolicited "
+					"NOP-In detected for suspended "
+					"connection dev=%s!\n",
+					bnx2i_conn->hba->netdev->name);
+				bnx2i_unsol_pdu_adjust_rq(bnx2i_conn);
+				goto cqe_out;
+			}
 			break;
-
+		}
 		tgt_async_msg = 0;
 
 		switch (nopin->op_code) {
@@ -1770,10 +1796,9 @@
 			printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n",
 					  nopin->op_code);
 		}
-
 		if (!tgt_async_msg)
 			bnx2i_conn->ep->num_active_cmds--;
-
+cqe_out:
 		/* clear out in production version only, till beta keep opcode
 		 * field intact, will be helpful in debugging (context dump)
 		 * nopin->op_code = 0;
@@ -2154,11 +2179,24 @@
 	}
 
 	if (ofld_kcqe->completion_status) {
+		ep->state = EP_STATE_OFLD_FAILED;
 		if (ofld_kcqe->completion_status ==
 		    ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE)
-			printk(KERN_ALERT "bnx2i: unable to allocate"
-					  " iSCSI context resources\n");
-		ep->state = EP_STATE_OFLD_FAILED;
+			printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - unable "
+				"to allocate iSCSI context resources\n",
+				hba->netdev->name);
+		else if (ofld_kcqe->completion_status ==
+			 ISCSI_KCQE_COMPLETION_STATUS_INVALID_OPCODE)
+			printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
+				"opcode\n", hba->netdev->name);
+		else if (ofld_kcqe->completion_status ==
+			ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
+			/* error status code valid only for 5771x chipset */
+			ep->state = EP_STATE_OFLD_FAILED_CID_BUSY;
+		else
+			printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
+				"error code %d\n", hba->netdev->name,
+				ofld_kcqe->completion_status);
 	} else {
 		ep->state = EP_STATE_OFLD_COMPL;
 		cid_addr = ofld_kcqe->iscsi_conn_context_id;
@@ -2339,10 +2377,14 @@
 static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
 {
 	struct bnx2i_endpoint *ep = (struct bnx2i_endpoint *) cm_sk->context;
+	u32 old_state = ep->state;
 
 	ep->state = EP_STATE_TCP_RST_RCVD;
-	if (ep->conn)
-		bnx2i_recovery_que_add_conn(ep->hba, ep->conn);
+	if (old_state == EP_STATE_DISCONN_START)
+		wake_up_interruptible(&ep->ofld_wait);
+	else
+		if (ep->conn)
+			bnx2i_recovery_que_add_conn(ep->hba, ep->conn);
 }
 
 
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 50c2aa3b..72a7b2d 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,6 +1,6 @@
 /* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
  */
 
 #include "bnx2i.h"
@@ -17,8 +18,8 @@
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.1.3"
-#define DRV_MODULE_RELDATE	"Aug 10, 2010"
+#define DRV_MODULE_VERSION	"2.6.2.2"
+#define DRV_MODULE_RELDATE	"Nov 23, 2010"
 
 static char version[] __devinitdata =
 		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -65,8 +66,6 @@
 
 u64 iscsi_error_mask = 0x00;
 
-static void bnx2i_unreg_one_device(struct bnx2i_hba *hba) ;
-
 
 /**
  * bnx2i_identify_device - identifies NetXtreme II device type
@@ -211,13 +210,24 @@
 {
 	struct bnx2i_hba *hba = handle;
 	int conns_active;
+	int wait_delay = 1 * HZ;
 
 	/* check if cleanup happened in GOING_DOWN context */
-	if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN,
-				&hba->adapter_state))
+	if (!test_and_set_bit(ADAPTER_STATE_GOING_DOWN,
+			      &hba->adapter_state)) {
 		iscsi_host_for_each_session(hba->shost,
 					    bnx2i_drop_session);
-
+		wait_delay = hba->hba_shutdown_tmo;
+	}
+	/* Wait for inflight offload connection tasks to complete before
+	 * proceeding. Forcefully terminate all connection recovery in
+	 * progress at the earliest, either in bind(), send_pdu(LOGIN),
+	 * or conn_start()
+	 */
+	wait_event_interruptible_timeout(hba->eh_wait,
+					 (list_empty(&hba->ep_ofld_list) &&
+					 list_empty(&hba->ep_destroy_list)),
+					 10 * HZ);
 	/* Wait for all endpoints to be torn down, Chip will be reset once
 	 *  control returns to network driver. So it is required to cleanup and
 	 * release all connection resources before returning from this routine.
@@ -226,7 +236,7 @@
 		conns_active = hba->ofld_conns_active;
 		wait_event_interruptible_timeout(hba->eh_wait,
 				(hba->ofld_conns_active != conns_active),
-				hba->hba_shutdown_tmo);
+				wait_delay);
 		if (hba->ofld_conns_active == conns_active)
 			break;
 	}
@@ -235,88 +245,10 @@
 	/* This flag should be cleared last so that ep_disconnect() gracefully
 	 * cleans up connection context
 	 */
+	clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
 	clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
 }
 
-/**
- * bnx2i_register_device - register bnx2i adapter instance with the cnic driver
- * @hba:	Adapter instance to register
- *
- * registers bnx2i adapter instance with the cnic driver while holding the
- *	adapter structure lock
- */
-void bnx2i_register_device(struct bnx2i_hba *hba)
-{
-	int rc;
-
-	if (test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) ||
-	    test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
-		return;
-	}
-
-	rc = hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba);
-
-	if (!rc)
-		set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
-}
-
-
-/**
- * bnx2i_reg_dev_all - registers all adapter instances with the cnic driver
- *
- * registers all bnx2i adapter instances with the cnic driver while holding
- *	the global resource lock
- */
-void bnx2i_reg_dev_all(void)
-{
-	struct bnx2i_hba *hba, *temp;
-
-	mutex_lock(&bnx2i_dev_lock);
-	list_for_each_entry_safe(hba, temp, &adapter_list, link)
-		bnx2i_register_device(hba);
-	mutex_unlock(&bnx2i_dev_lock);
-}
-
-
-/**
- * bnx2i_unreg_one_device - unregister adapter instance with the cnic driver
- * @hba:	Adapter instance to unregister
- *
- * registers bnx2i adapter instance with the cnic driver while holding
- *	the adapter structure lock
- */
-static void bnx2i_unreg_one_device(struct bnx2i_hba *hba)
-{
-	if (hba->ofld_conns_active ||
-	    !test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic) ||
-	    test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state))
-		return;
-
-	hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
-
-	/* ep_disconnect could come before NETDEV_DOWN, driver won't
-	 * see NETDEV_DOWN as it already unregistered itself.
-	 */
-	hba->adapter_state = 0;
-	clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
-}
-
-/**
- * bnx2i_unreg_dev_all - unregisters all bnx2i instances with the cnic driver
- *
- * unregisters all bnx2i adapter instances with the cnic driver while holding
- *	the global resource lock
- */
-void bnx2i_unreg_dev_all(void)
-{
-	struct bnx2i_hba *hba, *temp;
-
-	mutex_lock(&bnx2i_dev_lock);
-	list_for_each_entry_safe(hba, temp, &adapter_list, link)
-		bnx2i_unreg_one_device(hba);
-	mutex_unlock(&bnx2i_dev_lock);
-}
-
 
 /**
  * bnx2i_init_one - initialize an adapter instance and allocate memory resources
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index fb50efb..f0dce26 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,7 +1,7 @@
 /*
  * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2009 Broadcom Corporation
+ * Copyright (c) 2006 - 2010 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -10,6 +10,7 @@
  * the Free Software Foundation.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
  */
 
 #include <linux/slab.h>
@@ -411,7 +412,9 @@
 	bnx2i_ep->state = EP_STATE_IDLE;
 	bnx2i_ep->hba->ofld_conns_active--;
 
-	bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid);
+	if (bnx2i_ep->ep_iscsi_cid != (u16) -1)
+		bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid);
+
 	if (bnx2i_ep->conn) {
 		bnx2i_ep->conn->ep = NULL;
 		bnx2i_ep->conn = NULL;
@@ -1383,6 +1386,12 @@
 	ep = iscsi_lookup_endpoint(transport_fd);
 	if (!ep)
 		return -EINVAL;
+	/*
+	 * Forcefully terminate all in progress connection recovery at the
+	 * earliest, either in bind(), send_pdu(LOGIN), or conn_start()
+	 */
+	if (bnx2i_adapter_ready(hba))
+		return -EIO;
 
 	bnx2i_ep = ep->dd_data;
 	if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) ||
@@ -1404,7 +1413,6 @@
 				  hba->netdev->name);
 		return -EEXIST;
 	}
-
 	bnx2i_ep->conn = bnx2i_conn;
 	bnx2i_conn->ep = bnx2i_ep;
 	bnx2i_conn->iscsi_conn_cid = bnx2i_ep->ep_iscsi_cid;
@@ -1461,21 +1469,28 @@
 	struct bnx2i_conn *bnx2i_conn = conn->dd_data;
 	int len = 0;
 
+	if (!(bnx2i_conn && bnx2i_conn->ep && bnx2i_conn->ep->hba))
+		goto out;
+
 	switch (param) {
 	case ISCSI_PARAM_CONN_PORT:
-		if (bnx2i_conn->ep)
+		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
+		if (bnx2i_conn->ep->cm_sk)
 			len = sprintf(buf, "%hu\n",
 				      bnx2i_conn->ep->cm_sk->dst_port);
+		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
 		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
-		if (bnx2i_conn->ep)
+		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
+		if (bnx2i_conn->ep->cm_sk)
 			len = sprintf(buf, "%pI4\n",
 				      &bnx2i_conn->ep->cm_sk->dst_ip);
+		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
 		break;
 	default:
 		return iscsi_conn_get_param(cls_conn, param, buf);
 	}
-
+out:
 	return len;
 }
 
@@ -1599,8 +1614,6 @@
 	struct bnx2i_hba *hba;
 	struct cnic_dev *cnic = NULL;
 
-	bnx2i_reg_dev_all();
-
 	hba = get_adapter_list_head();
 	if (hba && hba->cnic)
 		cnic = hba->cnic->cm_select_dev(desti, CNIC_ULP_ISCSI);
@@ -1640,18 +1653,26 @@
 static int bnx2i_tear_down_conn(struct bnx2i_hba *hba,
 				 struct bnx2i_endpoint *ep)
 {
-	if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic))
+	if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic) && ep->cm_sk)
 		hba->cnic->cm_destroy(ep->cm_sk);
 
-	if (test_bit(ADAPTER_STATE_GOING_DOWN, &ep->hba->adapter_state))
-		ep->state = EP_STATE_DISCONN_COMPL;
-
 	if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type) &&
 	    ep->state == EP_STATE_DISCONN_TIMEDOUT) {
-		printk(KERN_ALERT "bnx2i - ERROR - please submit GRC Dump,"
-				  " NW/PCIe trace, driver msgs to developers"
-				  " for analysis\n");
-		return 1;
+		if (ep->conn && ep->conn->cls_conn &&
+		    ep->conn->cls_conn->dd_data) {
+			struct iscsi_conn *conn = ep->conn->cls_conn->dd_data;
+
+			/* Must suspend all rx queue activity for this ep */
+			set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+		}
+		/* CONN_DISCONNECT timeout may or may not be an issue depending
+		 * on what transcribed in TCP layer, different targets behave
+		 * differently
+		 */
+		printk(KERN_ALERT "bnx2i (%s): - WARN - CONN_DISCON timed out, "
+				  "please submit GRC Dump, NW/PCIe trace, "
+				  "driver msgs to developers for analysis\n",
+				  hba->netdev->name);
 	}
 
 	ep->state = EP_STATE_CLEANUP_START;
@@ -1664,7 +1685,9 @@
 	bnx2i_ep_destroy_list_add(hba, ep);
 
 	/* destroy iSCSI context, wait for it to complete */
-	bnx2i_send_conn_destroy(hba, ep);
+	if (bnx2i_send_conn_destroy(hba, ep))
+		ep->state = EP_STATE_CLEANUP_CMPL;
+
 	wait_event_interruptible(ep->ofld_wait,
 				 (ep->state != EP_STATE_CLEANUP_START));
 
@@ -1711,8 +1734,6 @@
 	if (shost) {
 		/* driver is given scsi host to work with */
 		hba = iscsi_host_priv(shost);
-		/* Register the device with cnic if not already done so */
-		bnx2i_register_device(hba);
 	} else
 		/*
 		 * check if the given destination can be reached through
@@ -1720,13 +1741,17 @@
 		 */
 		hba = bnx2i_check_route(dst_addr);
 
-	if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) {
+	if (!hba) {
 		rc = -EINVAL;
 		goto nohba;
 	}
-
-	cnic = hba->cnic;
 	mutex_lock(&hba->net_dev_lock);
+
+	if (bnx2i_adapter_ready(hba) || !hba->cid_que.cid_free_cnt) {
+		rc = -EPERM;
+		goto check_busy;
+	}
+	cnic = hba->cnic;
 	ep = bnx2i_alloc_ep(hba);
 	if (!ep) {
 		rc = -ENOMEM;
@@ -1734,23 +1759,21 @@
 	}
 	bnx2i_ep = ep->dd_data;
 
-	if (bnx2i_adapter_ready(hba)) {
-		rc = -EPERM;
-		goto net_if_down;
-	}
-
 	bnx2i_ep->num_active_cmds = 0;
 	iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
 	if (iscsi_cid == -1) {
-		printk(KERN_ALERT "alloc_ep: unable to allocate iscsi cid\n");
+		printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
+			"iscsi cid\n", hba->netdev->name);
 		rc = -ENOMEM;
-		goto iscsi_cid_err;
+		bnx2i_free_ep(ep);
+		goto check_busy;
 	}
 	bnx2i_ep->hba_age = hba->age;
 
 	rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep);
 	if (rc != 0) {
-		printk(KERN_ALERT "bnx2i: ep_conn, alloc QP resc error\n");
+		printk(KERN_ALERT "bnx2i (%s): ep_conn - alloc QP resc error"
+			"\n", hba->netdev->name);
 		rc = -ENOMEM;
 		goto qp_resc_err;
 	}
@@ -1765,7 +1788,18 @@
 	bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep;
 	add_timer(&bnx2i_ep->ofld_timer);
 
-	bnx2i_send_conn_ofld_req(hba, bnx2i_ep);
+	if (bnx2i_send_conn_ofld_req(hba, bnx2i_ep)) {
+		if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) {
+			printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n",
+				hba->netdev->name, bnx2i_ep->ep_iscsi_cid);
+			rc = -EBUSY;
+		} else
+			rc = -ENOSPC;
+		printk(KERN_ALERT "bnx2i (%s): unable to send conn offld kwqe"
+			"\n", hba->netdev->name);
+		bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
+		goto conn_failed;
+	}
 
 	/* Wait for CNIC hardware to setup conn context and return 'cid' */
 	wait_event_interruptible(bnx2i_ep->ofld_wait,
@@ -1778,7 +1812,12 @@
 	bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
 
 	if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) {
-		rc = -ENOSPC;
+		if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) {
+			printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n",
+				hba->netdev->name, bnx2i_ep->ep_iscsi_cid);
+			rc = -EBUSY;
+		} else
+			rc = -ENOSPC;
 		goto conn_failed;
 	}
 
@@ -1786,7 +1825,8 @@
 			     iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep);
 	if (rc) {
 		rc = -EINVAL;
-		goto conn_failed;
+		/* Need to terminate and cleanup the connection */
+		goto release_ep;
 	}
 
 	bnx2i_ep->cm_sk->rcv_buf = 256 * 1024;
@@ -1830,15 +1870,12 @@
 		return ERR_PTR(rc);
 	}
 conn_failed:
-net_if_down:
-iscsi_cid_err:
 	bnx2i_free_qp_resc(hba, bnx2i_ep);
 qp_resc_err:
 	bnx2i_free_ep(ep);
 check_busy:
 	mutex_unlock(&hba->net_dev_lock);
 nohba:
-	bnx2i_unreg_dev_all();
 	return ERR_PTR(rc);
 }
 
@@ -1898,12 +1935,13 @@
 		cnic_dev_10g = 1;
 
 	switch (bnx2i_ep->state) {
-	case EP_STATE_CONNECT_START:
+	case EP_STATE_CONNECT_FAILED:
 	case EP_STATE_CLEANUP_FAILED:
 	case EP_STATE_OFLD_FAILED:
 	case EP_STATE_DISCONN_TIMEDOUT:
 		ret = 0;
 		break;
+	case EP_STATE_CONNECT_START:
 	case EP_STATE_CONNECT_COMPL:
 	case EP_STATE_ULP_UPDATE_START:
 	case EP_STATE_ULP_UPDATE_COMPL:
@@ -1914,13 +1952,10 @@
 		ret = 1;
 		break;
 	case EP_STATE_TCP_RST_RCVD:
-		ret = 0;
-		break;
-	case EP_STATE_CONNECT_FAILED:
 		if (cnic_dev_10g)
-			ret = 1;
-		else
 			ret = 0;
+		else
+			ret = 1;
 		break;
 	default:
 		ret = 0;
@@ -1953,7 +1988,8 @@
 	if (!cnic)
 		return 0;
 
-	if (bnx2i_ep->state == EP_STATE_IDLE)
+	if (bnx2i_ep->state == EP_STATE_IDLE ||
+	    bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT)
 		return 0;
 
 	if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
@@ -1979,9 +2015,10 @@
 			if (session->state == ISCSI_STATE_LOGGING_OUT) {
 				if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) {
 					/* Logout sent, but no resp */
-					printk(KERN_ALERT "bnx2i - WARNING "
-						"logout response was not "
-						"received!\n");
+					printk(KERN_ALERT "bnx2i (%s): WARNING"
+						" logout response was not "
+						"received!\n",
+						bnx2i_ep->hba->netdev->name);
 				} else if (bnx2i_ep->state ==
 					   EP_STATE_LOGOUT_RESP_RCVD)
 					close = 1;
@@ -1999,9 +2036,8 @@
 	else
 		close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
 
-	/* No longer allow CFC delete if cm_close/abort fails the request */
 	if (close_ret)
-		printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n",
+		printk(KERN_ALERT "bnx2i (%s): close/abort(%d) returned %d\n",
 			bnx2i_ep->hba->netdev->name, close, close_ret);
 	else
 		/* wait for option-2 conn teardown */
@@ -2015,7 +2051,7 @@
 destroy_conn:
 	bnx2i_ep_active_list_del(hba, bnx2i_ep);
 	if (bnx2i_tear_down_conn(hba, bnx2i_ep))
-		ret = -EINVAL;
+		return -EINVAL;
 out:
 	bnx2i_ep->state = EP_STATE_IDLE;
 	return ret;
@@ -2054,14 +2090,17 @@
 
 	mutex_lock(&hba->net_dev_lock);
 
+	if (bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT)
+		goto out;
+
 	if (bnx2i_ep->state == EP_STATE_IDLE)
-		goto return_bnx2i_ep;
-
-	if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
 		goto free_resc;
 
-	if (bnx2i_ep->hba_age != hba->age)
+	if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) ||
+	    (bnx2i_ep->hba_age != hba->age)) {
+		bnx2i_ep_active_list_del(hba, bnx2i_ep);
 		goto free_resc;
+	}
 
 	/* Do all chip cleanup here */
 	if (bnx2i_hw_ep_disconnect(bnx2i_ep)) {
@@ -2070,14 +2109,13 @@
 	}
 free_resc:
 	bnx2i_free_qp_resc(hba, bnx2i_ep);
-return_bnx2i_ep:
+
 	if (bnx2i_conn)
 		bnx2i_conn->ep = NULL;
 
 	bnx2i_free_ep(ep);
+out:
 	mutex_unlock(&hba->net_dev_lock);
-	if (!hba->ofld_conns_active)
-		bnx2i_unreg_dev_all();
 
 	wake_up_interruptible(&hba->eh_wait);
 }
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 96426b7..9174196 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,12 +1,13 @@
 /* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2004 - 2009 Broadcom Corporation
+ * Copyright (c) 2004 - 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.
  *
  * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
+ * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
  */
 
 #include "bnx2i.h"
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index 6fae3d2..b837c5b 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -442,12 +442,19 @@
 	sdev = q->queuedata;
 	if (sdev && sdev->scsi_dh_data)
 		scsi_dh = sdev->scsi_dh_data->scsi_dh;
-	if (!scsi_dh || !get_device(&sdev->sdev_gendev))
+	if (!scsi_dh || !get_device(&sdev->sdev_gendev) ||
+	    sdev->sdev_state == SDEV_CANCEL ||
+	    sdev->sdev_state == SDEV_DEL)
 		err = SCSI_DH_NOSYS;
+	if (sdev->sdev_state == SDEV_OFFLINE)
+		err = SCSI_DH_DEV_OFFLINED;
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
-	if (err)
+	if (err) {
+		if (fn)
+			fn(data, err);
 		return err;
+	}
 
 	if (scsi_dh->activate)
 		err = scsi_dh->activate(sdev, fn, data);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index d23a538..9f9600b 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -854,7 +854,6 @@
 
 	/* Cleanup the fc_lport */
 	fc_lport_destroy(lport);
-	fc_fcp_destroy(lport);
 
 	/* Stop the transmit retry timer */
 	del_timer_sync(&port->timer);
@@ -876,6 +875,9 @@
 	fc_remove_host(lport->host);
 	scsi_remove_host(lport->host);
 
+	/* Destroy lport scsi_priv */
+	fc_fcp_destroy(lport);
+
 	/* There are no more rports or I/O, free the EM */
 	fc_exch_mgr_free(lport);
 
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index bc17c71..625c6be 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -54,6 +54,7 @@
 static void fcoe_ctlr_timeout(unsigned long);
 static void fcoe_ctlr_timer_work(struct work_struct *);
 static void fcoe_ctlr_recv_work(struct work_struct *);
+static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
 
 static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
 static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
@@ -176,6 +177,7 @@
 	fip->mode = mode;
 	INIT_LIST_HEAD(&fip->fcfs);
 	mutex_init(&fip->ctlr_mutex);
+	spin_lock_init(&fip->ctlr_lock);
 	fip->flogi_oxid = FC_XID_UNKNOWN;
 	setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
 	INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
@@ -231,6 +233,49 @@
 EXPORT_SYMBOL(fcoe_ctlr_destroy);
 
 /**
+ * fcoe_ctlr_announce() - announce new FCF selection
+ * @fip: The FCoE controller
+ *
+ * Also sets the destination MAC for FCoE and control packets
+ *
+ * Called with neither ctlr_mutex nor ctlr_lock held.
+ */
+static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *sel;
+	struct fcoe_fcf *fcf;
+
+	mutex_lock(&fip->ctlr_mutex);
+	spin_lock_bh(&fip->ctlr_lock);
+
+	kfree_skb(fip->flogi_req);
+	fip->flogi_req = NULL;
+	list_for_each_entry(fcf, &fip->fcfs, list)
+		fcf->flogi_sent = 0;
+
+	spin_unlock_bh(&fip->ctlr_lock);
+	sel = fip->sel_fcf;
+
+	if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
+		goto unlock;
+	if (!is_zero_ether_addr(fip->dest_addr)) {
+		printk(KERN_NOTICE "libfcoe: host%d: "
+		       "FIP Fibre-Channel Forwarder MAC %pM deselected\n",
+		       fip->lp->host->host_no, fip->dest_addr);
+		memset(fip->dest_addr, 0, ETH_ALEN);
+	}
+	if (sel) {
+		printk(KERN_INFO "libfcoe: host%d: FIP selected "
+		       "Fibre-Channel Forwarder MAC %pM\n",
+		       fip->lp->host->host_no, sel->fcf_mac);
+		memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
+		fip->map_dest = 0;
+	}
+unlock:
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
  * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port
  * @fip: The FCoE controller to get the maximum FCoE size from
  *
@@ -564,6 +609,9 @@
  * The caller must check that the length is a multiple of 4.
  * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
  * The the skb must also be an fc_frame.
+ *
+ * This is called from the lower-level driver with spinlocks held,
+ * so we must not take a mutex here.
  */
 int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
 		       struct sk_buff *skb)
@@ -601,7 +649,15 @@
 	switch (op) {
 	case ELS_FLOGI:
 		op = FIP_DT_FLOGI;
-		break;
+		if (fip->mode == FIP_MODE_VN2VN)
+			break;
+		spin_lock_bh(&fip->ctlr_lock);
+		kfree_skb(fip->flogi_req);
+		fip->flogi_req = skb;
+		fip->flogi_req_send = 1;
+		spin_unlock_bh(&fip->ctlr_lock);
+		schedule_work(&fip->timer_work);
+		return -EINPROGRESS;
 	case ELS_FDISC:
 		if (ntoh24(fh->fh_s_id))
 			return 0;
@@ -922,11 +978,9 @@
 	}
 	mtu_valid = fcoe_ctlr_mtu_valid(fcf);
 	fcf->time = jiffies;
-	if (!found) {
-		LIBFCOE_FIP_DBG(fip, "New FCF for fab %16.16llx "
-				"map %x val %d\n",
-				fcf->fabric_name, fcf->fc_map, mtu_valid);
-	}
+	if (!found)
+		LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
+				fcf->fabric_name, fcf->fcf_mac);
 
 	/*
 	 * If this advertisement is not solicited and our max receive size
@@ -945,6 +999,17 @@
 		fcoe_ctlr_solicit(fip, NULL);
 
 	/*
+	 * Put this FCF at the head of the list for priority among equals.
+	 * This helps in the case of an NPV switch which insists we use
+	 * the FCF that answers multicast solicitations, not the others that
+	 * are sending periodic multicast advertisements.
+	 */
+	if (mtu_valid) {
+		list_del(&fcf->list);
+		list_add(&fcf->list, &fip->fcfs);
+	}
+
+	/*
 	 * If this is the first validated FCF, note the time and
 	 * set a timer to trigger selection.
 	 */
@@ -1061,18 +1126,24 @@
 	els_op = *(u8 *)(fh + 1);
 
 	if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
-	    sub == FIP_SC_REP && els_op == ELS_LS_ACC &&
-	    fip->mode != FIP_MODE_VN2VN) {
-		if (!is_valid_ether_addr(granted_mac)) {
-			LIBFCOE_FIP_DBG(fip,
-				"Invalid MAC address %pM in FIP ELS\n",
-				granted_mac);
-			goto drop;
-		}
-		memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
+	    sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
+		if (els_op == ELS_LS_ACC) {
+			if (!is_valid_ether_addr(granted_mac)) {
+				LIBFCOE_FIP_DBG(fip,
+					"Invalid MAC address %pM in FIP ELS\n",
+					granted_mac);
+				goto drop;
+			}
+			memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
 
-		if (fip->flogi_oxid == ntohs(fh->fh_ox_id))
-			fip->flogi_oxid = FC_XID_UNKNOWN;
+			if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
+				fip->flogi_oxid = FC_XID_UNKNOWN;
+				if (els_dtype == FIP_DT_FLOGI)
+					fcoe_ctlr_announce(fip);
+			}
+		} else if (els_dtype == FIP_DT_FLOGI &&
+			   !fcoe_ctlr_flogi_retry(fip))
+			goto drop;	/* retrying FLOGI so drop reject */
 	}
 
 	if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
@@ -1326,20 +1397,39 @@
  * fcoe_ctlr_select() - Select the best FCF (if possible)
  * @fip: The FCoE controller
  *
+ * Returns the selected FCF, or NULL if none are usable.
+ *
  * If there are conflicting advertisements, no FCF can be chosen.
  *
+ * If there is already a selected FCF, this will choose a better one or
+ * an equivalent one that hasn't already been sent a FLOGI.
+ *
  * Called with lock held.
  */
-static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
+static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
 {
 	struct fcoe_fcf *fcf;
-	struct fcoe_fcf *best = NULL;
+	struct fcoe_fcf *best = fip->sel_fcf;
+	struct fcoe_fcf *first;
+
+	first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
 
 	list_for_each_entry(fcf, &fip->fcfs, list) {
-		LIBFCOE_FIP_DBG(fip, "consider FCF for fab %16.16llx "
-				"VFID %d map %x val %d\n",
-				fcf->fabric_name, fcf->vfid,
-				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf));
+		LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx "
+				"VFID %d mac %pM map %x val %d "
+				"sent %u pri %u\n",
+				fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
+				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
+				fcf->flogi_sent, fcf->pri);
+		if (fcf->fabric_name != first->fabric_name ||
+		    fcf->vfid != first->vfid ||
+		    fcf->fc_map != first->fc_map) {
+			LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
+					"or FC-MAP\n");
+			return NULL;
+		}
+		if (fcf->flogi_sent)
+			continue;
 		if (!fcoe_ctlr_fcf_usable(fcf)) {
 			LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
 					"map %x %svalid %savailable\n",
@@ -1349,21 +1439,131 @@
 					"" : "un");
 			continue;
 		}
-		if (!best) {
-			best = fcf;
-			continue;
-		}
-		if (fcf->fabric_name != best->fabric_name ||
-		    fcf->vfid != best->vfid ||
-		    fcf->fc_map != best->fc_map) {
-			LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
-					"or FC-MAP\n");
-			return;
-		}
-		if (fcf->pri < best->pri)
+		if (!best || fcf->pri < best->pri || best->flogi_sent)
 			best = fcf;
 	}
 	fip->sel_fcf = best;
+	if (best) {
+		LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac);
+		fip->port_ka_time = jiffies +
+			msecs_to_jiffies(FIP_VN_KA_PERIOD);
+		fip->ctlr_ka_time = jiffies + best->fka_period;
+		if (time_before(fip->ctlr_ka_time, fip->timer.expires))
+			mod_timer(&fip->timer, fip->ctlr_ka_time);
+	}
+	return best;
+}
+
+/**
+ * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error if it could not be sent.
+ *
+ * Called with ctlr_mutex and ctlr_lock held.
+ * Caller must verify that fip->sel_fcf is not NULL.
+ */
+static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
+{
+	struct sk_buff *skb;
+	struct sk_buff *skb_orig;
+	struct fc_frame_header *fh;
+	int error;
+
+	skb_orig = fip->flogi_req;
+	if (!skb_orig)
+		return -EINVAL;
+
+	/*
+	 * Clone and send the FLOGI request.  If clone fails, use original.
+	 */
+	skb = skb_clone(skb_orig, GFP_ATOMIC);
+	if (!skb) {
+		skb = skb_orig;
+		fip->flogi_req = NULL;
+	}
+	fh = (struct fc_frame_header *)skb->data;
+	error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
+				 ntoh24(fh->fh_d_id));
+	if (error) {
+		kfree_skb(skb);
+		return error;
+	}
+	fip->send(fip, skb);
+	fip->sel_fcf->flogi_sent = 1;
+	return 0;
+}
+
+/**
+ * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error code if there's no FLOGI request to retry or
+ * no alternate FCF available.
+ */
+static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	int error;
+
+	mutex_lock(&fip->ctlr_mutex);
+	spin_lock_bh(&fip->ctlr_lock);
+	LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
+	fcf = fcoe_ctlr_select(fip);
+	if (!fcf || fcf->flogi_sent) {
+		kfree_skb(fip->flogi_req);
+		fip->flogi_req = NULL;
+		error = -ENOENT;
+	} else {
+		fcoe_ctlr_solicit(fip, NULL);
+		error = fcoe_ctlr_flogi_send_locked(fip);
+	}
+	spin_unlock_bh(&fip->ctlr_lock);
+	mutex_unlock(&fip->ctlr_mutex);
+	return error;
+}
+
+
+/**
+ * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
+ * @fip: The FCoE controller that timed out
+ *
+ * Done here because fcoe_ctlr_els_send() can't get mutex.
+ *
+ * Called with ctlr_mutex held.  The caller must not hold ctlr_lock.
+ */
+static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+
+	spin_lock_bh(&fip->ctlr_lock);
+	fcf = fip->sel_fcf;
+	if (!fcf || !fip->flogi_req_send)
+		goto unlock;
+
+	LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
+
+	/*
+	 * If this FLOGI is being sent due to a timeout retry
+	 * to the same FCF as before, select a different FCF if possible.
+	 */
+	if (fcf->flogi_sent) {
+		LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
+		fcf = fcoe_ctlr_select(fip);
+		if (!fcf || fcf->flogi_sent) {
+			LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
+			list_for_each_entry(fcf, &fip->fcfs, list)
+				fcf->flogi_sent = 0;
+			fcf = fcoe_ctlr_select(fip);
+		}
+	}
+	if (fcf) {
+		fcoe_ctlr_flogi_send_locked(fip);
+		fip->flogi_req_send = 0;
+	} else /* XXX */
+		LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
+unlock:
+	spin_unlock_bh(&fip->ctlr_lock);
 }
 
 /**
@@ -1411,34 +1611,16 @@
 	sel = fip->sel_fcf;
 	if (!sel && fip->sel_time) {
 		if (time_after_eq(jiffies, fip->sel_time)) {
-			fcoe_ctlr_select(fip);
-			sel = fip->sel_fcf;
+			sel = fcoe_ctlr_select(fip);
 			fip->sel_time = 0;
 		} else if (time_after(next_timer, fip->sel_time))
 			next_timer = fip->sel_time;
 	}
 
-	if (sel != fcf) {
-		fcf = sel;		/* the old FCF may have been freed */
-		if (sel) {
-			printk(KERN_INFO "libfcoe: host%d: FIP selected "
-			       "Fibre-Channel Forwarder MAC %pM\n",
-			       fip->lp->host->host_no, sel->fcf_mac);
-			memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
-			fip->map_dest = 0;
-			fip->port_ka_time = jiffies +
-				msecs_to_jiffies(FIP_VN_KA_PERIOD);
-			fip->ctlr_ka_time = jiffies + sel->fka_period;
-			if (time_after(next_timer, fip->ctlr_ka_time))
-				next_timer = fip->ctlr_ka_time;
-		} else {
-			printk(KERN_NOTICE "libfcoe: host%d: "
-			       "FIP Fibre-Channel Forwarder timed out.	"
-			       "Starting FCF discovery.\n",
-			       fip->lp->host->host_no);
-			reset = 1;
-		}
-	}
+	if (sel && fip->flogi_req_send)
+		fcoe_ctlr_flogi_send(fip);
+	else if (!sel && fcf)
+		reset = 1;
 
 	if (sel && !sel->fd_flags) {
 		if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
@@ -2475,7 +2657,7 @@
 	case FIP_ST_LINK_WAIT:
 		goto unlock;
 	default:
-		WARN(1, "unexpected state %d", fip->state);
+		WARN(1, "unexpected state %d\n", fip->state);
 		goto unlock;
 	}
 	mod_timer(&fip->timer, next_time);
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 7636570..3242bca 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4273,8 +4273,10 @@
     }
 
     rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info);
-    if (rval < 0)
+    if (rval < 0) {
+	gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr);
         return rval;
+    }
     gen.status = rval;
 
     if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, 
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 0572b9b..6527543 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -365,8 +365,10 @@
                     len = 0;
                     begin = pos;
                 }
-                if (pos > offset + length)
+		if (pos > offset + length) {
+		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
                     goto stop_output;
+		}
             }
         }
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
@@ -450,8 +452,10 @@
                     len = 0;
                     begin = pos;
                 }
-                if (pos > offset + length)
+		if (pos > offset + length) {
+		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
                     goto stop_output;
+		}
             } while (drv_no != -1);
              
             if (is_mirr) {
@@ -472,8 +476,10 @@
                 len = 0;
                 begin = pos;
             }
-            if (pos > offset + length)
+	    if (pos > offset + length) {
+		gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
                 goto stop_output;
+	    }
         }       
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
         
@@ -542,8 +548,10 @@
                     len = 0;
                     begin = pos;
                 }
-                if (pos > offset + length)
+		if (pos > offset + length) {
+		    gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
                     goto stop_output;
+		}
             }
         }
         gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr);
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a6dea08..12deffc 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -641,11 +641,6 @@
 static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1,
 	struct hpsa_scsi_dev_t *dev2)
 {
-	if ((is_logical_dev_addr_mode(dev1->scsi3addr) ||
-		(dev1->lun != -1 && dev2->lun != -1)) &&
-		dev1->devtype != 0x0C)
-		return (memcmp(dev1, dev2, sizeof(*dev1)) == 0);
-
 	/* we compare everything except lun and target as these
 	 * are not yet assigned.  Compare parts likely
 	 * to differ first
@@ -660,12 +655,8 @@
 		return 0;
 	if (memcmp(dev1->vendor, dev2->vendor, sizeof(dev1->vendor)) != 0)
 		return 0;
-	if (memcmp(dev1->revision, dev2->revision, sizeof(dev1->revision)) != 0)
-		return 0;
 	if (dev1->devtype != dev2->devtype)
 		return 0;
-	if (dev1->raid_level != dev2->raid_level)
-		return 0;
 	if (dev1->bus != dev2->bus)
 		return 0;
 	return 1;
@@ -1477,8 +1468,6 @@
 		sizeof(this_device->vendor));
 	memcpy(this_device->model, &inq_buff[16],
 		sizeof(this_device->model));
-	memcpy(this_device->revision, &inq_buff[32],
-		sizeof(this_device->revision));
 	memset(this_device->device_id, 0,
 		sizeof(this_device->device_id));
 	hpsa_get_device_id(h, scsi3addr, this_device->device_id,
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index a203ef6..19586e1 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -45,7 +45,6 @@
 	unsigned char device_id[16];    /* from inquiry pg. 0x83 */
 	unsigned char vendor[8];        /* bytes 8-15 of inquiry data */
 	unsigned char model[16];        /* bytes 16-31 of inquiry data */
-	unsigned char revision[4];      /* bytes 32-35 of inquiry data */
 	unsigned char raid_level;	/* from inquiry page 0xC1 */
 };
 
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 57cad7e..b765061 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2493,23 +2493,23 @@
 }
 
 static const struct ibmvfc_async_desc ae_desc [] = {
-	{ IBMVFC_AE_ELS_PLOGI,		"PLOGI",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
-	{ IBMVFC_AE_ELS_LOGO,		"LOGO",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
-	{ IBMVFC_AE_ELS_PRLO,		"PRLO",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
-	{ IBMVFC_AE_SCN_NPORT,		"N-Port SCN",	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
-	{ IBMVFC_AE_SCN_GROUP,		"Group SCN",	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
-	{ IBMVFC_AE_SCN_DOMAIN,		"Domain SCN",	IBMVFC_DEFAULT_LOG_LEVEL },
-	{ IBMVFC_AE_SCN_FABRIC,		"Fabric SCN",	IBMVFC_DEFAULT_LOG_LEVEL },
-	{ IBMVFC_AE_LINK_UP,		"Link Up",		IBMVFC_DEFAULT_LOG_LEVEL },
-	{ IBMVFC_AE_LINK_DOWN,		"Link Down",	IBMVFC_DEFAULT_LOG_LEVEL },
-	{ IBMVFC_AE_LINK_DEAD,		"Link Dead",	IBMVFC_DEFAULT_LOG_LEVEL },
-	{ IBMVFC_AE_HALT,			"Halt",		IBMVFC_DEFAULT_LOG_LEVEL },
-	{ IBMVFC_AE_RESUME,		"Resume",		IBMVFC_DEFAULT_LOG_LEVEL },
-	{ IBMVFC_AE_ADAPTER_FAILED,	"Adapter Failed",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "PLOGI",	IBMVFC_AE_ELS_PLOGI,	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ "LOGO",	IBMVFC_AE_ELS_LOGO,	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ "PRLO",	IBMVFC_AE_ELS_PRLO,	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ "N-Port SCN",	IBMVFC_AE_SCN_NPORT,	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ "Group SCN",	IBMVFC_AE_SCN_GROUP,	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ "Domain SCN",	IBMVFC_AE_SCN_DOMAIN,	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "Fabric SCN",	IBMVFC_AE_SCN_FABRIC,	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "Link Up",	IBMVFC_AE_LINK_UP,	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "Link Down",	IBMVFC_AE_LINK_DOWN,	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "Link Dead",	IBMVFC_AE_LINK_DEAD,	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "Halt",	IBMVFC_AE_HALT,		IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "Resume",	IBMVFC_AE_RESUME,	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ "Adapter Failed", IBMVFC_AE_ADAPTER_FAILED, IBMVFC_DEFAULT_LOG_LEVEL },
 };
 
 static const struct ibmvfc_async_desc unknown_ae = {
-	0, "Unknown async", IBMVFC_DEFAULT_LOG_LEVEL
+	"Unknown async", 0, IBMVFC_DEFAULT_LOG_LEVEL
 };
 
 /**
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index ef663e7..834c37f 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -542,8 +542,8 @@
 };
 
 struct ibmvfc_async_desc {
-	enum ibmvfc_async_event ae;
 	const char *desc;
+	enum ibmvfc_async_event ae;
 	int log_level;
 };
 
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5bbaee5..de2e09e 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -146,7 +146,7 @@
 		}
 	},
 	{ /* CRoC */
-		.mailbox = 0x00040,
+		.mailbox = 0x00044,
 		.cache_line_size = 0x20,
 		{
 			.set_interrupt_mask_reg = 0x00010,
@@ -1048,6 +1048,8 @@
 			sizeof(res->res_path));
 
 		res->bus = 0;
+		memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
+			sizeof(res->dev_lun.scsi_lun));
 		res->lun = scsilun_to_int(&res->dev_lun);
 
 		if (res->type == IPR_RES_TYPE_GENERIC_SCSI) {
@@ -1063,9 +1065,6 @@
 								  ioa_cfg->max_devs_supported);
 				set_bit(res->target, ioa_cfg->target_ids);
 			}
-
-			memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
-				sizeof(res->dev_lun.scsi_lun));
 		} else if (res->type == IPR_RES_TYPE_IOAFP) {
 			res->bus = IPR_IOAFP_VIRTUAL_BUS;
 			res->target = 0;
@@ -1116,7 +1115,7 @@
 	if (res->ioa_cfg->sis64) {
 		if (!memcmp(&res->dev_id, &cfgtew->u.cfgte64->dev_id,
 					sizeof(cfgtew->u.cfgte64->dev_id)) &&
-			!memcmp(&res->lun, &cfgtew->u.cfgte64->lun,
+			!memcmp(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
 					sizeof(cfgtew->u.cfgte64->lun))) {
 			return 1;
 		}
@@ -2901,6 +2900,12 @@
 		return;
 	}
 
+	if (ioa_cfg->sis64) {
+		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+		ssleep(IPR_DUMP_DELAY_SECONDS);
+		spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	}
+
 	start_addr = readl(ioa_cfg->ioa_mailbox);
 
 	if (!ioa_cfg->sis64 && !ipr_sdt_is_fmt2(start_addr)) {
@@ -7473,6 +7478,29 @@
 }
 
 /**
+ * ipr_reset_get_unit_check_job - Call to get the unit check buffer.
+ * @ipr_cmd:	ipr command struct
+ *
+ * Description: This function will call to get the unit check buffer.
+ *
+ * Return value:
+ *	IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd)
+{
+	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
+	ENTER;
+	ioa_cfg->ioa_unit_checked = 0;
+	ipr_get_unit_check_buffer(ioa_cfg);
+	ipr_cmd->job_step = ipr_reset_alert;
+	ipr_reset_start_timer(ipr_cmd, 0);
+
+	LEAVE;
+	return IPR_RC_JOB_RETURN;
+}
+
+/**
  * ipr_reset_restore_cfg_space - Restore PCI config space.
  * @ipr_cmd:	ipr command struct
  *
@@ -7512,11 +7540,17 @@
 	}
 
 	if (ioa_cfg->ioa_unit_checked) {
-		ioa_cfg->ioa_unit_checked = 0;
-		ipr_get_unit_check_buffer(ioa_cfg);
-		ipr_cmd->job_step = ipr_reset_alert;
-		ipr_reset_start_timer(ipr_cmd, 0);
-		return IPR_RC_JOB_RETURN;
+		if (ioa_cfg->sis64) {
+			ipr_cmd->job_step = ipr_reset_get_unit_check_job;
+			ipr_reset_start_timer(ipr_cmd, IPR_DUMP_DELAY_TIMEOUT);
+			return IPR_RC_JOB_RETURN;
+		} else {
+			ioa_cfg->ioa_unit_checked = 0;
+			ipr_get_unit_check_buffer(ioa_cfg);
+			ipr_cmd->job_step = ipr_reset_alert;
+			ipr_reset_start_timer(ipr_cmd, 0);
+			return IPR_RC_JOB_RETURN;
+		}
 	}
 
 	if (ioa_cfg->in_ioa_bringdown) {
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index b28a00f..13f425f 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -218,6 +218,8 @@
 #define IPR_WAIT_FOR_BIST_TIMEOUT		(2 * HZ)
 #define IPR_PCI_RESET_TIMEOUT			(HZ / 2)
 #define IPR_DUMP_TIMEOUT			(15 * HZ)
+#define IPR_DUMP_DELAY_SECONDS			4
+#define IPR_DUMP_DELAY_TIMEOUT			(IPR_DUMP_DELAY_SECONDS * HZ)
 
 /*
  * SCSI Literals
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index ec2a1ae..d21367d 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -67,6 +67,11 @@
 struct fc_exch_pool {
 	u16		 next_index;
 	u16		 total_exches;
+
+	/* two cache of free slot in exch array */
+	u16		 left;
+	u16		 right;
+
 	spinlock_t	 lock;
 	struct list_head ex_list;
 };
@@ -108,7 +113,6 @@
 		atomic_t non_bls_resp;
 	} stats;
 };
-#define	fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
 
 /**
  * struct fc_exch_mgr_anchor - primary structure for list of EMs
@@ -397,13 +401,23 @@
 static void fc_exch_delete(struct fc_exch *ep)
 {
 	struct fc_exch_pool *pool;
+	u16 index;
 
 	pool = ep->pool;
 	spin_lock_bh(&pool->lock);
 	WARN_ON(pool->total_exches <= 0);
 	pool->total_exches--;
-	fc_exch_ptr_set(pool, (ep->xid - ep->em->min_xid) >> fc_cpu_order,
-			NULL);
+
+	/* update cache of free slot */
+	index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
+	if (pool->left == FC_XID_UNKNOWN)
+		pool->left = index;
+	else if (pool->right == FC_XID_UNKNOWN)
+		pool->right = index;
+	else
+		pool->next_index = index;
+
+	fc_exch_ptr_set(pool, index, NULL);
 	list_del(&ep->ex_list);
 	spin_unlock_bh(&pool->lock);
 	fc_exch_release(ep);	/* drop hold for exch in mp */
@@ -636,10 +650,13 @@
 		if (e_stat & ESB_ST_ABNORMAL)
 			rc = fc_exch_done_locked(ep);
 		spin_unlock_bh(&ep->ex_lock);
-		if (!rc)
-			fc_exch_delete(ep);
 		if (resp)
 			resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
+		if (!rc) {
+			/* delete the exchange if it's already being aborted */
+			fc_exch_delete(ep);
+			return;
+		}
 		fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
 		goto done;
 	}
@@ -679,6 +696,19 @@
 	pool = per_cpu_ptr(mp->pool, cpu);
 	spin_lock_bh(&pool->lock);
 	put_cpu();
+
+	/* peek cache of free slot */
+	if (pool->left != FC_XID_UNKNOWN) {
+		index = pool->left;
+		pool->left = FC_XID_UNKNOWN;
+		goto hit;
+	}
+	if (pool->right != FC_XID_UNKNOWN) {
+		index = pool->right;
+		pool->right = FC_XID_UNKNOWN;
+		goto hit;
+	}
+
 	index = pool->next_index;
 	/* allocate new exch from pool */
 	while (fc_exch_ptr_get(pool, index)) {
@@ -687,7 +717,7 @@
 			goto err;
 	}
 	pool->next_index = index == mp->pool_max_index ? 0 : index + 1;
-
+hit:
 	fc_exch_hold(ep);	/* hold for exch in mp */
 	spin_lock_init(&ep->ex_lock);
 	/*
@@ -1247,7 +1277,7 @@
 
 	list_for_each_entry(ema, &lport->ema_list, ema_list)
 		if ((!ema->match || ema->match(fp)) &&
-		    fc_seq_lookup_recip(lport, ema->mp, fp) != FC_RJT_NONE)
+		    fc_seq_lookup_recip(lport, ema->mp, fp) == FC_RJT_NONE)
 			break;
 	return fr_seq(fp);
 }
@@ -1343,7 +1373,7 @@
 	}
 	if (ep->esb_stat & ESB_ST_COMPLETE) {
 		atomic_inc(&mp->stats.xid_not_found);
-		goto out;
+		goto rel;
 	}
 	if (ep->rxid == FC_XID_UNKNOWN)
 		ep->rxid = ntohs(fh->fh_rx_id);
@@ -2181,6 +2211,8 @@
 		goto free_mempool;
 	for_each_possible_cpu(cpu) {
 		pool = per_cpu_ptr(mp->pool, cpu);
+		pool->left = FC_XID_UNKNOWN;
+		pool->right = FC_XID_UNKNOWN;
 		spin_lock_init(&pool->lock);
 		INIT_LIST_HEAD(&pool->ex_list);
 	}
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 2924363..cdc06cd 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -57,6 +57,9 @@
 #define FC_SRB_READ		(1 << 1)
 #define FC_SRB_WRITE		(1 << 0)
 
+/* constant added to e_d_tov timeout to get rec_tov value */
+#define REC_TOV_CONST		1
+
 /*
  * The SCp.ptr should be tested and set under the scsi_pkt_queue lock
  */
@@ -96,7 +99,7 @@
 static void fc_fcp_complete_locked(struct fc_fcp_pkt *);
 static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *);
 static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *);
-static void fc_fcp_recovery(struct fc_fcp_pkt *);
+static void fc_fcp_recovery(struct fc_fcp_pkt *, u8 code);
 static void fc_fcp_timeout(unsigned long);
 static void fc_fcp_rec(struct fc_fcp_pkt *);
 static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *);
@@ -120,14 +123,13 @@
 #define FC_DATA_UNDRUN		7
 #define FC_ERROR		8
 #define FC_HRD_ERROR		9
-#define FC_CMD_RECOVERY		10
+#define FC_CRC_ERROR		10
+#define FC_TIMED_OUT		11
 
 /*
  * Error recovery timeout values.
  */
-#define FC_SCSI_ER_TIMEOUT	(10 * HZ)
 #define FC_SCSI_TM_TOV		(10 * HZ)
-#define FC_SCSI_REC_TOV		(2 * HZ)
 #define FC_HOST_RESET_TIMEOUT	(30 * HZ)
 #define FC_CAN_QUEUE_PERIOD	(60 * HZ)
 
@@ -438,6 +440,7 @@
 	void *buf;
 	struct scatterlist *sg;
 	u32 nents;
+	u8 host_bcode = FC_COMPLETE;
 
 	fh = fc_frame_header_get(fp);
 	offset = ntohl(fh->fh_parm_offset);
@@ -446,13 +449,16 @@
 	buf = fc_frame_payload_get(fp, 0);
 
 	/*
-	 * if this I/O is ddped then clear it
-	 * and initiate recovery since data
-	 * frames are expected to be placed
-	 * directly in that case.
+	 * if this I/O is ddped then clear it and initiate recovery since data
+	 * frames are expected to be placed directly in that case.
+	 *
+	 * Indicate error to scsi-ml because something went wrong with the
+	 * ddp handling to get us here.
 	 */
 	if (fsp->xfer_ddp != FC_XID_UNKNOWN) {
 		fc_fcp_ddp_done(fsp);
+		FC_FCP_DBG(fsp, "DDP I/O in fc_fcp_recv_data set ERROR\n");
+		host_bcode = FC_ERROR;
 		goto err;
 	}
 	if (offset + len > fsp->data_len) {
@@ -462,6 +468,9 @@
 			goto crc_err;
 		FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx "
 			   "data_len %x\n", len, offset, fsp->data_len);
+
+		/* Data is corrupted indicate scsi-ml should retry */
+		host_bcode = FC_DATA_OVRRUN;
 		goto err;
 	}
 	if (offset != fsp->xfer_len)
@@ -498,8 +507,10 @@
 			 * If so, we need to retry the entire operation.
 			 * Otherwise, ignore it.
 			 */
-			if (fsp->state & FC_SRB_DISCONTIG)
+			if (fsp->state & FC_SRB_DISCONTIG) {
+				host_bcode = FC_CRC_ERROR;
 				goto err;
+			}
 			return;
 		}
 	}
@@ -517,7 +528,7 @@
 		fc_fcp_complete_locked(fsp);
 	return;
 err:
-	fc_fcp_recovery(fsp);
+	fc_fcp_recovery(fsp, host_bcode);
 }
 
 /**
@@ -962,7 +973,13 @@
 		}
 		lport->tt.exch_done(seq);
 	}
-	fc_io_compl(fsp);
+	/*
+	 * Some resets driven by SCSI are not I/Os and do not have
+	 * SCSI commands associated with the requests. We should not
+	 * call I/O completion if we do not have a SCSI command.
+	 */
+	if (fsp->cmd)
+		fc_io_compl(fsp);
 }
 
 /**
@@ -1073,6 +1090,21 @@
 }
 
 /**
+ * get_fsp_rec_tov() - Helper function to get REC_TOV
+ * @fsp: the FCP packet
+ */
+static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
+{
+	struct fc_rport *rport;
+	struct fc_rport_libfc_priv *rpriv;
+
+	rport = fsp->rport;
+	rpriv = rport->dd_data;
+
+	return rpriv->e_d_tov + REC_TOV_CONST;
+}
+
+/**
  * fc_fcp_cmd_send() - Send a FCP command
  * @lport: The local port to send the command on
  * @fsp:   The FCP packet the command is on
@@ -1089,6 +1121,7 @@
 	struct fc_rport_libfc_priv *rpriv;
 	const size_t len = sizeof(fsp->cdb_cmd);
 	int rc = 0;
+	unsigned int rec_tov;
 
 	if (fc_fcp_lock_pkt(fsp))
 		return 0;
@@ -1119,10 +1152,13 @@
 	fsp->seq_ptr = seq;
 	fc_fcp_pkt_hold(fsp);	/* hold for fc_fcp_pkt_destroy */
 
+	rec_tov = get_fsp_rec_tov(fsp);
+
 	setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
-	fc_fcp_timer_set(fsp,
-			 (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) ?
-			 FC_SCSI_REC_TOV : FC_SCSI_ER_TIMEOUT);
+
+	if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
+		fc_fcp_timer_set(fsp, rec_tov);
+
 unlock:
 	fc_fcp_unlock_pkt(fsp);
 	return rc;
@@ -1197,13 +1233,16 @@
 {
 	struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data;
 	struct fc_lport *lport = fsp->lp;
+	unsigned int rec_tov;
+
 	if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) {
 		if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY)
 			return;
 		if (fc_fcp_lock_pkt(fsp))
 			return;
+		rec_tov = get_fsp_rec_tov(fsp);
 		setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp);
-		fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+		fc_fcp_timer_set(fsp, rec_tov);
 		fc_fcp_unlock_pkt(fsp);
 	}
 }
@@ -1282,27 +1321,27 @@
 		 *
 		 * scsi-eh will escalate for when either happens.
 		 */
-		return;
+		goto out;
 	}
 
 	if (fc_fcp_lock_pkt(fsp))
-		return;
+		goto out;
 
 	/*
 	 * raced with eh timeout handler.
 	 */
-	if (!fsp->seq_ptr || !fsp->wait_for_comp) {
-		spin_unlock_bh(&fsp->scsi_pkt_lock);
-		return;
-	}
+	if (!fsp->seq_ptr || !fsp->wait_for_comp)
+		goto out_unlock;
 
 	fh = fc_frame_header_get(fp);
 	if (fh->fh_type != FC_TYPE_BLS)
 		fc_fcp_resp(fsp, fp);
 	fsp->seq_ptr = NULL;
 	fsp->lp->tt.exch_done(seq);
-	fc_frame_free(fp);
+out_unlock:
 	fc_fcp_unlock_pkt(fsp);
+out:
+	fc_frame_free(fp);
 }
 
 /**
@@ -1341,13 +1380,10 @@
 
 	if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
 		fc_fcp_rec(fsp);
-	else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2),
-			       jiffies))
-		fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
 	else if (fsp->state & FC_SRB_RCV_STATUS)
 		fc_fcp_complete_locked(fsp);
 	else
-		fc_fcp_recovery(fsp);
+		fc_fcp_recovery(fsp, FC_TIMED_OUT);
 	fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
 unlock:
 	fc_fcp_unlock_pkt(fsp);
@@ -1373,6 +1409,7 @@
 		fc_fcp_complete_locked(fsp);
 		return;
 	}
+
 	fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec));
 	if (!fp)
 		goto retry;
@@ -1383,15 +1420,15 @@
 		       FC_FCTL_REQ, 0);
 	if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC,
 				 fc_fcp_rec_resp, fsp,
-				 jiffies_to_msecs(FC_SCSI_REC_TOV))) {
+				 2 * lport->r_a_tov)) {
 		fc_fcp_pkt_hold(fsp);		/* hold while REC outstanding */
 		return;
 	}
 retry:
 	if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
-		fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+		fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
 	else
-		fc_fcp_recovery(fsp);
+		fc_fcp_recovery(fsp, FC_TIMED_OUT);
 }
 
 /**
@@ -1445,7 +1482,6 @@
 			 * making progress.
 			 */
 			rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
-			fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
 			break;
 		case ELS_RJT_LOGIC:
 		case ELS_RJT_UNAB:
@@ -1460,7 +1496,7 @@
 				fc_fcp_retry_cmd(fsp);
 				break;
 			}
-			fc_fcp_recovery(fsp);
+			fc_fcp_recovery(fsp, FC_ERROR);
 			break;
 		}
 	} else if (opcode == ELS_LS_ACC) {
@@ -1498,12 +1534,12 @@
 			}
 			fc_fcp_srr(fsp, r_ctl, offset);
 		} else if (e_stat & ESB_ST_SEQ_INIT) {
-
+			unsigned int rec_tov = get_fsp_rec_tov(fsp);
 			/*
 			 * The remote port has the initiative, so just
 			 * keep waiting for it to complete.
 			 */
-			fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+			fc_fcp_timer_set(fsp, rec_tov);
 		} else {
 
 			/*
@@ -1575,7 +1611,7 @@
 		if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
 			fc_fcp_rec(fsp);
 		else
-			fc_fcp_recovery(fsp);
+			fc_fcp_recovery(fsp, FC_ERROR);
 		break;
 	}
 	fc_fcp_unlock_pkt(fsp);
@@ -1587,9 +1623,9 @@
  * fc_fcp_recovery() - Handler for fcp_pkt recovery
  * @fsp: The FCP pkt that needs to be aborted
  */
-static void fc_fcp_recovery(struct fc_fcp_pkt *fsp)
+static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
 {
-	fsp->status_code = FC_CMD_RECOVERY;
+	fsp->status_code = code;
 	fsp->cdb_status = 0;
 	fsp->io_status = 0;
 	/*
@@ -1616,6 +1652,7 @@
 	struct fcp_srr *srr;
 	struct fc_frame *fp;
 	u8 cdb_op;
+	unsigned int rec_tov;
 
 	rport = fsp->rport;
 	rpriv = rport->dd_data;
@@ -1640,8 +1677,9 @@
 		       rpriv->local_port->port_id, FC_TYPE_FCP,
 		       FC_FCTL_REQ, 0);
 
+	rec_tov = get_fsp_rec_tov(fsp);
 	seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL,
-				      fsp, jiffies_to_msecs(FC_SCSI_REC_TOV));
+				      fsp, jiffies_to_msecs(rec_tov));
 	if (!seq)
 		goto retry;
 
@@ -1665,6 +1703,7 @@
 {
 	struct fc_fcp_pkt *fsp = arg;
 	struct fc_frame_header *fh;
+	unsigned int rec_tov;
 
 	if (IS_ERR(fp)) {
 		fc_fcp_srr_error(fsp, fp);
@@ -1691,11 +1730,12 @@
 	switch (fc_frame_payload_op(fp)) {
 	case ELS_LS_ACC:
 		fsp->recov_retry = 0;
-		fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
+		rec_tov = get_fsp_rec_tov(fsp);
+		fc_fcp_timer_set(fsp, rec_tov);
 		break;
 	case ELS_LS_RJT:
 	default:
-		fc_fcp_recovery(fsp);
+		fc_fcp_recovery(fsp, FC_ERROR);
 		break;
 	}
 	fc_fcp_unlock_pkt(fsp);
@@ -1721,7 +1761,7 @@
 		if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
 			fc_fcp_rec(fsp);
 		else
-			fc_fcp_recovery(fsp);
+			fc_fcp_recovery(fsp, FC_TIMED_OUT);
 		break;
 	case -FC_EX_CLOSED:			/* e.g., link failure */
 		/* fall through */
@@ -1820,19 +1860,17 @@
 	if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
 		fsp->req_flags = FC_SRB_READ;
 		stats->InputRequests++;
-		stats->InputMegabytes = fsp->data_len;
+		stats->InputBytes += fsp->data_len;
 	} else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
 		fsp->req_flags = FC_SRB_WRITE;
 		stats->OutputRequests++;
-		stats->OutputMegabytes = fsp->data_len;
+		stats->OutputBytes += fsp->data_len;
 	} else {
 		fsp->req_flags = 0;
 		stats->ControlRequests++;
 	}
 	put_cpu();
 
-	fsp->tgt_flags = rpriv->flags;
-
 	init_timer(&fsp->timer);
 	fsp->timer.data = (unsigned long)fsp;
 
@@ -1946,18 +1984,29 @@
 		break;
 	case FC_CMD_ABORTED:
 		FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
-			   "due to FC_CMD_ABORTED\n");
+			  "due to FC_CMD_ABORTED\n");
 		sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
 		break;
-	case FC_CMD_RECOVERY:
-		sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
-		break;
 	case FC_CMD_RESET:
+		FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml "
+			   "due to FC_CMD_RESET\n");
 		sc_cmd->result = (DID_RESET << 16);
 		break;
 	case FC_HRD_ERROR:
+		FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml "
+			   "due to FC_HRD_ERROR\n");
 		sc_cmd->result = (DID_NO_CONNECT << 16);
 		break;
+	case FC_CRC_ERROR:
+		FC_FCP_DBG(fsp, "Returning DID_PARITY to scsi-ml "
+			   "due to FC_CRC_ERROR\n");
+		sc_cmd->result = (DID_PARITY << 16);
+		break;
+	case FC_TIMED_OUT:
+		FC_FCP_DBG(fsp, "Returning DID_BUS_BUSY to scsi-ml "
+			   "due to FC_TIMED_OUT\n");
+		sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status;
+		break;
 	default:
 		FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
 			   "due to unknown error\n");
@@ -2004,7 +2053,7 @@
 	fsp = CMD_SP(sc_cmd);
 	if (!fsp) {
 		/* command completed while scsi eh was setting up */
-		spin_unlock_irqrestore(lport->host->host_lock, flags);
+		spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 		return SUCCESS;
 	}
 	/* grab a ref so the fsp and sc_cmd cannot be relased from under us */
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
index 16d2162..eea0c35 100644
--- a/drivers/scsi/libfc/fc_libfc.h
+++ b/drivers/scsi/libfc/fc_libfc.h
@@ -66,9 +66,21 @@
 
 #define FC_FCP_DBG(pkt, fmt, args...)					\
 	FC_CHECK_LOGGING(FC_FCP_LOGGING,				\
-			 printk(KERN_INFO "host%u: fcp: %6.6x: " fmt,	\
+	{								\
+		if ((pkt)->seq_ptr) {					\
+			struct fc_exch *_ep = NULL;			\
+			_ep = fc_seq_exch((pkt)->seq_ptr);		\
+			printk(KERN_INFO "host%u: fcp: %6.6x: "		\
+				"xid %04x-%04x: " fmt,			\
 				(pkt)->lp->host->host_no,		\
-				pkt->rport->port_id, ##args))
+				(pkt)->rport->port_id,			\
+				(_ep)->oxid, (_ep)->rxid, ##args);	\
+		} else {						\
+			printk(KERN_INFO "host%u: fcp: %6.6x: " fmt,	\
+				(pkt)->lp->host->host_no,		\
+				(pkt)->rport->port_id, ##args);		\
+		}							\
+	})
 
 #define FC_EXCH_DBG(exch, fmt, args...)					\
 	FC_CHECK_LOGGING(FC_EXCH_LOGGING,				\
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 9be63ed..c5a10f9 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -288,6 +288,8 @@
 	struct fc_lport *lport = shost_priv(shost);
 	struct timespec v0, v1;
 	unsigned int cpu;
+	u64 fcp_in_bytes = 0;
+	u64 fcp_out_bytes = 0;
 
 	fcoe_stats = &lport->host_stats;
 	memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
@@ -310,10 +312,12 @@
 		fcoe_stats->fcp_input_requests += stats->InputRequests;
 		fcoe_stats->fcp_output_requests += stats->OutputRequests;
 		fcoe_stats->fcp_control_requests += stats->ControlRequests;
-		fcoe_stats->fcp_input_megabytes += stats->InputMegabytes;
-		fcoe_stats->fcp_output_megabytes += stats->OutputMegabytes;
+		fcp_in_bytes += stats->InputBytes;
+		fcp_out_bytes += stats->OutputBytes;
 		fcoe_stats->link_failure_count += stats->LinkFailureCount;
 	}
+	fcoe_stats->fcp_input_megabytes = div_u64(fcp_in_bytes, 1000000);
+	fcoe_stats->fcp_output_megabytes = div_u64(fcp_out_bytes, 1000000);
 	fcoe_stats->lip_count = -1;
 	fcoe_stats->nos_count = -1;
 	fcoe_stats->loss_of_sync_count = -1;
@@ -1703,8 +1707,10 @@
 	info->sg = job->reply_payload.sg_list;
 
 	if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp,
-				     NULL, info, tov))
+				     NULL, info, tov)) {
+		kfree(info);
 		return -ECOMM;
+	}
 	return 0;
 }
 
@@ -1762,8 +1768,10 @@
 	info->sg = job->reply_payload.sg_list;
 
 	if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp,
-				     NULL, info, tov))
+				     NULL, info, tov)) {
+		kfree(info);
 		return -ECOMM;
+	}
 	return 0;
 }
 
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a84ef13..a7175ad 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -652,7 +652,7 @@
 	FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp));
 
 	if (fp == ERR_PTR(-FC_EX_CLOSED))
-		return;
+		goto put;
 
 	mutex_lock(&rdata->rp_mutex);
 
@@ -689,6 +689,7 @@
 	fc_frame_free(fp);
 err:
 	mutex_unlock(&rdata->rp_mutex);
+put:
 	kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
 	return;
 bad:
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index c15fde8..da8b615 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -505,6 +505,7 @@
 	struct iscsi_conn *conn = task->conn;
 	struct iscsi_session *session = conn->session;
 	struct scsi_cmnd *sc = task->sc;
+	int oldstate = task->state;
 
 	ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n",
 			  task->itt, task->state, task->sc);
@@ -525,10 +526,10 @@
 		/* SCSI eh reuses commands to verify us */
 		sc->SCp.ptr = NULL;
 		/*
-		 * queue command may call this to free the task, but
-		 * not have setup the sc callback
+		 * queue command may call this to free the task, so
+		 * it will decide how to return sc to scsi-ml.
 		 */
-		if (sc->scsi_done)
+		if (oldstate != ISCSI_TASK_REQUEUE_SCSIQ)
 			sc->scsi_done(sc);
 	}
 }
@@ -539,11 +540,12 @@
 }
 EXPORT_SYMBOL_GPL(__iscsi_get_task);
 
-static void __iscsi_put_task(struct iscsi_task *task)
+void __iscsi_put_task(struct iscsi_task *task)
 {
 	if (atomic_dec_and_test(&task->refcount))
 		iscsi_free_task(task);
 }
+EXPORT_SYMBOL_GPL(__iscsi_put_task);
 
 void iscsi_put_task(struct iscsi_task *task)
 {
@@ -571,7 +573,8 @@
 			  task->itt, task->state, task->sc);
 	if (task->state == ISCSI_TASK_COMPLETED ||
 	    task->state == ISCSI_TASK_ABRT_TMF ||
-	    task->state == ISCSI_TASK_ABRT_SESS_RECOV)
+	    task->state == ISCSI_TASK_ABRT_SESS_RECOV ||
+	    task->state == ISCSI_TASK_REQUEUE_SCSIQ)
 		return;
 	WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
 	task->state = state;
@@ -1335,17 +1338,16 @@
 {
 	struct iscsi_conn *conn;
 	struct device *dev;
-	unsigned long flags;
 
-	spin_lock_irqsave(&session->lock, flags);
+	spin_lock_bh(&session->lock);
 	conn = session->leadconn;
 	if (session->state == ISCSI_STATE_TERMINATE || !conn) {
-		spin_unlock_irqrestore(&session->lock, flags);
+		spin_unlock_bh(&session->lock);
 		return;
 	}
 
 	dev = get_device(&conn->cls_conn->dev);
-	spin_unlock_irqrestore(&session->lock, flags);
+	spin_unlock_bh(&session->lock);
 	if (!dev)
 	        return;
 	/*
@@ -1364,17 +1366,16 @@
 void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
 {
 	struct iscsi_session *session = conn->session;
-	unsigned long flags;
 
-	spin_lock_irqsave(&session->lock, flags);
+	spin_lock_bh(&session->lock);
 	if (session->state == ISCSI_STATE_FAILED) {
-		spin_unlock_irqrestore(&session->lock, flags);
+		spin_unlock_bh(&session->lock);
 		return;
 	}
 
 	if (conn->stop_stage == 0)
 		session->state = ISCSI_STATE_FAILED;
-	spin_unlock_irqrestore(&session->lock, flags);
+	spin_unlock_bh(&session->lock);
 
 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
@@ -1599,27 +1600,23 @@
 	FAILURE_SESSION_NOT_READY,
 };
 
-static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
 {
 	struct iscsi_cls_session *cls_session;
-	struct Scsi_Host *host;
 	struct iscsi_host *ihost;
 	int reason = 0;
 	struct iscsi_session *session;
 	struct iscsi_conn *conn;
 	struct iscsi_task *task = NULL;
 
-	sc->scsi_done = done;
 	sc->result = 0;
 	sc->SCp.ptr = NULL;
 
-	host = sc->device->host;
 	ihost = shost_priv(host);
-	spin_unlock(host->host_lock);
 
 	cls_session = starget_to_session(scsi_target(sc->device));
 	session = cls_session->dd_data;
-	spin_lock(&session->lock);
+	spin_lock_bh(&session->lock);
 
 	reason = iscsi_session_chkready(cls_session);
 	if (reason) {
@@ -1705,25 +1702,21 @@
 	}
 
 	session->queued_cmdsn++;
-	spin_unlock(&session->lock);
-	spin_lock(host->host_lock);
+	spin_unlock_bh(&session->lock);
 	return 0;
 
 prepd_reject:
-	sc->scsi_done = NULL;
-	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+	iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
 reject:
-	spin_unlock(&session->lock);
+	spin_unlock_bh(&session->lock);
 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
 			  sc->cmnd[0], reason);
-	spin_lock(host->host_lock);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 prepd_fault:
-	sc->scsi_done = NULL;
-	iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
+	iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
 fault:
-	spin_unlock(&session->lock);
+	spin_unlock_bh(&session->lock);
 	ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
 			  sc->cmnd[0], reason);
 	if (!scsi_bidi_cmnd(sc))
@@ -1732,12 +1725,9 @@
 		scsi_out(sc)->resid = scsi_out(sc)->length;
 		scsi_in(sc)->resid = scsi_in(sc)->length;
 	}
-	done(sc);
-	spin_lock(host->host_lock);
+	sc->scsi_done(sc);
 	return 0;
 }
-
-DEF_SCSI_QCMD(iscsi_queuecommand)
 EXPORT_SYMBOL_GPL(iscsi_queuecommand);
 
 int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
@@ -1795,9 +1785,9 @@
 				      NULL, 0);
 	if (!task) {
 		spin_unlock_bh(&session->lock);
+		iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF.\n");
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 		spin_lock_bh(&session->lock);
-		ISCSI_DBG_EH(session, "tmf exec failure\n");
 		return -EPERM;
 	}
 	conn->tmfcmd_pdus_cnt++;
@@ -2202,7 +2192,7 @@
 		goto success_unlocked;
 	case TMF_TIMEDOUT:
 		spin_unlock_bh(&session->lock);
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
 		goto failed_unlocked;
 	case TMF_NOT_FOUND:
 		if (!sc->SCp.ptr) {
@@ -2289,7 +2279,7 @@
 		break;
 	case TMF_TIMEDOUT:
 		spin_unlock_bh(&session->lock);
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
 		goto done;
 	default:
 		conn->tmf_state = TMF_INITIAL;
@@ -2370,7 +2360,7 @@
 	 * we drop the lock here but the leadconn cannot be destoyed while
 	 * we are in the scsi eh
 	 */
-	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
 
 	ISCSI_DBG_EH(session, "wait for relogin\n");
 	wait_event_interruptible(conn->ehwait,
@@ -2452,7 +2442,7 @@
 		break;
 	case TMF_TIMEDOUT:
 		spin_unlock_bh(&session->lock);
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
 		goto done;
 	default:
 		conn->tmf_state = TMF_INITIAL;
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index fe8b74c..5257fdf 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -28,6 +28,17 @@
 #include <scsi/scsi_transport_sas.h>
 #include "../scsi_sas_internal.h"
 
+static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy *phy)
+{
+	struct sas_ha_struct *sas_ha = phy->ha;
+
+	if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
+		   SAS_ADDR_SIZE) != 0 || (sas_ha->strict_wide_ports &&
+	     memcmp(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE) != 0))
+		return false;
+	return true;
+}
+
 /**
  * sas_form_port -- add this phy to a port
  * @phy: the phy of interest
@@ -45,8 +56,7 @@
 	unsigned long flags;
 
 	if (port) {
-		if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
-			   SAS_ADDR_SIZE) != 0)
+		if (!phy_is_wideport_member(port, phy))
 			sas_deform_port(phy);
 		else {
 			SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
@@ -62,9 +72,7 @@
 		port = sas_ha->sas_port[i];
 		spin_lock(&port->phy_list_lock);
 		if (*(u64 *) port->sas_addr &&
-		    memcmp(port->attached_sas_addr,
-			   phy->attached_sas_addr, SAS_ADDR_SIZE) == 0 &&
-		    port->num_phys > 0) {
+		    phy_is_wideport_member(port, phy) && port->num_phys > 0) {
 			/* wide port */
 			SAS_DPRINTK("phy%d matched wide port%d\n", phy->id,
 				    port->id);
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 196de40..746dd3d 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -464,12 +464,29 @@
 #define UNSOL_VALID	0x00000001
 };
 
+#define LPFC_USER_LINK_SPEED_AUTO	0	/* auto select (default)*/
+#define LPFC_USER_LINK_SPEED_1G		1	/* 1 Gigabaud */
+#define LPFC_USER_LINK_SPEED_2G		2	/* 2 Gigabaud */
+#define LPFC_USER_LINK_SPEED_4G		4	/* 4 Gigabaud */
+#define LPFC_USER_LINK_SPEED_8G		8	/* 8 Gigabaud */
+#define LPFC_USER_LINK_SPEED_10G	10	/* 10 Gigabaud */
+#define LPFC_USER_LINK_SPEED_16G	16	/* 16 Gigabaud */
+#define LPFC_USER_LINK_SPEED_MAX	LPFC_USER_LINK_SPEED_16G
+#define LPFC_USER_LINK_SPEED_BITMAP ((1 << LPFC_USER_LINK_SPEED_16G) | \
+				     (1 << LPFC_USER_LINK_SPEED_10G) | \
+				     (1 << LPFC_USER_LINK_SPEED_8G) | \
+				     (1 << LPFC_USER_LINK_SPEED_4G) | \
+				     (1 << LPFC_USER_LINK_SPEED_2G) | \
+				     (1 << LPFC_USER_LINK_SPEED_1G) | \
+				     (1 << LPFC_USER_LINK_SPEED_AUTO))
+#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16"
+
 struct lpfc_hba {
 	/* SCSI interface function jump table entries */
 	int (*lpfc_new_scsi_buf)
 		(struct lpfc_vport *, int);
 	struct lpfc_scsi_buf * (*lpfc_get_scsi_buf)
-		(struct lpfc_hba *);
+		(struct lpfc_hba *, struct lpfc_nodelist *);
 	int (*lpfc_scsi_prep_dma_buf)
 		(struct lpfc_hba *, struct lpfc_scsi_buf *);
 	void (*lpfc_scsi_unprep_dma_buf)
@@ -545,7 +562,7 @@
 	uint32_t hba_flag;	/* hba generic flags */
 #define HBA_ERATT_HANDLED	0x1 /* This flag is set when eratt handled */
 #define DEFER_ERATT		0x2 /* Deferred error attention in progress */
-#define HBA_FCOE_SUPPORT	0x4 /* HBA function supports FCOE */
+#define HBA_FCOE_MODE		0x4 /* HBA function in FCoE Mode */
 #define HBA_SP_QUEUE_EVT	0x8 /* Slow-path qevt posted to worker thread*/
 #define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */
 #define FCP_XRI_ABORT_EVENT	0x20
@@ -557,6 +574,7 @@
 #define HBA_FIP_SUPPORT		0x800 /* FIP support in HBA */
 #define HBA_AER_ENABLED		0x1000 /* AER enabled with HBA */
 #define HBA_DEVLOSS_TMO         0x2000 /* HBA in devloss timeout */
+#define HBA_RRQ_ACTIVE		0x4000 /* process the rrq active list */
 	uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
 	struct lpfc_dmabuf slim2p;
 
@@ -606,6 +624,7 @@
 	/* HBA Config Parameters */
 	uint32_t cfg_ack0;
 	uint32_t cfg_enable_npiv;
+	uint32_t cfg_enable_rrq;
 	uint32_t cfg_topology;
 	uint32_t cfg_link_speed;
 	uint32_t cfg_cr_delay;
@@ -716,6 +735,7 @@
 	uint32_t total_scsi_bufs;
 	struct list_head lpfc_iocb_list;
 	uint32_t total_iocbq_bufs;
+	struct list_head active_rrq_list;
 	spinlock_t hbalock;
 
 	/* pci_mem_pools */
@@ -728,6 +748,7 @@
 
 	mempool_t *mbox_mem_pool;
 	mempool_t *nlp_mem_pool;
+	mempool_t *rrq_pool;
 
 	struct fc_host_statistics link_stats;
 	enum intr_type_t intr_type;
@@ -784,6 +805,7 @@
 	unsigned long skipped_hb;
 	struct timer_list hb_tmofunc;
 	uint8_t hb_outstanding;
+	struct timer_list rrq_tmr;
 	enum hba_temp_state over_temp_state;
 	/* ndlp reference management */
 	spinlock_t ndlp_lock;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index c1cbec0..c06491b 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -52,10 +52,6 @@
 #define LPFC_MIN_DEVLOSS_TMO 1
 #define LPFC_MAX_DEVLOSS_TMO 255
 
-#define LPFC_MAX_LINK_SPEED 8
-#define LPFC_LINK_SPEED_BITMAP 0x00000117
-#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8"
-
 /**
  * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
  * @incr: integer to convert.
@@ -463,7 +459,7 @@
 		if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
 			len += snprintf(buf + len, PAGE_SIZE-len,
 					"   Menlo Maint Mode\n");
-		else if (phba->fc_topology == TOPOLOGY_LOOP) {
+		else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 			if (vport->fc_flag & FC_PUBLIC_LOOP)
 				len += snprintf(buf + len, PAGE_SIZE-len,
 						"   Public Loop\n");
@@ -1981,6 +1977,13 @@
 lpfc_param_init(enable_npiv, 1, 0, 1);
 static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
 
+int lpfc_enable_rrq;
+module_param(lpfc_enable_rrq, int, 0);
+MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
+lpfc_param_show(enable_rrq);
+lpfc_param_init(enable_rrq, 0, 0, 1);
+static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL);
+
 /*
 # lpfc_suppress_link_up:  Bring link up at initialization
 #            0x0  = bring link up (issue MBX_INIT_LINK)
@@ -2837,14 +2840,8 @@
 /*
 # lpfc_link_speed: Link speed selection for initializing the Fibre Channel
 # connection.
-#       0  = auto select (default)
-#       1  = 1 Gigabaud
-#       2  = 2 Gigabaud
-#       4  = 4 Gigabaud
-#       8  = 8 Gigabaud
-# Value range is [0,8]. Default value is 0.
+# Value range is [0,16]. Default value is 0.
 */
-
 /**
  * lpfc_link_speed_set - Set the adapters link speed
  * @phba: lpfc_hba pointer.
@@ -2869,7 +2866,7 @@
 	struct Scsi_Host  *shost = class_to_shost(dev);
 	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
 	struct lpfc_hba   *phba = vport->phba;
-	int val = 0;
+	int val = LPFC_USER_LINK_SPEED_AUTO;
 	int nolip = 0;
 	const char *val_buf = buf;
 	int err;
@@ -2885,15 +2882,20 @@
 	if (sscanf(val_buf, "%i", &val) != 1)
 		return -EINVAL;
 
-	if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
-		((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
-		((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
-		((val == LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
-		((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)))
+	if (((val == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
+	    ((val == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
+	    ((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
+	    ((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
+	    ((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) ||
+	    ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb))) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+				"2879 lpfc_link_speed attribute cannot be set "
+				"to %d. Speed is not supported by this port.\n",
+				val);
 		return -EINVAL;
-
-	if ((val >= 0 && val <= 8)
-		&& (LPFC_LINK_SPEED_BITMAP & (1 << val))) {
+	}
+	if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
+	    (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
 		prev_val = phba->cfg_link_speed;
 		phba->cfg_link_speed = val;
 		if (nolip)
@@ -2906,11 +2908,9 @@
 		} else
 			return strlen(buf);
 	}
-
 	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-		"%d:0469 lpfc_link_speed attribute cannot be set to %d, "
-		"allowed range is [0, 8]\n",
-		phba->brd_no, val);
+		"0469 lpfc_link_speed attribute cannot be set to %d, "
+		"allowed values are ["LPFC_LINK_SPEED_STRING"]\n", val);
 	return -EINVAL;
 }
 
@@ -2938,8 +2938,8 @@
 static int
 lpfc_link_speed_init(struct lpfc_hba *phba, int val)
 {
-	if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED)
-		&& (LPFC_LINK_SPEED_BITMAP & (1 << val))) {
+	if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
+	    (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
 		phba->cfg_link_speed = val;
 		return 0;
 	}
@@ -2947,12 +2947,12 @@
 			"0405 lpfc_link_speed attribute cannot "
 			"be set to %d, allowed values are "
 			"["LPFC_LINK_SPEED_STRING"]\n", val);
-	phba->cfg_link_speed = 0;
+	phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
 	return -EINVAL;
 }
 
 static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
-		lpfc_link_speed_show, lpfc_link_speed_store);
+		   lpfc_link_speed_show, lpfc_link_speed_store);
 
 /*
 # lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER)
@@ -3305,12 +3305,12 @@
 LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "Enable HBA resets from the driver.");
 
 /*
-# lpfc_enable_hba_heartbeat: Enable HBA heartbeat timer..
+# lpfc_enable_hba_heartbeat: Disable HBA heartbeat timer..
 #       0  = HBA Heartbeat disabled
 #       1  = HBA Heartbeat enabled (default)
 # Value range is [0,1]. Default value is 1.
 */
-LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat.");
+LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat.");
 
 /*
 # lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF)
@@ -3401,6 +3401,7 @@
 	&dev_attr_lpfc_fdmi_on,
 	&dev_attr_lpfc_max_luns,
 	&dev_attr_lpfc_enable_npiv,
+	&dev_attr_lpfc_enable_rrq,
 	&dev_attr_nport_evt_cnt,
 	&dev_attr_board_mode,
 	&dev_attr_max_vpi,
@@ -3798,8 +3799,7 @@
 			}
 			break;
 		case MBX_READ_SPARM64:
-		case MBX_READ_LA:
-		case MBX_READ_LA64:
+		case MBX_READ_TOPOLOGY:
 		case MBX_REG_LOGIN:
 		case MBX_REG_LOGIN64:
 		case MBX_CONFIG_PORT:
@@ -3989,7 +3989,7 @@
 	if (vport->port_type == LPFC_NPIV_PORT) {
 		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
 	} else if (lpfc_is_link_up(phba)) {
-		if (phba->fc_topology == TOPOLOGY_LOOP) {
+		if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 			if (vport->fc_flag & FC_PUBLIC_LOOP)
 				fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
 			else
@@ -4058,23 +4058,26 @@
 
 	if (lpfc_is_link_up(phba)) {
 		switch(phba->fc_linkspeed) {
-			case LA_1GHZ_LINK:
-				fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+		case LPFC_LINK_SPEED_1GHZ:
+			fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
 			break;
-			case LA_2GHZ_LINK:
-				fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
+		case LPFC_LINK_SPEED_2GHZ:
+			fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
 			break;
-			case LA_4GHZ_LINK:
-				fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
+		case LPFC_LINK_SPEED_4GHZ:
+			fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
 			break;
-			case LA_8GHZ_LINK:
-				fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
+		case LPFC_LINK_SPEED_8GHZ:
+			fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
 			break;
-			case LA_10GHZ_LINK:
-				fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+		case LPFC_LINK_SPEED_10GHZ:
+			fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
 			break;
-			default:
-				fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+		case LPFC_LINK_SPEED_16GHZ:
+			fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
+			break;
+		default:
+			fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 			break;
 		}
 	} else
@@ -4097,7 +4100,7 @@
 	spin_lock_irq(shost->host_lock);
 
 	if ((vport->fc_flag & FC_FABRIC) ||
-	    ((phba->fc_topology == TOPOLOGY_LOOP) &&
+	    ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
 	     (vport->fc_flag & FC_PUBLIC_LOOP)))
 		node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
 	else
@@ -4208,11 +4211,11 @@
 	hs->invalid_crc_count -= lso->invalid_crc_count;
 	hs->error_frames -= lso->error_frames;
 
-	if (phba->hba_flag & HBA_FCOE_SUPPORT) {
+	if (phba->hba_flag & HBA_FCOE_MODE) {
 		hs->lip_count = -1;
 		hs->nos_count = (phba->link_events >> 1);
 		hs->nos_count -= lso->link_events;
-	} else if (phba->fc_topology == TOPOLOGY_LOOP) {
+	} else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 		hs->lip_count = (phba->fc_eventTag >> 1);
 		hs->lip_count -= lso->link_events;
 		hs->nos_count = -1;
@@ -4303,7 +4306,7 @@
 	lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;
 	lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
 	lso->error_frames = pmb->un.varRdLnk.crcCnt;
-	if (phba->hba_flag & HBA_FCOE_SUPPORT)
+	if (phba->hba_flag & HBA_FCOE_MODE)
 		lso->link_events = (phba->link_events >> 1);
 	else
 		lso->link_events = (phba->fc_eventTag >> 1);
@@ -4615,6 +4618,7 @@
 	lpfc_link_speed_init(phba, lpfc_link_speed);
 	lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
 	lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
+	lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
 	lpfc_use_msi_init(phba, lpfc_use_msi);
 	lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
 	lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 7260c3a..0dd43bb 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -162,7 +162,6 @@
 			struct lpfc_iocbq *cmdiocbq,
 			struct lpfc_iocbq *rspiocbq)
 {
-	unsigned long iflags;
 	struct bsg_job_data *dd_data;
 	struct fc_bsg_job *job;
 	IOCB_t *rsp;
@@ -173,9 +172,10 @@
 	int rc = 0;
 
 	spin_lock_irqsave(&phba->ct_ev_lock, flags);
-	dd_data = cmdiocbq->context1;
+	dd_data = cmdiocbq->context2;
 	if (!dd_data) {
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
+		lpfc_sli_release_iocbq(phba, cmdiocbq);
 		return;
 	}
 
@@ -183,17 +183,9 @@
 	job = iocb->set_job;
 	job->dd_data = NULL; /* so timeout handler does not reply */
 
-	spin_lock_irqsave(&phba->hbalock, iflags);
-	cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
-	if (cmdiocbq->context2 && rspiocbq)
-		memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
-		       &rspiocbq->iocb, sizeof(IOCB_t));
-	spin_unlock_irqrestore(&phba->hbalock, iflags);
-
 	bmp = iocb->bmp;
-	rspiocbq = iocb->rspiocbq;
 	rsp = &rspiocbq->iocb;
-	ndlp = iocb->ndlp;
+	ndlp = cmdiocbq->context1;
 
 	pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
 		     job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -220,7 +212,6 @@
 			rsp->un.genreq64.bdl.bdeSize;
 
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	lpfc_sli_release_iocbq(phba, rspiocbq);
 	lpfc_sli_release_iocbq(phba, cmdiocbq);
 	lpfc_nlp_put(ndlp);
 	kfree(bmp);
@@ -247,9 +238,7 @@
 	struct ulp_bde64 *bpl = NULL;
 	uint32_t timeout;
 	struct lpfc_iocbq *cmdiocbq = NULL;
-	struct lpfc_iocbq *rspiocbq = NULL;
 	IOCB_t *cmd;
-	IOCB_t *rsp;
 	struct lpfc_dmabuf *bmp = NULL;
 	int request_nseg;
 	int reply_nseg;
@@ -296,17 +285,10 @@
 	}
 
 	cmd = &cmdiocbq->iocb;
-	rspiocbq = lpfc_sli_get_iocbq(phba);
-	if (!rspiocbq) {
-		rc = -ENOMEM;
-		goto free_cmdiocbq;
-	}
-
-	rsp = &rspiocbq->iocb;
 	bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
 	if (!bmp->virt) {
 		rc = -ENOMEM;
-		goto free_rspiocbq;
+		goto free_cmdiocbq;
 	}
 
 	INIT_LIST_HEAD(&bmp->list);
@@ -358,14 +340,12 @@
 	cmd->ulpTimeout = timeout;
 
 	cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
-	cmdiocbq->context1 = dd_data;
-	cmdiocbq->context2 = rspiocbq;
+	cmdiocbq->context1 = ndlp;
+	cmdiocbq->context2 = dd_data;
 	dd_data->type = TYPE_IOCB;
 	dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
-	dd_data->context_un.iocb.rspiocbq = rspiocbq;
 	dd_data->context_un.iocb.set_job = job;
 	dd_data->context_un.iocb.bmp = bmp;
-	dd_data->context_un.iocb.ndlp = ndlp;
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
 		creg_val = readl(phba->HCregaddr);
@@ -391,8 +371,6 @@
 
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
 
-free_rspiocbq:
-	lpfc_sli_release_iocbq(phba, rspiocbq);
 free_cmdiocbq:
 	lpfc_sli_release_iocbq(phba, cmdiocbq);
 free_bmp:
@@ -1220,7 +1198,7 @@
 	int rc = 0;
 
 	spin_lock_irqsave(&phba->ct_ev_lock, flags);
-	dd_data = cmdiocbq->context1;
+	dd_data = cmdiocbq->context2;
 	/* normal completion and timeout crossed paths, already done */
 	if (!dd_data) {
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
@@ -1369,8 +1347,8 @@
 	ctiocb->context3 = bmp;
 
 	ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp;
-	ctiocb->context1 = dd_data;
-	ctiocb->context2 = NULL;
+	ctiocb->context2 = dd_data;
+	ctiocb->context1 = ndlp;
 	dd_data->type = TYPE_IOCB;
 	dd_data->context_un.iocb.cmdiocbq = ctiocb;
 	dd_data->context_un.iocb.rspiocbq = NULL;
@@ -1641,7 +1619,7 @@
  * This function obtains a remote port login id so the diag loopback test
  * can send and receive its own unsolicited CT command.
  **/
-static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi)
+static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi)
 {
 	LPFC_MBOXQ_t *mbox;
 	struct lpfc_dmabuf *dmabuff;
@@ -1651,10 +1629,14 @@
 	if (!mbox)
 		return -ENOMEM;
 
+	if (phba->sli_rev == LPFC_SLI_REV4)
+		*rpi = lpfc_sli4_alloc_rpi(phba);
 	status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
-				(uint8_t *)&phba->pport->fc_sparam, mbox, 0);
+			      (uint8_t *)&phba->pport->fc_sparam, mbox, *rpi);
 	if (status) {
 		mempool_free(mbox, phba->mbox_mem_pool);
+		if (phba->sli_rev == LPFC_SLI_REV4)
+			lpfc_sli4_free_rpi(phba, *rpi);
 		return -ENOMEM;
 	}
 
@@ -1668,6 +1650,8 @@
 		kfree(dmabuff);
 		if (status != MBX_TIMEOUT)
 			mempool_free(mbox, phba->mbox_mem_pool);
+		if (phba->sli_rev == LPFC_SLI_REV4)
+			lpfc_sli4_free_rpi(phba, *rpi);
 		return -ENODEV;
 	}
 
@@ -1704,8 +1688,9 @@
 			mempool_free(mbox, phba->mbox_mem_pool);
 		return -EIO;
 	}
-
 	mempool_free(mbox, phba->mbox_mem_pool);
+	if (phba->sli_rev == LPFC_SLI_REV4)
+		lpfc_sli4_free_rpi(phba, rpi);
 	return 0;
 }
 
@@ -2102,7 +2087,7 @@
 	uint32_t size;
 	uint32_t full_size;
 	size_t segment_len = 0, segment_offset = 0, current_offset = 0;
-	uint16_t rpi;
+	uint16_t rpi = 0;
 	struct lpfc_iocbq *cmdiocbq, *rspiocbq;
 	IOCB_t *cmd, *rsp;
 	struct lpfc_sli_ct_request *ctreq;
@@ -2162,7 +2147,7 @@
 		goto loopback_test_exit;
 	}
 
-	if (size >= BUF_SZ_4K) {
+	if (full_size >= BUF_SZ_4K) {
 		/*
 		 * Allocate memory for ioctl data. If buffer is bigger than 64k,
 		 * then we allocate 64k and re-use that buffer over and over to
@@ -2171,7 +2156,7 @@
 		 * problem with GET_FCPTARGETMAPPING...
 		 */
 		if (size <= (64 * 1024))
-			total_mem = size;
+			total_mem = full_size;
 		else
 			total_mem = 64 * 1024;
 	} else
@@ -2189,7 +2174,6 @@
 	sg_copy_to_buffer(job->request_payload.sg_list,
 				job->request_payload.sg_cnt,
 				ptr, size);
-
 	rc = lpfcdiag_loop_self_reg(phba, &rpi);
 	if (rc)
 		goto loopback_test_exit;
@@ -2601,12 +2585,11 @@
 			phba->wait_4_mlo_maint_flg = 1;
 		} else if (mb->un.varWords[0] == SETVAR_MLORST) {
 			phba->link_flag &= ~LS_LOOPBACK_MODE;
-			phba->fc_topology = TOPOLOGY_PT_PT;
+			phba->fc_topology = LPFC_TOPOLOGY_PT_PT;
 		}
 		break;
 	case MBX_READ_SPARM64:
-	case MBX_READ_LA:
-	case MBX_READ_LA64:
+	case MBX_READ_TOPOLOGY:
 	case MBX_REG_LOGIN:
 	case MBX_REG_LOGIN64:
 	case MBX_CONFIG_PORT:
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index a5f5a09..17fde52 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -31,7 +31,7 @@
 void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
 
 void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
-int lpfc_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
+int lpfc_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
 void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_issue_clear_la(struct lpfc_hba *, struct lpfc_vport *);
 void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -40,7 +40,7 @@
 void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
-		 LPFC_MBOXQ_t *, uint32_t);
+		 LPFC_MBOXQ_t *, uint16_t);
 void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
 void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
 void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
@@ -64,7 +64,7 @@
 int lpfc_linkdown(struct lpfc_hba *);
 void lpfc_linkdown_port(struct lpfc_vport *);
 void lpfc_port_link_failure(struct lpfc_vport *);
-void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
+void lpfc_mbx_cmpl_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *);
 void lpfc_retry_pport_discovery(struct lpfc_hba *);
@@ -121,6 +121,7 @@
 int lpfc_els_chk_latt(struct lpfc_vport *);
 int lpfc_els_abort_flogi(struct lpfc_hba *);
 int lpfc_initial_flogi(struct lpfc_vport *);
+void lpfc_issue_init_vfi(struct lpfc_vport *);
 int lpfc_initial_fdisc(struct lpfc_vport *);
 int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t);
 int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
@@ -415,5 +416,13 @@
 int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
 	struct lpfc_iocbq *, uint32_t);
 uint32_t lpfc_drain_txq(struct lpfc_hba *);
-
-
+void lpfc_clr_rrq_active(struct lpfc_hba *, uint16_t, struct lpfc_node_rrq *);
+int lpfc_test_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, uint16_t);
+void lpfc_handle_rrq_active(struct lpfc_hba *);
+int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *);
+int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
+	uint16_t, uint16_t, uint16_t);
+void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
+void lpfc_cleanup_vports_rrqs(struct lpfc_vport *);
+struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
+	uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 463b749..c004fa9 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -48,14 +48,14 @@
 #include "lpfc_vport.h"
 #include "lpfc_debugfs.h"
 
-#define HBA_PORTSPEED_UNKNOWN               0	/* Unknown - transceiver
-						 * incapable of reporting */
-#define HBA_PORTSPEED_1GBIT                 1	/* 1 GBit/sec */
-#define HBA_PORTSPEED_2GBIT                 2	/* 2 GBit/sec */
-#define HBA_PORTSPEED_4GBIT                 8   /* 4 GBit/sec */
-#define HBA_PORTSPEED_8GBIT                16   /* 8 GBit/sec */
-#define HBA_PORTSPEED_10GBIT                4	/* 10 GBit/sec */
-#define HBA_PORTSPEED_NOT_NEGOTIATED        5	/* Speed not established */
+/* FDMI Port Speed definitions */
+#define HBA_PORTSPEED_1GBIT		0x0001	/* 1 GBit/sec */
+#define HBA_PORTSPEED_2GBIT		0x0002	/* 2 GBit/sec */
+#define HBA_PORTSPEED_4GBIT		0x0008	/* 4 GBit/sec */
+#define HBA_PORTSPEED_10GBIT		0x0004	/* 10 GBit/sec */
+#define HBA_PORTSPEED_8GBIT		0x0010	/* 8 GBit/sec */
+#define HBA_PORTSPEED_16GBIT		0x0020	/* 16 GBit/sec */
+#define HBA_PORTSPEED_UNKNOWN		0x0800	/* Unknown */
 
 #define FOURBYTES	4
 
@@ -1593,8 +1593,10 @@
 			ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
 
 			ae->un.SupportSpeed = 0;
+			if (phba->lmt & LMT_16Gb)
+				ae->un.SupportSpeed |= HBA_PORTSPEED_16GBIT;
 			if (phba->lmt & LMT_10Gb)
-				ae->un.SupportSpeed = HBA_PORTSPEED_10GBIT;
+				ae->un.SupportSpeed |= HBA_PORTSPEED_10GBIT;
 			if (phba->lmt & LMT_8Gb)
 				ae->un.SupportSpeed |= HBA_PORTSPEED_8GBIT;
 			if (phba->lmt & LMT_4Gb)
@@ -1612,24 +1614,26 @@
 			ae->ad.bits.AttrType = be16_to_cpu(PORT_SPEED);
 			ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4);
 			switch(phba->fc_linkspeed) {
-				case LA_1GHZ_LINK:
-					ae->un.PortSpeed = HBA_PORTSPEED_1GBIT;
+			case LPFC_LINK_SPEED_1GHZ:
+				ae->un.PortSpeed = HBA_PORTSPEED_1GBIT;
 				break;
-				case LA_2GHZ_LINK:
-					ae->un.PortSpeed = HBA_PORTSPEED_2GBIT;
+			case LPFC_LINK_SPEED_2GHZ:
+				ae->un.PortSpeed = HBA_PORTSPEED_2GBIT;
 				break;
-				case LA_4GHZ_LINK:
-					ae->un.PortSpeed = HBA_PORTSPEED_4GBIT;
+			case LPFC_LINK_SPEED_4GHZ:
+				ae->un.PortSpeed = HBA_PORTSPEED_4GBIT;
 				break;
-				case LA_8GHZ_LINK:
-					ae->un.PortSpeed = HBA_PORTSPEED_8GBIT;
+			case LPFC_LINK_SPEED_8GHZ:
+				ae->un.PortSpeed = HBA_PORTSPEED_8GBIT;
 				break;
-				case LA_10GHZ_LINK:
-					ae->un.PortSpeed = HBA_PORTSPEED_10GBIT;
+			case LPFC_LINK_SPEED_10GHZ:
+				ae->un.PortSpeed = HBA_PORTSPEED_10GBIT;
 				break;
-				default:
-					ae->un.PortSpeed =
-						HBA_PORTSPEED_UNKNOWN;
+			case LPFC_LINK_SPEED_16GHZ:
+				ae->un.PortSpeed = HBA_PORTSPEED_16GBIT;
+				break;
+			default:
+				ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN;
 				break;
 			}
 			pab->ab.EntryCnt++;
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 7cae69d..1d84b63 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -68,6 +68,12 @@
 	} un;
 };
 
+#define LPFC_SLI4_MAX_XRI	1024	/* Used to make the ndlp's xri_bitmap */
+#define XRI_BITMAP_ULONGS (LPFC_SLI4_MAX_XRI / BITS_PER_LONG)
+struct lpfc_node_rrqs {
+	unsigned long xri_bitmap[XRI_BITMAP_ULONGS];
+};
+
 struct lpfc_nodelist {
 	struct list_head nlp_listp;
 	struct lpfc_name nlp_portname;
@@ -110,8 +116,19 @@
 	atomic_t cmd_pending;
 	uint32_t cmd_qdepth;
 	unsigned long last_change_time;
+	struct lpfc_node_rrqs active_rrqs;
 	struct lpfc_scsicmd_bkt *lat_data;	/* Latency data */
 };
+struct lpfc_node_rrq {
+	struct list_head list;
+	uint16_t xritag;
+	uint16_t send_rrq;
+	uint16_t rxid;
+	uint32_t         nlp_DID;		/* FC D_ID of entry */
+	struct lpfc_vport *vport;
+	struct lpfc_nodelist *ndlp;
+	unsigned long rrq_stop_time;
+};
 
 /* Defines for nlp_flag (uint32) */
 #define NLP_IGNR_REG_CMPL  0x00000001 /* Rcvd rscn before we cmpl reg login */
@@ -136,7 +153,7 @@
 #define NLP_NODEV_REMOVE   0x08000000	/* Defer removal till discovery ends */
 #define NLP_TARGET_REMOVE  0x10000000   /* Target remove in process */
 #define NLP_SC_REQ         0x20000000	/* Target requires authentication */
-#define NLP_RPI_VALID      0x80000000	/* nlp_rpi is valid */
+#define NLP_RPI_REGISTERED 0x80000000	/* nlp_rpi is valid */
 
 /* ndlp usage management macros */
 #define NLP_CHK_NODE_ACT(ndlp)		(((ndlp)->nlp_usg_map \
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 884f4d3..c62d567 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -375,7 +375,8 @@
 		err = 4;
 		goto fail;
 	}
-	rc = lpfc_reg_rpi(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox, 0);
+	rc = lpfc_reg_rpi(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
+			  ndlp->nlp_rpi);
 	if (rc) {
 		err = 5;
 		goto fail_free_mbox;
@@ -523,7 +524,7 @@
 	phba->fc_edtovResol = sp->cmn.edtovResolution;
 	phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
 
-	if (phba->fc_topology == TOPOLOGY_LOOP) {
+	if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 		spin_lock_irq(shost->host_lock);
 		vport->fc_flag |= FC_PUBLIC_LOOP;
 		spin_unlock_irq(shost->host_lock);
@@ -832,6 +833,12 @@
 		if (lpfc_els_retry(phba, cmdiocb, rspiocb))
 			goto out;
 
+		/* FLOGI failure */
+		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+				 "0100 FLOGI failure Status:x%x/x%x TMO:x%x\n",
+				 irsp->ulpStatus, irsp->un.ulpWord[4],
+				 irsp->ulpTimeout);
+
 		/* FLOGI failed, so there is no fabric */
 		spin_lock_irq(shost->host_lock);
 		vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
@@ -843,13 +850,16 @@
 		 */
 		if (phba->alpa_map[0] == 0) {
 			vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
+			if ((phba->sli_rev == LPFC_SLI_REV4) &&
+			    (!(vport->fc_flag & FC_VFI_REGISTERED) ||
+			     (vport->fc_prevDID != vport->fc_myDID))) {
+				if (vport->fc_flag & FC_VFI_REGISTERED)
+					lpfc_sli4_unreg_all_rpis(vport);
+				lpfc_issue_reg_vfi(vport);
+				lpfc_nlp_put(ndlp);
+				goto out;
+			}
 		}
-
-		/* FLOGI failure */
-		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-				 "0100 FLOGI failure Status:x%x/x%x TMO:x%x\n",
-				 irsp->ulpStatus, irsp->un.ulpWord[4],
-				 irsp->ulpTimeout);
 		goto flogifail;
 	}
 	spin_lock_irq(shost->host_lock);
@@ -879,7 +889,7 @@
 		 */
 		if (sp->cmn.fPort)
 			rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp);
-		else if (!(phba->hba_flag & HBA_FCOE_SUPPORT))
+		else if (!(phba->hba_flag & HBA_FCOE_MODE))
 			rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
 		else {
 			lpfc_printf_vlog(vport, KERN_ERR,
@@ -1014,7 +1024,9 @@
 	if (sp->cmn.fcphHigh < FC_PH3)
 		sp->cmn.fcphHigh = FC_PH3;
 
-	if  (phba->sli_rev == LPFC_SLI_REV4) {
+	if  ((phba->sli_rev == LPFC_SLI_REV4) &&
+	     (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+	      LPFC_SLI_INTF_IF_TYPE_0)) {
 		elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1);
 		elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1);
 		/* FLOGI needs to be 3 for WQE FCFI */
@@ -1027,7 +1039,7 @@
 		icmd->ulpCt_l = 0;
 	}
 
-	if (phba->fc_topology != TOPOLOGY_LOOP) {
+	if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
 		icmd->un.elsreq64.myID = 0;
 		icmd->un.elsreq64.fl = 1;
 	}
@@ -1281,6 +1293,7 @@
 	uint32_t rc, keepDID = 0;
 	int  put_node;
 	int  put_rport;
+	struct lpfc_node_rrqs rrq;
 
 	/* Fabric nodes can have the same WWPN so we don't bother searching
 	 * by WWPN.  Just return the ndlp that was given to us.
@@ -1298,6 +1311,7 @@
 
 	if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp))
 		return ndlp;
+	memset(&rrq.xri_bitmap, 0, sizeof(new_ndlp->active_rrqs.xri_bitmap));
 
 	if (!new_ndlp) {
 		rc = memcmp(&ndlp->nlp_portname, name,
@@ -1318,12 +1332,25 @@
 		if (!new_ndlp)
 			return ndlp;
 		keepDID = new_ndlp->nlp_DID;
-	} else
+		if (phba->sli_rev == LPFC_SLI_REV4)
+			memcpy(&rrq.xri_bitmap,
+				&new_ndlp->active_rrqs.xri_bitmap,
+				sizeof(new_ndlp->active_rrqs.xri_bitmap));
+	} else {
 		keepDID = new_ndlp->nlp_DID;
+		if (phba->sli_rev == LPFC_SLI_REV4)
+			memcpy(&rrq.xri_bitmap,
+				&new_ndlp->active_rrqs.xri_bitmap,
+				sizeof(new_ndlp->active_rrqs.xri_bitmap));
+	}
 
 	lpfc_unreg_rpi(vport, new_ndlp);
 	new_ndlp->nlp_DID = ndlp->nlp_DID;
 	new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
+	if (phba->sli_rev == LPFC_SLI_REV4)
+		memcpy(new_ndlp->active_rrqs.xri_bitmap,
+			&ndlp->active_rrqs.xri_bitmap,
+			sizeof(ndlp->active_rrqs.xri_bitmap));
 
 	if (ndlp->nlp_flag & NLP_NPR_2B_DISC)
 		new_ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@@ -1362,12 +1389,20 @@
 
 		/* Two ndlps cannot have the same did on the nodelist */
 		ndlp->nlp_DID = keepDID;
+		if (phba->sli_rev == LPFC_SLI_REV4)
+			memcpy(&ndlp->active_rrqs.xri_bitmap,
+				&rrq.xri_bitmap,
+				sizeof(ndlp->active_rrqs.xri_bitmap));
 		lpfc_drop_node(vport, ndlp);
 	}
 	else {
 		lpfc_unreg_rpi(vport, ndlp);
 		/* Two ndlps cannot have the same did */
 		ndlp->nlp_DID = keepDID;
+		if (phba->sli_rev == LPFC_SLI_REV4)
+			memcpy(&ndlp->active_rrqs.xri_bitmap,
+				&rrq.xri_bitmap,
+				sizeof(ndlp->active_rrqs.xri_bitmap));
 		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 		/* Since we are swapping the ndlp passed in with the new one
 		 * and the did has already been swapped, copy over the
@@ -1428,6 +1463,73 @@
 }
 
 /**
+ * lpfc_cmpl_els_rrq - Completion handled for els RRQs.
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine will call the clear rrq function to free the rrq and
+ * clear the xri's bit in the ndlp's xri_bitmap. If the ndlp does not
+ * exist then the clear_rrq is still called because the rrq needs to
+ * be freed.
+ **/
+
+static void
+lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		    struct lpfc_iocbq *rspiocb)
+{
+	struct lpfc_vport *vport = cmdiocb->vport;
+	IOCB_t *irsp;
+	struct lpfc_nodelist *ndlp;
+	struct lpfc_node_rrq *rrq;
+
+	/* we pass cmdiocb to state machine which needs rspiocb as well */
+	rrq = cmdiocb->context_un.rrq;
+	cmdiocb->context_un.rsp_iocb = rspiocb;
+
+	irsp = &rspiocb->iocb;
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"RRQ cmpl:      status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4],
+		irsp->un.elsreq64.remoteID);
+
+	ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
+	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) {
+		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+				 "2882 RRQ completes to NPort x%x "
+				 "with no ndlp. Data: x%x x%x x%x\n",
+				 irsp->un.elsreq64.remoteID,
+				 irsp->ulpStatus, irsp->un.ulpWord[4],
+				 irsp->ulpIoTag);
+		goto out;
+	}
+
+	/* rrq completes to NPort <nlp_DID> */
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+			 "2880 RRQ completes to NPort x%x "
+			 "Data: x%x x%x x%x x%x x%x\n",
+			 ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
+			 irsp->ulpTimeout, rrq->xritag, rrq->rxid);
+
+	if (irsp->ulpStatus) {
+		/* Check for retry */
+		/* RRQ failed Don't print the vport to vport rjts */
+		if (irsp->ulpStatus != IOSTAT_LS_RJT ||
+			(((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) &&
+			((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) ||
+			(phba)->pport->cfg_log_verbose & LOG_ELS)
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+				 "2881 RRQ failure DID:%06X Status:x%x/x%x\n",
+				 ndlp->nlp_DID, irsp->ulpStatus,
+				 irsp->un.ulpWord[4]);
+	}
+out:
+	if (rrq)
+		lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+	lpfc_els_free_iocb(phba, cmdiocb);
+	return;
+}
+/**
  * lpfc_cmpl_els_plogi - Completion callback function for plogi
  * @phba: pointer to lpfc hba data structure.
  * @cmdiocb: pointer to lpfc command iocb data structure.
@@ -2722,7 +2824,7 @@
 			if (cmd == ELS_CMD_FLOGI) {
 				if (PCI_DEVICE_ID_HORNET ==
 					phba->pcidev->device) {
-					phba->fc_topology = TOPOLOGY_LOOP;
+					phba->fc_topology = LPFC_TOPOLOGY_LOOP;
 					phba->pport->fc_myDID = 0;
 					phba->alpa_map[0] = 0;
 					phba->alpa_map[1] = 0;
@@ -2877,7 +2979,7 @@
 		retry = 1;
 
 	if (((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) &&
-	    (phba->fc_topology != TOPOLOGY_LOOP) &&
+	    (phba->fc_topology != LPFC_TOPOLOGY_LOOP) &&
 	    !lpfc_error_lost_link(irsp)) {
 		/* FLOGI retry policy */
 		retry = 1;
@@ -3219,14 +3321,6 @@
 	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
 	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
 
-	/*
-	 * This routine is used to register and unregister in previous SLI
-	 * modes.
-	 */
-	if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) &&
-	    (phba->sli_rev == LPFC_SLI_REV4))
-		lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi);
-
 	pmb->context1 = NULL;
 	pmb->context2 = NULL;
 
@@ -3904,6 +3998,47 @@
 }
 
 /**
+ * lpfc_els_clear_rrq - Clear the rq that this rrq describes.
+ * @vport: pointer to a virtual N_Port data structure.
+ * @iocb: pointer to the lpfc command iocb data structure.
+ * @ndlp: pointer to a node-list data structure.
+ *
+ * Return
+ **/
+static void
+lpfc_els_clear_rrq(struct lpfc_vport *vport,
+      struct lpfc_iocbq *iocb, struct lpfc_nodelist *ndlp)
+{
+	struct lpfc_hba  *phba = vport->phba;
+	uint8_t *pcmd;
+	struct RRQ *rrq;
+	uint16_t rxid;
+	struct lpfc_node_rrq *prrq;
+
+
+	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt);
+	pcmd += sizeof(uint32_t);
+	rrq = (struct RRQ *)pcmd;
+	rxid = bf_get(rrq_oxid, rrq);
+
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+			"2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x"
+			" x%x x%x\n",
+			bf_get(rrq_did, rrq),
+			bf_get(rrq_oxid, rrq),
+			rxid,
+			iocb->iotag, iocb->iocb.ulpContext);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+		"Clear RRQ:  did:x%x flg:x%x exchg:x%.08x",
+		ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg);
+	prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID);
+	if (prrq)
+		lpfc_clr_rrq_active(phba, rxid, prrq);
+	return;
+}
+
+/**
  * lpfc_els_rsp_echo_acc - Issue echo acc response
  * @vport: pointer to a virtual N_Port data structure.
  * @data: pointer to echo data to return in the accept.
@@ -4597,7 +4732,7 @@
 
 	lpfc_set_disctmo(vport);
 
-	if (phba->fc_topology == TOPOLOGY_LOOP) {
+	if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 		/* We should never receive a FLOGI in loop mode, ignore it */
 		did = icmd->un.elsreq64.remoteID;
 
@@ -4792,6 +4927,8 @@
 		 struct lpfc_nodelist *ndlp)
 {
 	lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
+	if (vport->phba->sli_rev == LPFC_SLI_REV4)
+		lpfc_els_clear_rrq(vport, cmdiocb, ndlp);
 }
 
 /**
@@ -4940,7 +5077,7 @@
 	pcmd += sizeof(uint32_t); /* Skip past command */
 	rps_rsp = (RPS_RSP *)pcmd;
 
-	if (phba->fc_topology != TOPOLOGY_LOOP)
+	if (phba->fc_topology != LPFC_TOPOLOGY_LOOP)
 		status = 0x10;
 	else
 		status = 0x8;
@@ -5194,6 +5331,97 @@
 	return 0;
 }
 
+/* lpfc_issue_els_rrq - Process an unsolicited rps iocb
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @did: DID of the target.
+ * @rrq: Pointer to the rrq struct.
+ *
+ * Build a ELS RRQ command and send it to the target. If the issue_iocb is
+ * Successful the the completion handler will clear the RRQ.
+ *
+ * Return codes
+ *   0 - Successfully sent rrq els iocb.
+ *   1 - Failed to send rrq els iocb.
+ **/
+static int
+lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+			uint32_t did, struct lpfc_node_rrq *rrq)
+{
+	struct lpfc_hba  *phba = vport->phba;
+	struct RRQ *els_rrq;
+	IOCB_t *icmd;
+	struct lpfc_iocbq *elsiocb;
+	uint8_t *pcmd;
+	uint16_t cmdsize;
+	int ret;
+
+
+	if (ndlp != rrq->ndlp)
+		ndlp = rrq->ndlp;
+	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+		return 1;
+
+	/* If ndlp is not NULL, we will bump the reference count on it */
+	cmdsize = (sizeof(uint32_t) + sizeof(struct RRQ));
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, did,
+				     ELS_CMD_RRQ);
+	if (!elsiocb)
+		return 1;
+
+	icmd = &elsiocb->iocb;
+	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+
+	/* For RRQ request, remainder of payload is Exchange IDs */
+	*((uint32_t *) (pcmd)) = ELS_CMD_RRQ;
+	pcmd += sizeof(uint32_t);
+	els_rrq = (struct RRQ *) pcmd;
+
+	bf_set(rrq_oxid, els_rrq, rrq->xritag);
+	bf_set(rrq_rxid, els_rrq, rrq->rxid);
+	bf_set(rrq_did, els_rrq, vport->fc_myDID);
+	els_rrq->rrq = cpu_to_be32(els_rrq->rrq);
+	els_rrq->rrq_exchg = cpu_to_be32(els_rrq->rrq_exchg);
+
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+		"Issue RRQ:     did:x%x",
+		did, rrq->xritag, rrq->rxid);
+	elsiocb->context_un.rrq = rrq;
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq;
+	ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
+
+	if (ret == IOCB_ERROR) {
+		lpfc_els_free_iocb(phba, elsiocb);
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * lpfc_send_rrq - Sends ELS RRQ if needed.
+ * @phba: pointer to lpfc hba data structure.
+ * @rrq: pointer to the active rrq.
+ *
+ * This routine will call the lpfc_issue_els_rrq if the rrq is
+ * still active for the xri. If this function returns a failure then
+ * the caller needs to clean up the RRQ by calling lpfc_clr_active_rrq.
+ *
+ * Returns 0 Success.
+ *         1 Failure.
+ **/
+int
+lpfc_send_rrq(struct lpfc_hba *phba, struct lpfc_node_rrq *rrq)
+{
+	struct lpfc_nodelist *ndlp = lpfc_findnode_did(rrq->vport,
+							rrq->nlp_DID);
+	if (lpfc_test_rrq_active(phba, ndlp, rrq->xritag))
+		return lpfc_issue_els_rrq(rrq->vport, ndlp,
+					 rrq->nlp_DID, rrq);
+	else
+		return 1;
+}
+
 /**
  * lpfc_els_rsp_rpl_acc - Issue an accept rpl els command
  * @vport: pointer to a host virtual N_Port data structure.
@@ -5482,7 +5710,7 @@
 		    (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
 			    sizeof(struct lpfc_name)))) {
 			/* This port has switched fabrics. FLOGI is required */
-			lpfc_initial_flogi(vport);
+			lpfc_issue_init_vfi(vport);
 		} else {
 			/* FAN verified - skip FLOGI */
 			vport->fc_myDID = vport->fc_prevDID;
@@ -6201,7 +6429,7 @@
 			cmd, did, vport->port_state);
 
 		/* Unsupported ELS command, reject */
-		rjt_err = LSRJT_INVALID_CMD;
+		rjt_err = LSRJT_CMD_UNSUPPORTED;
 
 		/* Unknown ELS command <elsCmd> received from NPORT <did> */
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -6373,7 +6601,7 @@
 	if (!ndlp) {
 		ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
 		if (!ndlp) {
-			if (phba->fc_topology == TOPOLOGY_LOOP) {
+			if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 				lpfc_disc_start(vport);
 				return;
 			}
@@ -6386,7 +6614,7 @@
 	} else if (!NLP_CHK_NODE_ACT(ndlp)) {
 		ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
 		if (!ndlp) {
-			if (phba->fc_topology == TOPOLOGY_LOOP) {
+			if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 				lpfc_disc_start(vport);
 				return;
 			}
@@ -6408,18 +6636,31 @@
 	}
 
 	if (vport->cfg_fdmi_on) {
-		ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
-					  GFP_KERNEL);
+		/* If this is the first time, allocate an ndlp and initialize
+		 * it. Otherwise, make sure the node is enabled and then do the
+		 * login.
+		 */
+		ndlp_fdmi = lpfc_findnode_did(vport, FDMI_DID);
+		if (!ndlp_fdmi) {
+			ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
+						  GFP_KERNEL);
+			if (ndlp_fdmi) {
+				lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
+				ndlp_fdmi->nlp_type |= NLP_FABRIC;
+			} else
+				return;
+		}
+		if (!NLP_CHK_NODE_ACT(ndlp_fdmi))
+			ndlp_fdmi = lpfc_enable_node(vport,
+						     ndlp_fdmi,
+						     NLP_STE_NPR_NODE);
+
 		if (ndlp_fdmi) {
-			lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
-			ndlp_fdmi->nlp_type |= NLP_FABRIC;
 			lpfc_nlp_set_state(vport, ndlp_fdmi,
-				NLP_STE_PLOGI_ISSUE);
-			lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
-					     0);
+					   NLP_STE_PLOGI_ISSUE);
+			lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID, 0);
 		}
 	}
-	return;
 }
 
 /**
@@ -6497,7 +6738,7 @@
 			spin_unlock_irq(shost->host_lock);
 			if (vport->port_type == LPFC_PHYSICAL_PORT
 				&& !(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG))
-				lpfc_initial_flogi(vport);
+				lpfc_issue_init_vfi(vport);
 			else
 				lpfc_initial_fdisc(vport);
 			break;
@@ -6734,7 +6975,7 @@
 	vport->fc_flag &= ~FC_VPORT_CVL_RCVD;
 	vport->fc_flag &= ~FC_VPORT_LOGO_RCVD;
 	vport->fc_flag |= FC_FABRIC;
-	if (vport->phba->fc_topology == TOPOLOGY_LOOP)
+	if (vport->phba->fc_topology == LPFC_TOPOLOGY_LOOP)
 		vport->fc_flag |=  FC_PUBLIC_LOOP;
 	spin_unlock_irq(shost->host_lock);
 
@@ -6844,7 +7085,9 @@
 	icmd->un.elsreq64.myID = 0;
 	icmd->un.elsreq64.fl = 1;
 
-	if  (phba->sli_rev == LPFC_SLI_REV4) {
+	if  ((phba->sli_rev == LPFC_SLI_REV4) &&
+	     (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+	      LPFC_SLI_INTF_IF_TYPE_0)) {
 		/* FDISC needs to be 1 for WQE VPI */
 		elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1;
 		elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ;
@@ -7351,8 +7594,11 @@
 			  struct sli4_wcqe_xri_aborted *axri)
 {
 	uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
+	uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
+
 	struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
 	unsigned long iflag = 0;
+	struct lpfc_nodelist *ndlp;
 	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
 
 	spin_lock_irqsave(&phba->hbalock, iflag);
@@ -7361,11 +7607,14 @@
 			&phba->sli4_hba.lpfc_abts_els_sgl_list, list) {
 		if (sglq_entry->sli4_xritag == xri) {
 			list_del(&sglq_entry->list);
+			ndlp = sglq_entry->ndlp;
+			sglq_entry->ndlp = NULL;
 			list_add_tail(&sglq_entry->list,
 				&phba->sli4_hba.lpfc_sgl_list);
 			sglq_entry->state = SGL_FREED;
 			spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
 			spin_unlock_irqrestore(&phba->hbalock, iflag);
+			lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1);
 
 			/* Check if TXQ queue needs to be serviced */
 			if (pring->txq_cnt)
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index a5d1695..f9f160a 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -607,6 +607,8 @@
 
 	/* Process SLI4 events */
 	if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) {
+		if (phba->hba_flag & HBA_RRQ_ACTIVE)
+			lpfc_handle_rrq_active(phba);
 		if (phba->hba_flag & FCP_XRI_ABORT_EVENT)
 			lpfc_sli4_fcp_xri_abort_event_proc(phba);
 		if (phba->hba_flag & ELS_XRI_ABORT_EVENT)
@@ -966,6 +968,7 @@
 	struct lpfc_vport **vports;
 	int i;
 
+	lpfc_cleanup_wt_rrqs(phba);
 	phba->link_state = LPFC_LINK_UP;
 
 	/* Unblock fabric iocbs if they are blocked */
@@ -1064,7 +1067,7 @@
 
 	mempool_free(pmb, phba->mbox_mem_pool);
 
-	if (phba->fc_topology == TOPOLOGY_LOOP &&
+	if (phba->fc_topology == LPFC_TOPOLOGY_LOOP &&
 	    vport->fc_flag & FC_PUBLIC_LOOP &&
 	    !(vport->fc_flag & FC_LBIT)) {
 			/* Need to wait for FAN - use discovery timer
@@ -1078,9 +1081,8 @@
 	/* Start discovery by sending a FLOGI. port_state is identically
 	 * LPFC_FLOGI while waiting for FLOGI cmpl
 	 */
-	if (vport->port_state != LPFC_FLOGI) {
+	if (vport->port_state != LPFC_FLOGI)
 		lpfc_initial_flogi(vport);
-	}
 	return;
 
 out:
@@ -1131,7 +1133,7 @@
 	if (vport->port_state != LPFC_FLOGI) {
 		phba->hba_flag |= FCF_RR_INPROG;
 		spin_unlock_irq(&phba->hbalock);
-		lpfc_initial_flogi(vport);
+		lpfc_issue_init_vfi(vport);
 		goto out;
 	}
 	spin_unlock_irq(&phba->hbalock);
@@ -1353,7 +1355,7 @@
 		if (phba->pport->port_state != LPFC_FLOGI) {
 			phba->hba_flag |= FCF_RR_INPROG;
 			spin_unlock_irq(&phba->hbalock);
-			lpfc_initial_flogi(phba->pport);
+			lpfc_issue_init_vfi(phba->pport);
 			return;
 		}
 		spin_unlock_irq(&phba->hbalock);
@@ -2331,7 +2333,7 @@
 				phba->fcf.current_rec.fcf_indx, fcf_index);
 		/* Wait 500 ms before retrying FLOGI to current FCF */
 		msleep(500);
-		lpfc_initial_flogi(phba->pport);
+		lpfc_issue_init_vfi(phba->pport);
 		goto out;
 	}
 
@@ -2422,6 +2424,63 @@
 }
 
 /**
+ * lpfc_init_vfi_cmpl - Completion handler for init_vfi mbox command.
+ * @phba: pointer to lpfc hba data structure.
+ * @mboxq: pointer to mailbox data structure.
+ *
+ * This function handles completion of init vfi mailbox command.
+ */
+void
+lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+{
+	struct lpfc_vport *vport = mboxq->vport;
+
+	if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) {
+		lpfc_printf_vlog(vport, KERN_ERR,
+				LOG_MBOX,
+				"2891 Init VFI mailbox failed 0x%x\n",
+				mboxq->u.mb.mbxStatus);
+		mempool_free(mboxq, phba->mbox_mem_pool);
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		return;
+	}
+	lpfc_initial_flogi(vport);
+	mempool_free(mboxq, phba->mbox_mem_pool);
+	return;
+}
+
+/**
+ * lpfc_issue_init_vfi - Issue init_vfi mailbox command.
+ * @vport: pointer to lpfc_vport data structure.
+ *
+ * This function issue a init_vfi mailbox command to initialize the VFI and
+ * VPI for the physical port.
+ */
+void
+lpfc_issue_init_vfi(struct lpfc_vport *vport)
+{
+	LPFC_MBOXQ_t *mboxq;
+	int rc;
+	struct lpfc_hba *phba = vport->phba;
+
+	mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!mboxq) {
+		lpfc_printf_vlog(vport, KERN_ERR,
+			LOG_MBOX, "2892 Failed to allocate "
+			"init_vfi mailbox\n");
+		return;
+	}
+	lpfc_init_vfi(mboxq, vport);
+	mboxq->mbox_cmpl = lpfc_init_vfi_cmpl;
+	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
+	if (rc == MBX_NOT_FINISHED) {
+		lpfc_printf_vlog(vport, KERN_ERR,
+			LOG_MBOX, "2893 Failed to issue init_vfi mailbox\n");
+		mempool_free(mboxq, vport->phba->mbox_mem_pool);
+	}
+}
+
+/**
  * lpfc_init_vpi_cmpl - Completion handler for init_vpi mbox command.
  * @phba: pointer to lpfc hba data structure.
  * @mboxq: pointer to mailbox data structure.
@@ -2528,7 +2587,7 @@
 						     FC_VPORT_FAILED);
 				continue;
 			}
-			if (phba->fc_topology == TOPOLOGY_LOOP) {
+			if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 				lpfc_vport_set_state(vports[i],
 						     FC_VPORT_LINKDOWN);
 				continue;
@@ -2564,7 +2623,7 @@
 			 "2018 REG_VFI mbxStatus error x%x "
 			 "HBA state x%x\n",
 			 mboxq->u.mb.mbxStatus, vport->port_state);
-		if (phba->fc_topology == TOPOLOGY_LOOP) {
+		if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 			/* FLOGI failed, use loop map to make discovery list */
 			lpfc_disc_list_loopmap(vport);
 			/* Start discovery */
@@ -2582,8 +2641,18 @@
 	spin_unlock_irq(shost->host_lock);
 
 	if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
-		lpfc_start_fdiscs(phba);
-		lpfc_do_scr_ns_plogi(phba, vport);
+		/* For private loop just start discovery and we are done. */
+		if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) &&
+		    (phba->alpa_map[0] == 0) &&
+		    !(vport->fc_flag & FC_PUBLIC_LOOP)) {
+			/* Use loop map to make discovery list */
+			lpfc_disc_list_loopmap(vport);
+			/* Start discovery */
+			lpfc_disc_start(vport);
+		} else {
+			lpfc_start_fdiscs(phba);
+			lpfc_do_scr_ns_plogi(phba, vport);
+		}
 	}
 
 fail_free_mem:
@@ -2644,7 +2713,7 @@
 }
 
 static void
-lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
+lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
 {
 	struct lpfc_vport *vport = phba->pport;
 	LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL;
@@ -2654,31 +2723,24 @@
 	struct fcf_record *fcf_record;
 
 	spin_lock_irq(&phba->hbalock);
-	switch (la->UlnkSpeed) {
-	case LA_1GHZ_LINK:
-		phba->fc_linkspeed = LA_1GHZ_LINK;
-		break;
-	case LA_2GHZ_LINK:
-		phba->fc_linkspeed = LA_2GHZ_LINK;
-		break;
-	case LA_4GHZ_LINK:
-		phba->fc_linkspeed = LA_4GHZ_LINK;
-		break;
-	case LA_8GHZ_LINK:
-		phba->fc_linkspeed = LA_8GHZ_LINK;
-		break;
-	case LA_10GHZ_LINK:
-		phba->fc_linkspeed = LA_10GHZ_LINK;
+	switch (bf_get(lpfc_mbx_read_top_link_spd, la)) {
+	case LPFC_LINK_SPEED_1GHZ:
+	case LPFC_LINK_SPEED_2GHZ:
+	case LPFC_LINK_SPEED_4GHZ:
+	case LPFC_LINK_SPEED_8GHZ:
+	case LPFC_LINK_SPEED_10GHZ:
+	case LPFC_LINK_SPEED_16GHZ:
+		phba->fc_linkspeed = bf_get(lpfc_mbx_read_top_link_spd, la);
 		break;
 	default:
-		phba->fc_linkspeed = LA_UNKNW_LINK;
+		phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN;
 		break;
 	}
 
-	phba->fc_topology = la->topology;
+	phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la);
 	phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
 
-	if (phba->fc_topology == TOPOLOGY_LOOP) {
+	if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 		phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
 
 		/* if npiv is enabled and this adapter supports npiv log
@@ -2689,11 +2751,11 @@
 				"1309 Link Up Event npiv not supported in loop "
 				"topology\n");
 				/* Get Loop Map information */
-		if (la->il)
+		if (bf_get(lpfc_mbx_read_top_il, la))
 			vport->fc_flag |= FC_LBIT;
 
-		vport->fc_myDID = la->granted_AL_PA;
-		i = la->un.lilpBde64.tus.f.bdeSize;
+		vport->fc_myDID = bf_get(lpfc_mbx_read_top_alpa_granted, la);
+		i = la->lilpBde64.tus.f.bdeSize;
 
 		if (i == 0) {
 			phba->alpa_map[0] = 0;
@@ -2764,7 +2826,7 @@
 		goto out;
 	}
 
-	if (!(phba->hba_flag & HBA_FCOE_SUPPORT)) {
+	if (!(phba->hba_flag & HBA_FCOE_MODE)) {
 		cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 		if (!cfglink_mbox)
 			goto out;
@@ -2874,17 +2936,17 @@
 
 
 /*
- * This routine handles processing a READ_LA mailbox
+ * This routine handles processing a READ_TOPOLOGY mailbox
  * command upon completion. It is setup in the LPFC_MBOXQ
  * as the completion routine when the command is
  * handed off to the SLI layer.
  */
 void
-lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
 	struct lpfc_vport *vport = pmb->vport;
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
-	READ_LA_VAR *la;
+	struct lpfc_mbx_read_top *la;
 	MAILBOX_t *mb = &pmb->u.mb;
 	struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
 
@@ -2897,15 +2959,15 @@
 				mb->mbxStatus, vport->port_state);
 		lpfc_mbx_issue_link_down(phba);
 		phba->link_state = LPFC_HBA_ERROR;
-		goto lpfc_mbx_cmpl_read_la_free_mbuf;
+		goto lpfc_mbx_cmpl_read_topology_free_mbuf;
 	}
 
-	la = (READ_LA_VAR *) &pmb->u.mb.un.varReadLA;
+	la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop;
 
 	memcpy(&phba->alpa_map[0], mp->virt, 128);
 
 	spin_lock_irq(shost->host_lock);
-	if (la->pb)
+	if (bf_get(lpfc_mbx_read_top_pb, la))
 		vport->fc_flag |= FC_BYPASSED_MODE;
 	else
 		vport->fc_flag &= ~FC_BYPASSED_MODE;
@@ -2914,41 +2976,48 @@
 	if ((phba->fc_eventTag  < la->eventTag) ||
 	    (phba->fc_eventTag == la->eventTag)) {
 		phba->fc_stat.LinkMultiEvent++;
-		if (la->attType == AT_LINK_UP)
+		if (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)
 			if (phba->fc_eventTag != 0)
 				lpfc_linkdown(phba);
 	}
 
 	phba->fc_eventTag = la->eventTag;
 	spin_lock_irq(&phba->hbalock);
-	if (la->mm)
+	if (bf_get(lpfc_mbx_read_top_mm, la))
 		phba->sli.sli_flag |= LPFC_MENLO_MAINT;
 	else
 		phba->sli.sli_flag &= ~LPFC_MENLO_MAINT;
 	spin_unlock_irq(&phba->hbalock);
 
 	phba->link_events++;
-	if (la->attType == AT_LINK_UP && (!la->mm)) {
+	if ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) &&
+	    (!bf_get(lpfc_mbx_read_top_mm, la))) {
 		phba->fc_stat.LinkUp++;
 		if (phba->link_flag & LS_LOOPBACK_MODE) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
 					"1306 Link Up Event in loop back mode "
 					"x%x received Data: x%x x%x x%x x%x\n",
 					la->eventTag, phba->fc_eventTag,
-					la->granted_AL_PA, la->UlnkSpeed,
+					bf_get(lpfc_mbx_read_top_alpa_granted,
+					       la),
+					bf_get(lpfc_mbx_read_top_link_spd, la),
 					phba->alpa_map[0]);
 		} else {
 			lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
 					"1303 Link Up Event x%x received "
 					"Data: x%x x%x x%x x%x x%x x%x %d\n",
 					la->eventTag, phba->fc_eventTag,
-					la->granted_AL_PA, la->UlnkSpeed,
+					bf_get(lpfc_mbx_read_top_alpa_granted,
+					       la),
+					bf_get(lpfc_mbx_read_top_link_spd, la),
 					phba->alpa_map[0],
-					la->mm, la->fa,
+					bf_get(lpfc_mbx_read_top_mm, la),
+					bf_get(lpfc_mbx_read_top_fa, la),
 					phba->wait_4_mlo_maint_flg);
 		}
 		lpfc_mbx_process_link_up(phba, la);
-	} else if (la->attType == AT_LINK_DOWN) {
+	} else if (bf_get(lpfc_mbx_read_top_att_type, la) ==
+		   LPFC_ATT_LINK_DOWN) {
 		phba->fc_stat.LinkDown++;
 		if (phba->link_flag & LS_LOOPBACK_MODE) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -2964,11 +3033,13 @@
 				"Data: x%x x%x x%x x%x x%x\n",
 				la->eventTag, phba->fc_eventTag,
 				phba->pport->port_state, vport->fc_flag,
-				la->mm, la->fa);
+				bf_get(lpfc_mbx_read_top_mm, la),
+				bf_get(lpfc_mbx_read_top_fa, la));
 		}
 		lpfc_mbx_issue_link_down(phba);
 	}
-	if (la->mm && la->attType == AT_LINK_UP) {
+	if ((bf_get(lpfc_mbx_read_top_mm, la)) &&
+	    (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)) {
 		if (phba->link_state != LPFC_LINK_DOWN) {
 			phba->fc_stat.LinkDown++;
 			lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
@@ -2996,14 +3067,15 @@
 		}
 	}
 
-	if (la->fa) {
-		if (la->mm)
+	if (bf_get(lpfc_mbx_read_top_fa, la)) {
+		if (bf_get(lpfc_mbx_read_top_mm, la))
 			lpfc_issue_clear_la(phba, vport);
 		lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
-				"1311 fa %d\n", la->fa);
+				"1311 fa %d\n",
+				bf_get(lpfc_mbx_read_top_fa, la));
 	}
 
-lpfc_mbx_cmpl_read_la_free_mbuf:
+lpfc_mbx_cmpl_read_topology_free_mbuf:
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
 	mempool_free(pmb, phba->mbox_mem_pool);
@@ -3030,8 +3102,8 @@
 	if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
 		ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
 
-	if (ndlp->nlp_flag &  NLP_IGNR_REG_CMPL ||
-		ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) {
+	if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL ||
+	    ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) {
 		/* We rcvd a rscn after issuing this
 		 * mbox reg login, we may have cycled
 		 * back through the state and be
@@ -3043,10 +3115,6 @@
 		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
 		spin_unlock_irq(shost->host_lock);
-		if (phba->sli_rev == LPFC_SLI_REV4)
-			lpfc_sli4_free_rpi(phba,
-				pmb->u.mb.un.varRegLogin.rpi);
-
 	} else
 		/* Good status, call state machine */
 		lpfc_disc_state_machine(vport, ndlp, pmb,
@@ -3092,6 +3160,7 @@
 	spin_unlock_irq(shost->host_lock);
 	vport->unreg_vpi_cmpl = VPORT_OK;
 	mempool_free(pmb, phba->mbox_mem_pool);
+	lpfc_cleanup_vports_rrqs(vport);
 	/*
 	 * This shost reference might have been taken at the beginning of
 	 * lpfc_vport_delete()
@@ -3333,7 +3402,7 @@
 		kfree(mp);
 		mempool_free(pmb, phba->mbox_mem_pool);
 
-		if (phba->fc_topology == TOPOLOGY_LOOP) {
+		if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 			/* FLOGI failed, use loop map to make discovery list */
 			lpfc_disc_list_loopmap(vport);
 
@@ -3355,7 +3424,7 @@
 	}
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
-	ndlp->nlp_flag |= NLP_RPI_VALID;
+	ndlp->nlp_flag |= NLP_RPI_REGISTERED;
 	ndlp->nlp_type |= NLP_FABRIC;
 	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
@@ -3413,7 +3482,7 @@
 		/* If no other thread is using the ndlp, free it */
 		lpfc_nlp_not_used(ndlp);
 
-		if (phba->fc_topology == TOPOLOGY_LOOP) {
+		if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
 			/*
 			 * RegLogin failed, use loop map to make discovery
 			 * list
@@ -3429,7 +3498,7 @@
 	}
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
-	ndlp->nlp_flag |= NLP_RPI_VALID;
+	ndlp->nlp_flag |= NLP_RPI_REGISTERED;
 	ndlp->nlp_type |= NLP_FABRIC;
 	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
@@ -3762,6 +3831,8 @@
 	NLP_INT_NODE_ACT(ndlp);
 	atomic_set(&ndlp->cmd_pending, 0);
 	ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth;
+	if (vport->phba->sli_rev == LPFC_SLI_REV4)
+		ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba);
 }
 
 struct lpfc_nodelist *
@@ -3975,7 +4046,7 @@
 	 * by firmware with a no rpi error.
 	 */
 	psli = &phba->sli;
-	if (ndlp->nlp_flag & NLP_RPI_VALID) {
+	if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
 		/* Now process each ring */
 		for (i = 0; i < psli->num_rings; i++) {
 			pring = &psli->ring[i];
@@ -4023,7 +4094,7 @@
 	LPFC_MBOXQ_t    *mbox;
 	int rc;
 
-	if (ndlp->nlp_flag & NLP_RPI_VALID) {
+	if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
 		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 		if (mbox) {
 			lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox);
@@ -4035,8 +4106,9 @@
 		}
 		lpfc_no_rpi(phba, ndlp);
 
-		ndlp->nlp_rpi = 0;
-		ndlp->nlp_flag &= ~NLP_RPI_VALID;
+		if (phba->sli_rev != LPFC_SLI_REV4)
+			ndlp->nlp_rpi = 0;
+		ndlp->nlp_flag &= ~NLP_RPI_REGISTERED;
 		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
 		return 1;
 	}
@@ -4059,11 +4131,16 @@
 	int i;
 
 	vports = lpfc_create_vport_work_array(phba);
+	if (!vports) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+			"2884 Vport array allocation failed \n");
+		return;
+	}
 	for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
 		shost = lpfc_shost_from_vport(vports[i]);
 		spin_lock_irq(shost->host_lock);
 		list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) {
-			if (ndlp->nlp_flag & NLP_RPI_VALID) {
+			if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
 				/* The mempool_alloc might sleep */
 				spin_unlock_irq(shost->host_lock);
 				lpfc_unreg_rpi(vports[i], ndlp);
@@ -4192,9 +4269,6 @@
 				kfree(mp);
 			}
 			list_del(&mb->list);
-			if (phba->sli_rev == LPFC_SLI_REV4)
-				lpfc_sli4_free_rpi(phba,
-					 mb->u.mb.un.varRegLogin.rpi);
 			mempool_free(mb, phba->mbox_mem_pool);
 			/* We shall not invoke the lpfc_nlp_put to decrement
 			 * the ndlp reference count as we are in the process
@@ -4236,15 +4310,15 @@
 
 	lpfc_cancel_retry_delay_tmo(vport, ndlp);
 	if ((ndlp->nlp_flag & NLP_DEFER_RM) &&
-		!(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) &&
-	    !(ndlp->nlp_flag & NLP_RPI_VALID)) {
+	    !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) &&
+	    !(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
 		/* For this case we need to cleanup the default rpi
 		 * allocated by the firmware.
 		 */
 		if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))
 			!= NULL) {
 			rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID,
-			    (uint8_t *) &vport->fc_sparam, mbox, 0);
+			    (uint8_t *) &vport->fc_sparam, mbox, ndlp->nlp_rpi);
 			if (rc) {
 				mempool_free(mbox, phba->mbox_mem_pool);
 			}
@@ -4436,7 +4510,7 @@
 	if (!lpfc_is_link_up(phba))
 		return;
 
-	if (phba->fc_topology != TOPOLOGY_LOOP)
+	if (phba->fc_topology != LPFC_TOPOLOGY_LOOP)
 		return;
 
 	/* Check for loop map present or not */
@@ -4788,7 +4862,10 @@
 			}
 		}
 		if (vport->port_state != LPFC_FLOGI) {
-			lpfc_initial_flogi(vport);
+			if (phba->sli_rev <= LPFC_SLI_REV3)
+				lpfc_initial_flogi(vport);
+			else
+				lpfc_issue_init_vfi(vport);
 			return;
 		}
 		break;
@@ -4979,7 +5056,7 @@
 	pmb->context2 = NULL;
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
-	ndlp->nlp_flag |= NLP_RPI_VALID;
+	ndlp->nlp_flag |= NLP_RPI_REGISTERED;
 	ndlp->nlp_type |= NLP_FABRIC;
 	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
 
@@ -5103,6 +5180,8 @@
 	spin_lock_irqsave(&phba->ndlp_lock, flags);
 	NLP_CLR_NODE_ACT(ndlp);
 	spin_unlock_irqrestore(&phba->ndlp_lock, flags);
+	if (phba->sli_rev == LPFC_SLI_REV4)
+		lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
 
 	/* free ndlp memory for final ndlp release */
 	if (NLP_CHK_FREE_REQ(ndlp)) {
@@ -5254,6 +5333,10 @@
 
 	vports = lpfc_create_vport_work_array(phba);
 
+	/* If driver cannot allocate memory, indicate fcf is in use */
+	if (!vports)
+		return 1;
+
 	for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
 		shost = lpfc_shost_from_vport(vports[i]);
 		spin_lock_irq(shost->host_lock);
@@ -5269,7 +5352,7 @@
 					"logged in\n",
 					ndlp->nlp_rpi, ndlp->nlp_DID,
 					ndlp->nlp_flag);
-				if (ndlp->nlp_flag & NLP_RPI_VALID)
+				if (ndlp->nlp_flag & NLP_RPI_REGISTERED)
 					ret = 1;
 			}
 		}
@@ -5550,7 +5633,7 @@
 	 * registered, do nothing.
 	 */
 	spin_lock_irq(&phba->hbalock);
-	if (!(phba->hba_flag & HBA_FCOE_SUPPORT) ||
+	if (!(phba->hba_flag & HBA_FCOE_MODE) ||
 	    !(phba->fcf.fcf_flag & FCF_REGISTERED) ||
 	    !(phba->hba_flag & HBA_FIP_SUPPORT) ||
 	    (phba->fcf.fcf_flag & FCF_DISCOVERY) ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 9b83334..96ed3ba 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -880,6 +880,24 @@
 	uint32_t crcCnt;
 };
 
+struct RRQ {			/* Structure is in Big Endian format */
+	uint32_t rrq;
+#define rrq_rsvd_SHIFT		24
+#define rrq_rsvd_MASK		0x000000ff
+#define rrq_rsvd_WORD		rrq
+#define rrq_did_SHIFT		0
+#define rrq_did_MASK		0x00ffffff
+#define rrq_did_WORD		rrq
+	uint32_t rrq_exchg;
+#define rrq_oxid_SHIFT		16
+#define rrq_oxid_MASK		0xffff
+#define rrq_oxid_WORD		rrq_exchg
+#define rrq_rxid_SHIFT		0
+#define rrq_rxid_MASK		0xffff
+#define rrq_rxid_WORD		rrq_exchg
+};
+
+
 struct RTV_RSP {		/* Structure is in Big Endian format */
 	uint32_t ratov;
 	uint32_t edtov;
@@ -1172,7 +1190,10 @@
 #define PCI_VENDOR_ID_EMULEX        0x10df
 #define PCI_DEVICE_ID_FIREFLY       0x1ae5
 #define PCI_DEVICE_ID_PROTEUS_VF    0xe100
+#define PCI_DEVICE_ID_BALIUS        0xe131
 #define PCI_DEVICE_ID_PROTEUS_PF    0xe180
+#define PCI_DEVICE_ID_LANCER_FC     0xe200
+#define PCI_DEVICE_ID_LANCER_FCOE   0xe260
 #define PCI_DEVICE_ID_SAT_SMB       0xf011
 #define PCI_DEVICE_ID_SAT_MID       0xf015
 #define PCI_DEVICE_ID_RFLY          0xf095
@@ -1189,6 +1210,7 @@
 #define PCI_DEVICE_ID_SAT           0xf100
 #define PCI_DEVICE_ID_SAT_SCSP      0xf111
 #define PCI_DEVICE_ID_SAT_DCSP      0xf112
+#define PCI_DEVICE_ID_FALCON        0xf180
 #define PCI_DEVICE_ID_SUPERFLY      0xf700
 #define PCI_DEVICE_ID_DRAGONFLY     0xf800
 #define PCI_DEVICE_ID_CENTAUR       0xf900
@@ -1210,8 +1232,6 @@
 #define PCI_VENDOR_ID_SERVERENGINE  0x19a2
 #define PCI_DEVICE_ID_TIGERSHARK    0x0704
 #define PCI_DEVICE_ID_TOMCAT        0x0714
-#define PCI_DEVICE_ID_FALCON        0xf180
-#define PCI_DEVICE_ID_BALIUS        0xe131
 
 #define JEDEC_ID_ADDRESS            0x0080001c
 #define FIREFLY_JEDEC_ID            0x1ACC
@@ -1368,7 +1388,6 @@
 #define MBX_READ_LNK_STAT   0x12
 #define MBX_REG_LOGIN       0x13
 #define MBX_UNREG_LOGIN     0x14
-#define MBX_READ_LA         0x15
 #define MBX_CLEAR_LA        0x16
 #define MBX_DUMP_MEMORY     0x17
 #define MBX_DUMP_CONTEXT    0x18
@@ -1402,7 +1421,7 @@
 #define MBX_READ_SPARM64    0x8D
 #define MBX_READ_RPI64      0x8F
 #define MBX_REG_LOGIN64     0x93
-#define MBX_READ_LA64       0x95
+#define MBX_READ_TOPOLOGY   0x95
 #define MBX_REG_VPI	    0x96
 #define MBX_UNREG_VPI	    0x97
 
@@ -1823,12 +1842,13 @@
 #define FLAGS_IMED_ABORT             0x04000	/* Bit 14 */
 
 	uint32_t link_speed;
-#define LINK_SPEED_AUTO 0       /* Auto selection */
-#define LINK_SPEED_1G   1       /* 1 Gigabaud */
-#define LINK_SPEED_2G   2       /* 2 Gigabaud */
-#define LINK_SPEED_4G   4       /* 4 Gigabaud */
-#define LINK_SPEED_8G   8       /* 8 Gigabaud */
-#define LINK_SPEED_10G   16      /* 10 Gigabaud */
+#define LINK_SPEED_AUTO 0x0     /* Auto selection */
+#define LINK_SPEED_1G   0x1     /* 1 Gigabaud */
+#define LINK_SPEED_2G   0x2     /* 2 Gigabaud */
+#define LINK_SPEED_4G   0x4     /* 4 Gigabaud */
+#define LINK_SPEED_8G   0x8     /* 8 Gigabaud */
+#define LINK_SPEED_10G  0x10    /* 10 Gigabaud */
+#define LINK_SPEED_16G  0x11    /* 16 Gigabaud */
 
 } INIT_LINK_VAR;
 
@@ -1999,6 +2019,7 @@
 #define LMT_4Gb       0x040
 #define LMT_8Gb       0x080
 #define LMT_10Gb      0x100
+#define LMT_16Gb      0x200
 	uint32_t rsvd2;
 	uint32_t rsvd3;
 	uint32_t max_xri;
@@ -2394,100 +2415,93 @@
 #endif
 } UNREG_D_ID_VAR;
 
-/* Structure for MB Command READ_LA (21) */
-/* Structure for MB Command READ_LA64 (0x95) */
-
-typedef struct {
+/* Structure for MB Command READ_TOPOLOGY (0x95) */
+struct lpfc_mbx_read_top {
 	uint32_t eventTag;	/* Event tag */
-#ifdef __BIG_ENDIAN_BITFIELD
-	uint32_t rsvd1:19;
-	uint32_t fa:1;
-	uint32_t mm:1;		/* Menlo Maintenance mode enabled */
-	uint32_t rx:1;
-	uint32_t pb:1;
-	uint32_t il:1;
-	uint32_t attType:8;
-#else	/*  __LITTLE_ENDIAN_BITFIELD */
-	uint32_t attType:8;
-	uint32_t il:1;
-	uint32_t pb:1;
-	uint32_t rx:1;
-	uint32_t mm:1;
-	uint32_t fa:1;
-	uint32_t rsvd1:19;
-#endif
-
-#define AT_RESERVED    0x00	/* Reserved - attType */
-#define AT_LINK_UP     0x01	/* Link is up */
-#define AT_LINK_DOWN   0x02	/* Link is down */
-
-#ifdef __BIG_ENDIAN_BITFIELD
-	uint8_t granted_AL_PA;
-	uint8_t lipAlPs;
-	uint8_t lipType;
-	uint8_t topology;
-#else	/*  __LITTLE_ENDIAN_BITFIELD */
-	uint8_t topology;
-	uint8_t lipType;
-	uint8_t lipAlPs;
-	uint8_t granted_AL_PA;
-#endif
-
-#define TOPOLOGY_PT_PT 0x01	/* Topology is pt-pt / pt-fabric */
-#define TOPOLOGY_LOOP  0x02	/* Topology is FC-AL */
-#define TOPOLOGY_LNK_MENLO_MAINTENANCE 0x05 /* maint mode zephtr to menlo */
-
-	union {
-		struct ulp_bde lilpBde; /* This BDE points to a 128 byte buffer
-					   to */
-		/* store the LILP AL_PA position map into */
-		struct ulp_bde64 lilpBde64;
-	} un;
-
-#ifdef __BIG_ENDIAN_BITFIELD
-	uint32_t Dlu:1;
-	uint32_t Dtf:1;
-	uint32_t Drsvd2:14;
-	uint32_t DlnkSpeed:8;
-	uint32_t DnlPort:4;
-	uint32_t Dtx:2;
-	uint32_t Drx:2;
-#else	/*  __LITTLE_ENDIAN_BITFIELD */
-	uint32_t Drx:2;
-	uint32_t Dtx:2;
-	uint32_t DnlPort:4;
-	uint32_t DlnkSpeed:8;
-	uint32_t Drsvd2:14;
-	uint32_t Dtf:1;
-	uint32_t Dlu:1;
-#endif
-
-#ifdef __BIG_ENDIAN_BITFIELD
-	uint32_t Ulu:1;
-	uint32_t Utf:1;
-	uint32_t Ursvd2:14;
-	uint32_t UlnkSpeed:8;
-	uint32_t UnlPort:4;
-	uint32_t Utx:2;
-	uint32_t Urx:2;
-#else	/*  __LITTLE_ENDIAN_BITFIELD */
-	uint32_t Urx:2;
-	uint32_t Utx:2;
-	uint32_t UnlPort:4;
-	uint32_t UlnkSpeed:8;
-	uint32_t Ursvd2:14;
-	uint32_t Utf:1;
-	uint32_t Ulu:1;
-#endif
-
-#define LA_UNKNW_LINK  0x0    /* lnkSpeed */
-#define LA_1GHZ_LINK   0x04   /* lnkSpeed */
-#define LA_2GHZ_LINK   0x08   /* lnkSpeed */
-#define LA_4GHZ_LINK   0x10   /* lnkSpeed */
-#define LA_8GHZ_LINK   0x20   /* lnkSpeed */
-#define LA_10GHZ_LINK  0x40   /* lnkSpeed */
-
-} READ_LA_VAR;
+	uint32_t word2;
+#define lpfc_mbx_read_top_fa_SHIFT		12
+#define lpfc_mbx_read_top_fa_MASK		0x00000001
+#define lpfc_mbx_read_top_fa_WORD		word2
+#define lpfc_mbx_read_top_mm_SHIFT		11
+#define lpfc_mbx_read_top_mm_MASK		0x00000001
+#define lpfc_mbx_read_top_mm_WORD		word2
+#define lpfc_mbx_read_top_pb_SHIFT		9
+#define lpfc_mbx_read_top_pb_MASK		0X00000001
+#define lpfc_mbx_read_top_pb_WORD		word2
+#define lpfc_mbx_read_top_il_SHIFT		8
+#define lpfc_mbx_read_top_il_MASK		0x00000001
+#define lpfc_mbx_read_top_il_WORD		word2
+#define lpfc_mbx_read_top_att_type_SHIFT	0
+#define lpfc_mbx_read_top_att_type_MASK		0x000000FF
+#define lpfc_mbx_read_top_att_type_WORD		word2
+#define LPFC_ATT_RESERVED    0x00	/* Reserved - attType */
+#define LPFC_ATT_LINK_UP     0x01	/* Link is up */
+#define LPFC_ATT_LINK_DOWN   0x02	/* Link is down */
+	uint32_t word3;
+#define lpfc_mbx_read_top_alpa_granted_SHIFT	24
+#define lpfc_mbx_read_top_alpa_granted_MASK	0x000000FF
+#define lpfc_mbx_read_top_alpa_granted_WORD	word3
+#define lpfc_mbx_read_top_lip_alps_SHIFT	16
+#define lpfc_mbx_read_top_lip_alps_MASK		0x000000FF
+#define lpfc_mbx_read_top_lip_alps_WORD		word3
+#define lpfc_mbx_read_top_lip_type_SHIFT	8
+#define lpfc_mbx_read_top_lip_type_MASK		0x000000FF
+#define lpfc_mbx_read_top_lip_type_WORD		word3
+#define lpfc_mbx_read_top_topology_SHIFT	0
+#define lpfc_mbx_read_top_topology_MASK		0x000000FF
+#define lpfc_mbx_read_top_topology_WORD		word3
+#define LPFC_TOPOLOGY_PT_PT 0x01	/* Topology is pt-pt / pt-fabric */
+#define LPFC_TOPOLOGY_LOOP  0x02	/* Topology is FC-AL */
+#define LPFC_TOPOLOGY_MM    0x05	/* maint mode zephtr to menlo */
+	/* store the LILP AL_PA position map into */
+	struct ulp_bde64 lilpBde64;
+#define LPFC_ALPA_MAP_SIZE	128
+	uint32_t word7;
+#define lpfc_mbx_read_top_ld_lu_SHIFT		31
+#define lpfc_mbx_read_top_ld_lu_MASK		0x00000001
+#define lpfc_mbx_read_top_ld_lu_WORD		word7
+#define lpfc_mbx_read_top_ld_tf_SHIFT		30
+#define lpfc_mbx_read_top_ld_tf_MASK		0x00000001
+#define lpfc_mbx_read_top_ld_tf_WORD		word7
+#define lpfc_mbx_read_top_ld_link_spd_SHIFT	8
+#define lpfc_mbx_read_top_ld_link_spd_MASK	0x000000FF
+#define lpfc_mbx_read_top_ld_link_spd_WORD	word7
+#define lpfc_mbx_read_top_ld_nl_port_SHIFT	4
+#define lpfc_mbx_read_top_ld_nl_port_MASK	0x0000000F
+#define lpfc_mbx_read_top_ld_nl_port_WORD	word7
+#define lpfc_mbx_read_top_ld_tx_SHIFT		2
+#define lpfc_mbx_read_top_ld_tx_MASK		0x00000003
+#define lpfc_mbx_read_top_ld_tx_WORD		word7
+#define lpfc_mbx_read_top_ld_rx_SHIFT		0
+#define lpfc_mbx_read_top_ld_rx_MASK		0x00000003
+#define lpfc_mbx_read_top_ld_rx_WORD		word7
+	uint32_t word8;
+#define lpfc_mbx_read_top_lu_SHIFT		31
+#define lpfc_mbx_read_top_lu_MASK		0x00000001
+#define lpfc_mbx_read_top_lu_WORD		word8
+#define lpfc_mbx_read_top_tf_SHIFT		30
+#define lpfc_mbx_read_top_tf_MASK		0x00000001
+#define lpfc_mbx_read_top_tf_WORD		word8
+#define lpfc_mbx_read_top_link_spd_SHIFT	8
+#define lpfc_mbx_read_top_link_spd_MASK		0x000000FF
+#define lpfc_mbx_read_top_link_spd_WORD		word8
+#define lpfc_mbx_read_top_nl_port_SHIFT		4
+#define lpfc_mbx_read_top_nl_port_MASK		0x0000000F
+#define lpfc_mbx_read_top_nl_port_WORD		word8
+#define lpfc_mbx_read_top_tx_SHIFT		2
+#define lpfc_mbx_read_top_tx_MASK		0x00000003
+#define lpfc_mbx_read_top_tx_WORD		word8
+#define lpfc_mbx_read_top_rx_SHIFT		0
+#define lpfc_mbx_read_top_rx_MASK		0x00000003
+#define lpfc_mbx_read_top_rx_WORD		word8
+#define LPFC_LINK_SPEED_UNKNOWN	0x0
+#define LPFC_LINK_SPEED_1GHZ	0x04
+#define LPFC_LINK_SPEED_2GHZ	0x08
+#define LPFC_LINK_SPEED_4GHZ	0x10
+#define LPFC_LINK_SPEED_8GHZ	0x20
+#define LPFC_LINK_SPEED_10GHZ	0x40
+#define LPFC_LINK_SPEED_16GHZ	0x80
+};
 
 /* Structure for MB Command CLEAR_LA (22) */
 
@@ -3016,7 +3030,6 @@
 	READ_LNK_VAR varRdLnk;		/* cmd = 18 (READ_LNK_STAT)  */
 	REG_LOGIN_VAR varRegLogin;	/* cmd = 19 (REG_LOGIN(64))  */
 	UNREG_LOGIN_VAR varUnregLogin;	/* cmd = 20 (UNREG_LOGIN)    */
-	READ_LA_VAR varReadLA;		/* cmd = 21 (READ_LA(64))    */
 	CLEAR_LA_VAR varClearLA;	/* cmd = 22 (CLEAR_LA)       */
 	DUMP_VAR varDmp;		/* Warm Start DUMP mbx cmd   */
 	UNREG_D_ID_VAR varUnregDID;	/* cmd = 0x23 (UNREG_D_ID)   */
@@ -3026,6 +3039,7 @@
 	struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ)  */
 	struct update_cfg_var varUpdateCfg; /* cmd = 0x1B (UPDATE_CFG)*/
 	CONFIG_PORT_VAR varCfgPort;	/* cmd = 0x88 (CONFIG_PORT)  */
+	struct lpfc_mbx_read_top varReadTop; /* cmd = 0x95 (READ_TOPOLOGY) */
 	REG_VPI_VAR varRegVpi;		/* cmd = 0x96 (REG_VPI) */
 	UNREG_VPI_VAR varUnregVpi;	/* cmd = 0x97 (UNREG_VPI) */
 	ASYNCEVT_ENABLE_VAR varCfgAsyncEvent; /*cmd = x33 (CONFIG_ASYNC) */
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 6e4bc34..94c1aa1 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -64,29 +64,39 @@
 #define lpfc_sli_intf_valid_MASK		0x00000007
 #define lpfc_sli_intf_valid_WORD		word0
 #define LPFC_SLI_INTF_VALID		6
-#define lpfc_sli_intf_featurelevel2_SHIFT	24
-#define lpfc_sli_intf_featurelevel2_MASK	0x0000001F
-#define lpfc_sli_intf_featurelevel2_WORD	word0
-#define lpfc_sli_intf_featurelevel1_SHIFT	16
-#define lpfc_sli_intf_featurelevel1_MASK	0x000000FF
-#define lpfc_sli_intf_featurelevel1_WORD	word0
-#define LPFC_SLI_INTF_FEATURELEVEL1_1	1
-#define LPFC_SLI_INTF_FEATURELEVEL1_2	2
+#define lpfc_sli_intf_sli_hint2_SHIFT		24
+#define lpfc_sli_intf_sli_hint2_MASK		0x0000001F
+#define lpfc_sli_intf_sli_hint2_WORD		word0
+#define LPFC_SLI_INTF_SLI_HINT2_NONE	0
+#define lpfc_sli_intf_sli_hint1_SHIFT		16
+#define lpfc_sli_intf_sli_hint1_MASK		0x000000FF
+#define lpfc_sli_intf_sli_hint1_WORD		word0
+#define LPFC_SLI_INTF_SLI_HINT1_NONE	0
+#define LPFC_SLI_INTF_SLI_HINT1_1	1
+#define LPFC_SLI_INTF_SLI_HINT1_2	2
+#define lpfc_sli_intf_if_type_SHIFT		12
+#define lpfc_sli_intf_if_type_MASK		0x0000000F
+#define lpfc_sli_intf_if_type_WORD		word0
+#define LPFC_SLI_INTF_IF_TYPE_0		0
+#define LPFC_SLI_INTF_IF_TYPE_1		1
+#define LPFC_SLI_INTF_IF_TYPE_2		2
 #define lpfc_sli_intf_sli_family_SHIFT		8
-#define lpfc_sli_intf_sli_family_MASK		0x000000FF
+#define lpfc_sli_intf_sli_family_MASK		0x0000000F
 #define lpfc_sli_intf_sli_family_WORD		word0
-#define LPFC_SLI_INTF_FAMILY_BE2	0
-#define LPFC_SLI_INTF_FAMILY_BE3	1
+#define LPFC_SLI_INTF_FAMILY_BE2	0x0
+#define LPFC_SLI_INTF_FAMILY_BE3	0x1
+#define LPFC_SLI_INTF_FAMILY_LNCR_A0	0xa
+#define LPFC_SLI_INTF_FAMILY_LNCR_B0	0xb
 #define lpfc_sli_intf_slirev_SHIFT		4
 #define lpfc_sli_intf_slirev_MASK		0x0000000F
 #define lpfc_sli_intf_slirev_WORD		word0
 #define LPFC_SLI_INTF_REV_SLI3		3
 #define LPFC_SLI_INTF_REV_SLI4		4
-#define lpfc_sli_intf_if_type_SHIFT		0
-#define lpfc_sli_intf_if_type_MASK		0x00000007
-#define lpfc_sli_intf_if_type_WORD		word0
-#define LPFC_SLI_INTF_IF_TYPE_0		0
-#define LPFC_SLI_INTF_IF_TYPE_1		1
+#define lpfc_sli_intf_func_type_SHIFT		0
+#define lpfc_sli_intf_func_type_MASK		0x00000001
+#define lpfc_sli_intf_func_type_WORD		word0
+#define LPFC_SLI_INTF_IF_TYPE_PHYS	0
+#define LPFC_SLI_INTF_IF_TYPE_VIRT	1
 };
 
 #define LPFC_SLI4_MBX_EMBED	true
@@ -450,35 +460,40 @@
 	uint32_t word0;
 };
 
+/* The following BAR0 Registers apply to SLI4 if_type 0 UCNAs. */
 #define LPFC_UERR_STATUS_HI		0x00A4
 #define LPFC_UERR_STATUS_LO		0x00A0
 #define LPFC_UE_MASK_HI			0x00AC
 #define LPFC_UE_MASK_LO			0x00A8
+
+/* The following BAR0 register sets are defined for if_type 0 and 2 UCNAs. */
 #define LPFC_SLI_INTF			0x0058
 
-/* BAR0 Registers */
-#define LPFC_HST_STATE			0x00AC
-#define lpfc_hst_state_perr_SHIFT	31
-#define lpfc_hst_state_perr_MASK	0x1
-#define lpfc_hst_state_perr_WORD	word0
-#define lpfc_hst_state_sfi_SHIFT	30
-#define lpfc_hst_state_sfi_MASK		0x1
-#define lpfc_hst_state_sfi_WORD		word0
-#define lpfc_hst_state_nip_SHIFT	29
-#define lpfc_hst_state_nip_MASK		0x1
-#define lpfc_hst_state_nip_WORD		word0
-#define lpfc_hst_state_ipc_SHIFT	28
-#define lpfc_hst_state_ipc_MASK		0x1
-#define lpfc_hst_state_ipc_WORD		word0
-#define lpfc_hst_state_xrom_SHIFT	27
-#define lpfc_hst_state_xrom_MASK	0x1
-#define lpfc_hst_state_xrom_WORD	word0
-#define lpfc_hst_state_dl_SHIFT		26
-#define lpfc_hst_state_dl_MASK		0x1
-#define lpfc_hst_state_dl_WORD		word0
-#define lpfc_hst_state_port_status_SHIFT	0
-#define lpfc_hst_state_port_status_MASK		0xFFFF
-#define lpfc_hst_state_port_status_WORD		word0
+#define LPFC_SLIPORT_IF2_SMPHR		0x0400
+#define lpfc_port_smphr_perr_SHIFT	31
+#define lpfc_port_smphr_perr_MASK	0x1
+#define lpfc_port_smphr_perr_WORD	word0
+#define lpfc_port_smphr_sfi_SHIFT	30
+#define lpfc_port_smphr_sfi_MASK	0x1
+#define lpfc_port_smphr_sfi_WORD	word0
+#define lpfc_port_smphr_nip_SHIFT	29
+#define lpfc_port_smphr_nip_MASK	0x1
+#define lpfc_port_smphr_nip_WORD	word0
+#define lpfc_port_smphr_ipc_SHIFT	28
+#define lpfc_port_smphr_ipc_MASK	0x1
+#define lpfc_port_smphr_ipc_WORD	word0
+#define lpfc_port_smphr_scr1_SHIFT	27
+#define lpfc_port_smphr_scr1_MASK	0x1
+#define lpfc_port_smphr_scr1_WORD	word0
+#define lpfc_port_smphr_scr2_SHIFT	26
+#define lpfc_port_smphr_scr2_MASK	0x1
+#define lpfc_port_smphr_scr2_WORD	word0
+#define lpfc_port_smphr_host_scratch_SHIFT	16
+#define lpfc_port_smphr_host_scratch_MASK	0xFF
+#define lpfc_port_smphr_host_scratch_WORD	word0
+#define lpfc_port_smphr_port_status_SHIFT	0
+#define lpfc_port_smphr_port_status_MASK	0xFFFF
+#define lpfc_port_smphr_port_status_WORD	word0
 
 #define LPFC_POST_STAGE_POWER_ON_RESET			0x0000
 #define LPFC_POST_STAGE_AWAITING_HOST_RDY		0x0001
@@ -511,10 +526,46 @@
 #define LPFC_POST_STAGE_RC_DONE				0x0B07
 #define LPFC_POST_STAGE_REBOOT_SYSTEM			0x0B08
 #define LPFC_POST_STAGE_MAC_ADDRESS			0x0C00
-#define LPFC_POST_STAGE_ARMFW_READY			0xC000
-#define LPFC_POST_STAGE_ARMFW_UE 			0xF000
+#define LPFC_POST_STAGE_PORT_READY			0xC000
+#define LPFC_POST_STAGE_PORT_UE 			0xF000
 
-/* BAR1 Registers */
+#define LPFC_SLIPORT_STATUS		0x0404
+#define lpfc_sliport_status_err_SHIFT	31
+#define lpfc_sliport_status_err_MASK	0x1
+#define lpfc_sliport_status_err_WORD	word0
+#define lpfc_sliport_status_end_SHIFT	30
+#define lpfc_sliport_status_end_MASK	0x1
+#define lpfc_sliport_status_end_WORD	word0
+#define lpfc_sliport_status_oti_SHIFT	29
+#define lpfc_sliport_status_oti_MASK	0x1
+#define lpfc_sliport_status_oti_WORD	word0
+#define lpfc_sliport_status_rn_SHIFT	24
+#define lpfc_sliport_status_rn_MASK	0x1
+#define lpfc_sliport_status_rn_WORD	word0
+#define lpfc_sliport_status_rdy_SHIFT	23
+#define lpfc_sliport_status_rdy_MASK	0x1
+#define lpfc_sliport_status_rdy_WORD	word0
+#define MAX_IF_TYPE_2_RESETS	1000
+
+#define LPFC_SLIPORT_CNTRL		0x0408
+#define lpfc_sliport_ctrl_end_SHIFT	30
+#define lpfc_sliport_ctrl_end_MASK	0x1
+#define lpfc_sliport_ctrl_end_WORD	word0
+#define LPFC_SLIPORT_LITTLE_ENDIAN 0
+#define LPFC_SLIPORT_BIG_ENDIAN	   1
+#define lpfc_sliport_ctrl_ip_SHIFT	27
+#define lpfc_sliport_ctrl_ip_MASK	0x1
+#define lpfc_sliport_ctrl_ip_WORD	word0
+#define LPFC_SLIPORT_INIT_PORT	1
+
+#define LPFC_SLIPORT_ERR_1		0x040C
+#define LPFC_SLIPORT_ERR_2		0x0410
+
+/* The following Registers apply to SLI4 if_type 0 UCNAs. They typically
+ * reside in BAR 2.
+ */
+#define LPFC_SLIPORT_IF0_SMPHR	0x00AC
+
 #define LPFC_IMR_MASK_ALL	0xFFFFFFFF
 #define LPFC_ISCR_CLEAR_ALL	0xFFFFFFFF
 
@@ -569,14 +620,21 @@
 #define LPFC_SLI4_INTR30		BIT30
 #define LPFC_SLI4_INTR31		BIT31
 
-/* BAR2 Registers */
+/*
+ * The Doorbell registers defined here exist in different BAR
+ * register sets depending on the UCNA Port's reported if_type
+ * value.  For UCNA ports running SLI4 and if_type 0, they reside in
+ * BAR4.  For UCNA ports running SLI4 and if_type 2, they reside in
+ * BAR0.  The offsets are the same so the driver must account for
+ * any base address difference.
+ */
 #define LPFC_RQ_DOORBELL		0x00A0
 #define lpfc_rq_doorbell_num_posted_SHIFT	16
 #define lpfc_rq_doorbell_num_posted_MASK	0x3FFF
 #define lpfc_rq_doorbell_num_posted_WORD	word0
 #define LPFC_RQ_POST_BATCH		8	/* RQEs to post at one time */
 #define lpfc_rq_doorbell_id_SHIFT		0
-#define lpfc_rq_doorbell_id_MASK		0x03FF
+#define lpfc_rq_doorbell_id_MASK		0xFFFF
 #define lpfc_rq_doorbell_id_WORD		word0
 
 #define LPFC_WQ_DOORBELL		0x0040
@@ -591,6 +649,11 @@
 #define lpfc_wq_doorbell_id_WORD		word0
 
 #define LPFC_EQCQ_DOORBELL		0x0120
+#define lpfc_eqcq_doorbell_se_SHIFT		31
+#define lpfc_eqcq_doorbell_se_MASK		0x0001
+#define lpfc_eqcq_doorbell_se_WORD		word0
+#define LPFC_EQCQ_SOLICIT_ENABLE_OFF	0
+#define LPFC_EQCQ_SOLICIT_ENABLE_ON	1
 #define lpfc_eqcq_doorbell_arm_SHIFT		29
 #define lpfc_eqcq_doorbell_arm_MASK		0x0001
 #define lpfc_eqcq_doorbell_arm_WORD		word0
@@ -628,7 +691,7 @@
 #define lpfc_mq_doorbell_num_posted_MASK	0x3FFF
 #define lpfc_mq_doorbell_num_posted_WORD	word0
 #define lpfc_mq_doorbell_id_SHIFT		0
-#define lpfc_mq_doorbell_id_MASK		0x03FF
+#define lpfc_mq_doorbell_id_MASK		0xFFFF
 #define lpfc_mq_doorbell_id_WORD		word0
 
 struct lpfc_sli4_cfg_mhdr {
@@ -1048,12 +1111,18 @@
 #define lpfc_mbx_mq_create_ext_async_evt_link_SHIFT	LPFC_TRAILER_CODE_LINK
 #define lpfc_mbx_mq_create_ext_async_evt_link_MASK	0x00000001
 #define lpfc_mbx_mq_create_ext_async_evt_link_WORD	async_evt_bmap
-#define lpfc_mbx_mq_create_ext_async_evt_fcfste_SHIFT	LPFC_TRAILER_CODE_FCOE
-#define lpfc_mbx_mq_create_ext_async_evt_fcfste_MASK	0x00000001
-#define lpfc_mbx_mq_create_ext_async_evt_fcfste_WORD	async_evt_bmap
+#define lpfc_mbx_mq_create_ext_async_evt_fip_SHIFT	LPFC_TRAILER_CODE_FCOE
+#define lpfc_mbx_mq_create_ext_async_evt_fip_MASK	0x00000001
+#define lpfc_mbx_mq_create_ext_async_evt_fip_WORD	async_evt_bmap
 #define lpfc_mbx_mq_create_ext_async_evt_group5_SHIFT	LPFC_TRAILER_CODE_GRP5
 #define lpfc_mbx_mq_create_ext_async_evt_group5_MASK	0x00000001
 #define lpfc_mbx_mq_create_ext_async_evt_group5_WORD	async_evt_bmap
+#define lpfc_mbx_mq_create_ext_async_evt_fc_SHIFT	LPFC_TRAILER_CODE_FC
+#define lpfc_mbx_mq_create_ext_async_evt_fc_MASK	0x00000001
+#define lpfc_mbx_mq_create_ext_async_evt_fc_WORD	async_evt_bmap
+#define lpfc_mbx_mq_create_ext_async_evt_sli_SHIFT	LPFC_TRAILER_CODE_SLI
+#define lpfc_mbx_mq_create_ext_async_evt_sli_MASK	0x00000001
+#define lpfc_mbx_mq_create_ext_async_evt_sli_WORD	async_evt_bmap
 			struct mq_context context;
 			struct dma_address page[LPFC_MAX_MQ_PAGE];
 		} request;
@@ -1307,7 +1376,7 @@
 #define lpfc_function_mode_dal_WORD		function_mode
 #define lpfc_function_mode_lro_SHIFT		9
 #define lpfc_function_mode_lro_MASK		0x00000001
-#define lpfc_function_mode_lro_WORD		function_mode9
+#define lpfc_function_mode_lro_WORD		function_mode
 #define lpfc_function_mode_flex10_SHIFT		10
 #define lpfc_function_mode_flex10_MASK		0x00000001
 #define lpfc_function_mode_flex10_WORD		function_mode
@@ -1358,10 +1427,16 @@
 #define lpfc_init_vfi_vf_SHIFT		29
 #define lpfc_init_vfi_vf_MASK		0x00000001
 #define lpfc_init_vfi_vf_WORD		word1
+#define lpfc_init_vfi_vp_SHIFT		28
+#define lpfc_init_vfi_vp_MASK		0x00000001
+#define lpfc_init_vfi_vp_WORD		word1
 #define lpfc_init_vfi_vfi_SHIFT		0
 #define lpfc_init_vfi_vfi_MASK		0x0000FFFF
 #define lpfc_init_vfi_vfi_WORD		word1
 	uint32_t word2;
+#define lpfc_init_vfi_vpi_SHIFT		16
+#define lpfc_init_vfi_vpi_MASK		0x0000FFFF
+#define lpfc_init_vfi_vpi_WORD		word2
 #define lpfc_init_vfi_fcfi_SHIFT	0
 #define lpfc_init_vfi_fcfi_MASK		0x0000FFFF
 #define lpfc_init_vfi_fcfi_WORD		word2
@@ -2069,6 +2144,8 @@
 #define LPFC_TRAILER_CODE_FCOE	0x2
 #define LPFC_TRAILER_CODE_DCBX	0x3
 #define LPFC_TRAILER_CODE_GRP5	0x5
+#define LPFC_TRAILER_CODE_FC	0x10
+#define LPFC_TRAILER_CODE_SLI	0x11
 };
 
 struct lpfc_acqe_link {
@@ -2094,11 +2171,12 @@
 #define LPFC_ASYNC_LINK_STATUS_UP		0x1
 #define LPFC_ASYNC_LINK_STATUS_LOGICAL_DOWN	0x2
 #define LPFC_ASYNC_LINK_STATUS_LOGICAL_UP	0x3
-#define lpfc_acqe_link_physical_SHIFT		0
-#define lpfc_acqe_link_physical_MASK		0x000000FF
-#define lpfc_acqe_link_physical_WORD		word0
-#define LPFC_ASYNC_LINK_PORT_A			0x0
-#define LPFC_ASYNC_LINK_PORT_B			0x1
+#define lpfc_acqe_link_type_SHIFT		6
+#define lpfc_acqe_link_type_MASK		0x00000003
+#define lpfc_acqe_link_type_WORD		word0
+#define lpfc_acqe_link_number_SHIFT		0
+#define lpfc_acqe_link_number_MASK		0x0000003F
+#define lpfc_acqe_link_number_WORD		word0
 	uint32_t word1;
 #define lpfc_acqe_link_fault_SHIFT	0
 #define lpfc_acqe_link_fault_MASK	0x000000FF
@@ -2106,29 +2184,31 @@
 #define LPFC_ASYNC_LINK_FAULT_NONE	0x0
 #define LPFC_ASYNC_LINK_FAULT_LOCAL	0x1
 #define LPFC_ASYNC_LINK_FAULT_REMOTE	0x2
-#define lpfc_acqe_qos_link_speed_SHIFT	16
-#define lpfc_acqe_qos_link_speed_MASK	0x0000FFFF
-#define lpfc_acqe_qos_link_speed_WORD	word1
+#define lpfc_acqe_logical_link_speed_SHIFT	16
+#define lpfc_acqe_logical_link_speed_MASK	0x0000FFFF
+#define lpfc_acqe_logical_link_speed_WORD	word1
 	uint32_t event_tag;
 	uint32_t trailer;
+#define LPFC_LINK_EVENT_TYPE_PHYSICAL	0x0
+#define LPFC_LINK_EVENT_TYPE_VIRTUAL	0x1
 };
 
-struct lpfc_acqe_fcoe {
+struct lpfc_acqe_fip {
 	uint32_t index;
 	uint32_t word1;
-#define lpfc_acqe_fcoe_fcf_count_SHIFT		0
-#define lpfc_acqe_fcoe_fcf_count_MASK		0x0000FFFF
-#define lpfc_acqe_fcoe_fcf_count_WORD		word1
-#define lpfc_acqe_fcoe_event_type_SHIFT		16
-#define lpfc_acqe_fcoe_event_type_MASK		0x0000FFFF
-#define lpfc_acqe_fcoe_event_type_WORD		word1
-#define LPFC_FCOE_EVENT_TYPE_NEW_FCF		0x1
-#define LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL	0x2
-#define LPFC_FCOE_EVENT_TYPE_FCF_DEAD		0x3
-#define LPFC_FCOE_EVENT_TYPE_CVL		0x4
-#define LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD	0x5
+#define lpfc_acqe_fip_fcf_count_SHIFT		0
+#define lpfc_acqe_fip_fcf_count_MASK		0x0000FFFF
+#define lpfc_acqe_fip_fcf_count_WORD		word1
+#define lpfc_acqe_fip_event_type_SHIFT		16
+#define lpfc_acqe_fip_event_type_MASK		0x0000FFFF
+#define lpfc_acqe_fip_event_type_WORD		word1
 	uint32_t event_tag;
 	uint32_t trailer;
+#define LPFC_FIP_EVENT_TYPE_NEW_FCF		0x1
+#define LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL	0x2
+#define LPFC_FIP_EVENT_TYPE_FCF_DEAD		0x3
+#define LPFC_FIP_EVENT_TYPE_CVL			0x4
+#define LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD	0x5
 };
 
 struct lpfc_acqe_dcbx {
@@ -2140,9 +2220,12 @@
 
 struct lpfc_acqe_grp5 {
 	uint32_t word0;
-#define lpfc_acqe_grp5_pport_SHIFT	0
-#define lpfc_acqe_grp5_pport_MASK	0x000000FF
-#define lpfc_acqe_grp5_pport_WORD	word0
+#define lpfc_acqe_grp5_type_SHIFT		6
+#define lpfc_acqe_grp5_type_MASK		0x00000003
+#define lpfc_acqe_grp5_type_WORD		word0
+#define lpfc_acqe_grp5_number_SHIFT		0
+#define lpfc_acqe_grp5_number_MASK		0x0000003F
+#define lpfc_acqe_grp5_number_WORD		word0
 	uint32_t word1;
 #define lpfc_acqe_grp5_llink_spd_SHIFT	16
 #define lpfc_acqe_grp5_llink_spd_MASK	0x0000FFFF
@@ -2151,6 +2234,68 @@
 	uint32_t trailer;
 };
 
+struct lpfc_acqe_fc_la {
+	uint32_t word0;
+#define lpfc_acqe_fc_la_speed_SHIFT		24
+#define lpfc_acqe_fc_la_speed_MASK		0x000000FF
+#define lpfc_acqe_fc_la_speed_WORD		word0
+#define LPFC_FC_LA_SPEED_UNKOWN		0x0
+#define LPFC_FC_LA_SPEED_1G		0x1
+#define LPFC_FC_LA_SPEED_2G		0x2
+#define LPFC_FC_LA_SPEED_4G		0x4
+#define LPFC_FC_LA_SPEED_8G		0x8
+#define LPFC_FC_LA_SPEED_10G		0xA
+#define LPFC_FC_LA_SPEED_16G		0x10
+#define lpfc_acqe_fc_la_topology_SHIFT		16
+#define lpfc_acqe_fc_la_topology_MASK		0x000000FF
+#define lpfc_acqe_fc_la_topology_WORD		word0
+#define LPFC_FC_LA_TOP_UNKOWN		0x0
+#define LPFC_FC_LA_TOP_P2P		0x1
+#define LPFC_FC_LA_TOP_FCAL		0x2
+#define LPFC_FC_LA_TOP_INTERNAL_LOOP	0x3
+#define LPFC_FC_LA_TOP_SERDES_LOOP	0x4
+#define lpfc_acqe_fc_la_att_type_SHIFT		8
+#define lpfc_acqe_fc_la_att_type_MASK		0x000000FF
+#define lpfc_acqe_fc_la_att_type_WORD		word0
+#define LPFC_FC_LA_TYPE_LINK_UP		0x1
+#define LPFC_FC_LA_TYPE_LINK_DOWN	0x2
+#define LPFC_FC_LA_TYPE_NO_HARD_ALPA	0x3
+#define lpfc_acqe_fc_la_port_type_SHIFT		6
+#define lpfc_acqe_fc_la_port_type_MASK		0x00000003
+#define lpfc_acqe_fc_la_port_type_WORD		word0
+#define LPFC_LINK_TYPE_ETHERNET		0x0
+#define LPFC_LINK_TYPE_FC		0x1
+#define lpfc_acqe_fc_la_port_number_SHIFT	0
+#define lpfc_acqe_fc_la_port_number_MASK	0x0000003F
+#define lpfc_acqe_fc_la_port_number_WORD	word0
+	uint32_t word1;
+#define lpfc_acqe_fc_la_llink_spd_SHIFT		16
+#define lpfc_acqe_fc_la_llink_spd_MASK		0x0000FFFF
+#define lpfc_acqe_fc_la_llink_spd_WORD		word1
+#define lpfc_acqe_fc_la_fault_SHIFT		0
+#define lpfc_acqe_fc_la_fault_MASK		0x000000FF
+#define lpfc_acqe_fc_la_fault_WORD		word1
+#define LPFC_FC_LA_FAULT_NONE		0x0
+#define LPFC_FC_LA_FAULT_LOCAL		0x1
+#define LPFC_FC_LA_FAULT_REMOTE		0x2
+	uint32_t event_tag;
+	uint32_t trailer;
+#define LPFC_FC_LA_EVENT_TYPE_FC_LINK		0x1
+#define LPFC_FC_LA_EVENT_TYPE_SHARED_LINK	0x2
+};
+
+struct lpfc_acqe_sli {
+	uint32_t event_data1;
+	uint32_t event_data2;
+	uint32_t reserved;
+	uint32_t trailer;
+#define LPFC_SLI_EVENT_TYPE_PORT_ERROR		0x1
+#define LPFC_SLI_EVENT_TYPE_OVER_TEMP		0x2
+#define LPFC_SLI_EVENT_TYPE_NORM_TEMP		0x3
+#define LPFC_SLI_EVENT_TYPE_NVLOG_POST		0x4
+#define LPFC_SLI_EVENT_TYPE_DIAG_DUMP		0x5
+};
+
 /*
  * Define the bootstrap mailbox (bmbx) region used to communicate
  * mailbox command between the host and port. The mailbox consists
@@ -2210,7 +2355,7 @@
 #define wqe_rcvoxid_WORD      word9
 	uint32_t word10;
 #define wqe_ebde_cnt_SHIFT    0
-#define wqe_ebde_cnt_MASK     0x00000007
+#define wqe_ebde_cnt_MASK     0x0000000f
 #define wqe_ebde_cnt_WORD     word10
 #define wqe_lenloc_SHIFT      7
 #define wqe_lenloc_MASK       0x00000003
@@ -2402,7 +2547,6 @@
 	uint32_t relative_offset;
 	struct wqe_rctl_dfctl wge_ctl;
 	struct wqe_common wqe_com; /* words 6-11 */
-	/* Note: word10 different REVISIT */
 	uint32_t xmit_len;
 	uint32_t rsvd_12_15[3];
 };
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b306579..462242d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -446,23 +446,25 @@
 	/* Get the default values for Model Name and Description */
 	lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc);
 
-	if ((phba->cfg_link_speed > LINK_SPEED_10G)
-	    || ((phba->cfg_link_speed == LINK_SPEED_1G)
+	if ((phba->cfg_link_speed > LPFC_USER_LINK_SPEED_16G)
+	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_1G)
 		&& !(phba->lmt & LMT_1Gb))
-	    || ((phba->cfg_link_speed == LINK_SPEED_2G)
+	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_2G)
 		&& !(phba->lmt & LMT_2Gb))
-	    || ((phba->cfg_link_speed == LINK_SPEED_4G)
+	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_4G)
 		&& !(phba->lmt & LMT_4Gb))
-	    || ((phba->cfg_link_speed == LINK_SPEED_8G)
+	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_8G)
 		&& !(phba->lmt & LMT_8Gb))
-	    || ((phba->cfg_link_speed == LINK_SPEED_10G)
-		&& !(phba->lmt & LMT_10Gb))) {
+	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G)
+		&& !(phba->lmt & LMT_10Gb))
+	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G)
+		&& !(phba->lmt & LMT_16Gb))) {
 		/* Reset link speed to auto */
 		lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
 			"1302 Invalid speed for this board: "
 			"Reset link speed to auto: x%x\n",
 			phba->cfg_link_speed);
-			phba->cfg_link_speed = LINK_SPEED_AUTO;
+			phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
 	}
 
 	phba->link_state = LPFC_LINK_DOWN;
@@ -648,22 +650,23 @@
 	mb = &pmb->u.mb;
 	pmb->vport = vport;
 
-	lpfc_init_link(phba, pmb, phba->cfg_topology,
-		phba->cfg_link_speed);
+	lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
 	pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 	lpfc_set_loopback_flag(phba);
 	rc = lpfc_sli_issue_mbox(phba, pmb, flag);
-	if (rc != MBX_SUCCESS) {
+	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 			"0498 Adapter failed to init, mbxCmd x%x "
 			"INIT_LINK, mbxStatus x%x\n",
 			mb->mbxCommand, mb->mbxStatus);
-		/* Clear all interrupt enable conditions */
-		writel(0, phba->HCregaddr);
-		readl(phba->HCregaddr); /* flush */
-		/* Clear all pending interrupts */
-		writel(0xffffffff, phba->HAregaddr);
-		readl(phba->HAregaddr); /* flush */
+		if (phba->sli_rev <= LPFC_SLI_REV3) {
+			/* Clear all interrupt enable conditions */
+			writel(0, phba->HCregaddr);
+			readl(phba->HCregaddr); /* flush */
+			/* Clear all pending interrupts */
+			writel(0xffffffff, phba->HAregaddr);
+			readl(phba->HAregaddr); /* flush */
+		}
 		phba->link_state = LPFC_HBA_ERROR;
 		if (rc != MBX_BUSY || flag == MBX_POLL)
 			mempool_free(pmb, phba->mbox_mem_pool);
@@ -927,6 +930,35 @@
 }
 
 /**
+ * lpfc_rrq_timeout - The RRQ-timer timeout handler
+ * @ptr: unsigned long holds the pointer to lpfc hba data structure.
+ *
+ * This is the RRQ-timer timeout handler registered to the lpfc driver. When
+ * this timer fires, a RRQ timeout event shall be posted to the lpfc driver
+ * work-port-events bitmap and the worker thread is notified. This timeout
+ * event will be used by the worker thread to invoke the actual timeout
+ * handler routine, lpfc_rrq_handler. Any periodical operations will
+ * be performed in the timeout handler and the RRQ timeout event bit shall
+ * be cleared by the worker thread after it has taken the event bitmap out.
+ **/
+static void
+lpfc_rrq_timeout(unsigned long ptr)
+{
+	struct lpfc_hba *phba;
+	uint32_t tmo_posted;
+	unsigned long iflag;
+
+	phba = (struct lpfc_hba *)ptr;
+	spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
+	tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE;
+	if (!tmo_posted)
+		phba->hba_flag |= HBA_RRQ_ACTIVE;
+	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+	if (!tmo_posted)
+		lpfc_worker_wake_up(phba);
+}
+
+/**
  * lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function
  * @phba: pointer to lpfc hba data structure.
  * @pmboxq: pointer to the driver internal queue element for mailbox command.
@@ -1374,6 +1406,8 @@
 	struct lpfc_vport *vport = phba->pport;
 	uint32_t event_data;
 	struct Scsi_Host *shost;
+	uint32_t if_type;
+	struct lpfc_register portstat_reg;
 
 	/* If the pci channel is offline, ignore possible errors, since
 	 * we cannot communicate with the pci card anyway.
@@ -1390,17 +1424,49 @@
 	/* For now, the actual action for SLI4 device handling is not
 	 * specified yet, just treated it as adaptor hardware failure
 	 */
-	lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-			"0143 SLI4 Adapter Hardware Error Data: x%x x%x\n",
-			phba->work_status[0], phba->work_status[1]);
-
 	event_data = FC_REG_DUMP_EVENT;
 	shost = lpfc_shost_from_vport(vport);
 	fc_host_post_vendor_event(shost, fc_get_event_number(),
 				  sizeof(event_data), (char *) &event_data,
 				  SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
 
-	lpfc_sli4_offline_eratt(phba);
+	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+	switch (if_type) {
+	case LPFC_SLI_INTF_IF_TYPE_0:
+		lpfc_sli4_offline_eratt(phba);
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_2:
+		portstat_reg.word0 =
+			readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
+
+		if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) {
+			/* TODO: Register for Overtemp async events. */
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+				"2889 Port Overtemperature event, "
+				"taking port\n");
+			spin_lock_irq(&phba->hbalock);
+			phba->over_temp_state = HBA_OVER_TEMP;
+			spin_unlock_irq(&phba->hbalock);
+			lpfc_sli4_offline_eratt(phba);
+			return;
+		}
+		if (bf_get(lpfc_sliport_status_rn, &portstat_reg)) {
+			/*
+			 * TODO: Attempt port recovery via a port reset.
+			 * When fully implemented, the driver should
+			 * attempt to recover the port here and return.
+			 * For now, log an error and take the port offline.
+			 */
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"2887 Port Error: Attempting "
+					"Port Recovery\n");
+		}
+		lpfc_sli4_offline_eratt(phba);
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_1:
+	default:
+		break;
+	}
 }
 
 /**
@@ -1459,8 +1525,8 @@
 	lpfc_els_flush_all_cmd(phba);
 
 	psli->slistat.link_event++;
-	lpfc_read_la(phba, pmb, mp);
-	pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
+	lpfc_read_topology(phba, pmb, mp);
+	pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
 	pmb->vport = vport;
 	/* Block ELS IOCBs until we have processed this mbox command */
 	phba->sli.ring[LPFC_ELS_RING].flag |= LPFC_STOP_IOCB_EVENT;
@@ -1853,6 +1919,14 @@
 		m = (typeof(m)){"LPVe12002", "PCIe Shared I/O",
 				"Fibre Channel Adapter"};
 		break;
+	case PCI_DEVICE_ID_LANCER_FC:
+		oneConnect = 1;
+		m = (typeof(m)){"Undefined", "PCIe", "Fibre Channel Adapter"};
+		break;
+	case PCI_DEVICE_ID_LANCER_FCOE:
+		oneConnect = 1;
+		m = (typeof(m)){"Undefined", "PCIe", "FCoE"};
+		break;
 	default:
 		m = (typeof(m)){"Unknown", "", ""};
 		break;
@@ -2943,63 +3017,6 @@
 }
 
 /**
- * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support
- * @phba: pointer to lpfc hba data structure.
- *
- * This function uses the QUERY_FW_CFG mailbox command to determine if the
- * firmware loaded supports FCoE. A return of zero indicates that the mailbox
- * was successful and the firmware supports FCoE. Any other return indicates
- * a error. It is assumed that this function will be called before interrupts
- * are enabled.
- **/
-static int
-lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba)
-{
-	int rc = 0;
-	LPFC_MBOXQ_t *mboxq;
-	struct lpfc_mbx_query_fw_cfg *query_fw_cfg;
-	uint32_t length;
-	uint32_t shdr_status, shdr_add_status;
-
-	mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mboxq) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"2621 Failed to allocate mbox for "
-				"query firmware config cmd\n");
-		return -ENOMEM;
-	}
-	query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg;
-	length = (sizeof(struct lpfc_mbx_query_fw_cfg) -
-		  sizeof(struct lpfc_sli4_cfg_mhdr));
-	lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
-			 LPFC_MBOX_OPCODE_QUERY_FW_CFG,
-			 length, LPFC_SLI4_MBX_EMBED);
-	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr_status = bf_get(lpfc_mbox_hdr_status,
-			     &query_fw_cfg->header.cfg_shdr.response);
-	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
-				 &query_fw_cfg->header.cfg_shdr.response);
-	if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2622 Query Firmware Config failed "
-				"mbx status x%x, status x%x add_status x%x\n",
-				rc, shdr_status, shdr_add_status);
-		return -EINVAL;
-	}
-	if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2623 FCoE Function not supported by firmware. "
-				"Function mode = %08x\n",
-				query_fw_cfg->function_mode);
-		return -EINVAL;
-	}
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mboxq, phba->mbox_mem_pool);
-	return 0;
-}
-
-/**
  * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code
  * @phba: pointer to lpfc hba data structure.
  * @acqe_link: pointer to the async link completion queue entry.
@@ -3051,20 +3068,20 @@
 	switch (bf_get(lpfc_acqe_link_status, acqe_link)) {
 	case LPFC_ASYNC_LINK_STATUS_DOWN:
 	case LPFC_ASYNC_LINK_STATUS_LOGICAL_DOWN:
-		att_type = AT_LINK_DOWN;
+		att_type = LPFC_ATT_LINK_DOWN;
 		break;
 	case LPFC_ASYNC_LINK_STATUS_UP:
 		/* Ignore physical link up events - wait for logical link up */
-		att_type = AT_RESERVED;
+		att_type = LPFC_ATT_RESERVED;
 		break;
 	case LPFC_ASYNC_LINK_STATUS_LOGICAL_UP:
-		att_type = AT_LINK_UP;
+		att_type = LPFC_ATT_LINK_UP;
 		break;
 	default:
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"0399 Invalid link attention type: x%x\n",
 				bf_get(lpfc_acqe_link_status, acqe_link));
-		att_type = AT_RESERVED;
+		att_type = LPFC_ATT_RESERVED;
 		break;
 	}
 	return att_type;
@@ -3088,36 +3105,32 @@
 
 	switch (bf_get(lpfc_acqe_link_speed, acqe_link)) {
 	case LPFC_ASYNC_LINK_SPEED_ZERO:
-		link_speed = LA_UNKNW_LINK;
-		break;
 	case LPFC_ASYNC_LINK_SPEED_10MBPS:
-		link_speed = LA_UNKNW_LINK;
-		break;
 	case LPFC_ASYNC_LINK_SPEED_100MBPS:
-		link_speed = LA_UNKNW_LINK;
+		link_speed = LPFC_LINK_SPEED_UNKNOWN;
 		break;
 	case LPFC_ASYNC_LINK_SPEED_1GBPS:
-		link_speed = LA_1GHZ_LINK;
+		link_speed = LPFC_LINK_SPEED_1GHZ;
 		break;
 	case LPFC_ASYNC_LINK_SPEED_10GBPS:
-		link_speed = LA_10GHZ_LINK;
+		link_speed = LPFC_LINK_SPEED_10GHZ;
 		break;
 	default:
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
 				"0483 Invalid link-attention link speed: x%x\n",
 				bf_get(lpfc_acqe_link_speed, acqe_link));
-		link_speed = LA_UNKNW_LINK;
+		link_speed = LPFC_LINK_SPEED_UNKNOWN;
 		break;
 	}
 	return link_speed;
 }
 
 /**
- * lpfc_sli4_async_link_evt - Process the asynchronous link event
+ * lpfc_sli4_async_link_evt - Process the asynchronous FCoE link event
  * @phba: pointer to lpfc hba data structure.
  * @acqe_link: pointer to the async link completion queue entry.
  *
- * This routine is to handle the SLI4 asynchronous link event.
+ * This routine is to handle the SLI4 asynchronous FCoE link event.
  **/
 static void
 lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
@@ -3126,11 +3139,12 @@
 	struct lpfc_dmabuf *mp;
 	LPFC_MBOXQ_t *pmb;
 	MAILBOX_t *mb;
-	READ_LA_VAR *la;
+	struct lpfc_mbx_read_top *la;
 	uint8_t att_type;
+	int rc;
 
 	att_type = lpfc_sli4_parse_latt_type(phba, acqe_link);
-	if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP)
+	if (att_type != LPFC_ATT_LINK_DOWN && att_type != LPFC_ATT_LINK_UP)
 		return;
 	phba->fcoe_eventtag = acqe_link->event_tag;
 	pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -3161,28 +3175,11 @@
 	/* Update link event statistics */
 	phba->sli.slistat.link_event++;
 
-	/* Create pseudo lpfc_handle_latt mailbox command from link ACQE */
-	lpfc_read_la(phba, pmb, mp);
+	/* Create lpfc_handle_latt mailbox command from link ACQE */
+	lpfc_read_topology(phba, pmb, mp);
+	pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
 	pmb->vport = phba->pport;
 
-	/* Parse and translate status field */
-	mb = &pmb->u.mb;
-	mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba, acqe_link);
-
-	/* Parse and translate link attention fields */
-	la = (READ_LA_VAR *) &pmb->u.mb.un.varReadLA;
-	la->eventTag = acqe_link->event_tag;
-	la->attType = att_type;
-	la->UlnkSpeed = lpfc_sli4_parse_latt_link_speed(phba, acqe_link);
-
-	/* Fake the the following irrelvant fields */
-	la->topology = TOPOLOGY_PT_PT;
-	la->granted_AL_PA = 0;
-	la->il = 0;
-	la->pb = 0;
-	la->fa = 0;
-	la->mm = 0;
-
 	/* Keep the link status for extra SLI4 state machine reference */
 	phba->sli4_hba.link_state.speed =
 				bf_get(lpfc_acqe_link_speed, acqe_link);
@@ -3190,15 +3187,61 @@
 				bf_get(lpfc_acqe_link_duplex, acqe_link);
 	phba->sli4_hba.link_state.status =
 				bf_get(lpfc_acqe_link_status, acqe_link);
-	phba->sli4_hba.link_state.physical =
-				bf_get(lpfc_acqe_link_physical, acqe_link);
+	phba->sli4_hba.link_state.type =
+				bf_get(lpfc_acqe_link_type, acqe_link);
+	phba->sli4_hba.link_state.number =
+				bf_get(lpfc_acqe_link_number, acqe_link);
 	phba->sli4_hba.link_state.fault =
 				bf_get(lpfc_acqe_link_fault, acqe_link);
 	phba->sli4_hba.link_state.logical_speed =
-				bf_get(lpfc_acqe_qos_link_speed, acqe_link);
+			bf_get(lpfc_acqe_logical_link_speed, acqe_link);
+	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+			"2900 Async FCoE Link event - Speed:%dGBit duplex:x%x "
+			"LA Type:x%x Port Type:%d Port Number:%d Logical "
+			"speed:%dMbps Fault:%d\n",
+			phba->sli4_hba.link_state.speed,
+			phba->sli4_hba.link_state.topology,
+			phba->sli4_hba.link_state.status,
+			phba->sli4_hba.link_state.type,
+			phba->sli4_hba.link_state.number,
+			phba->sli4_hba.link_state.logical_speed * 10,
+			phba->sli4_hba.link_state.fault);
+	/*
+	 * For FC Mode: issue the READ_TOPOLOGY mailbox command to fetch
+	 * topology info. Note: Optional for non FC-AL ports.
+	 */
+	if (!(phba->hba_flag & HBA_FCOE_MODE)) {
+		rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+		if (rc == MBX_NOT_FINISHED)
+			goto out_free_dmabuf;
+		return;
+	}
+	/*
+	 * For FCoE Mode: fill in all the topology information we need and call
+	 * the READ_TOPOLOGY completion routine to continue without actually
+	 * sending the READ_TOPOLOGY mailbox command to the port.
+	 */
+	/* Parse and translate status field */
+	mb = &pmb->u.mb;
+	mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba, acqe_link);
+
+	/* Parse and translate link attention fields */
+	la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop;
+	la->eventTag = acqe_link->event_tag;
+	bf_set(lpfc_mbx_read_top_att_type, la, att_type);
+	bf_set(lpfc_mbx_read_top_link_spd, la,
+	       lpfc_sli4_parse_latt_link_speed(phba, acqe_link));
+
+	/* Fake the the following irrelvant fields */
+	bf_set(lpfc_mbx_read_top_topology, la, LPFC_TOPOLOGY_PT_PT);
+	bf_set(lpfc_mbx_read_top_alpa_granted, la, 0);
+	bf_set(lpfc_mbx_read_top_il, la, 0);
+	bf_set(lpfc_mbx_read_top_pb, la, 0);
+	bf_set(lpfc_mbx_read_top_fa, la, 0);
+	bf_set(lpfc_mbx_read_top_mm, la, 0);
 
 	/* Invoke the lpfc_handle_latt mailbox command callback function */
-	lpfc_mbx_cmpl_read_la(phba, pmb);
+	lpfc_mbx_cmpl_read_topology(phba, pmb);
 
 	return;
 
@@ -3209,6 +3252,118 @@
 }
 
 /**
+ * lpfc_sli4_async_fc_evt - Process the asynchronous FC link event
+ * @phba: pointer to lpfc hba data structure.
+ * @acqe_fc: pointer to the async fc completion queue entry.
+ *
+ * This routine is to handle the SLI4 asynchronous FC event. It will simply log
+ * that the event was received and then issue a read_topology mailbox command so
+ * that the rest of the driver will treat it the same as SLI3.
+ **/
+static void
+lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
+{
+	struct lpfc_dmabuf *mp;
+	LPFC_MBOXQ_t *pmb;
+	int rc;
+
+	if (bf_get(lpfc_trailer_type, acqe_fc) !=
+	    LPFC_FC_LA_EVENT_TYPE_FC_LINK) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+				"2895 Non FC link Event detected.(%d)\n",
+				bf_get(lpfc_trailer_type, acqe_fc));
+		return;
+	}
+	/* Keep the link status for extra SLI4 state machine reference */
+	phba->sli4_hba.link_state.speed =
+				bf_get(lpfc_acqe_fc_la_speed, acqe_fc);
+	phba->sli4_hba.link_state.duplex = LPFC_ASYNC_LINK_DUPLEX_FULL;
+	phba->sli4_hba.link_state.topology =
+				bf_get(lpfc_acqe_fc_la_topology, acqe_fc);
+	phba->sli4_hba.link_state.status =
+				bf_get(lpfc_acqe_fc_la_att_type, acqe_fc);
+	phba->sli4_hba.link_state.type =
+				bf_get(lpfc_acqe_fc_la_port_type, acqe_fc);
+	phba->sli4_hba.link_state.number =
+				bf_get(lpfc_acqe_fc_la_port_number, acqe_fc);
+	phba->sli4_hba.link_state.fault =
+				bf_get(lpfc_acqe_link_fault, acqe_fc);
+	phba->sli4_hba.link_state.logical_speed =
+				bf_get(lpfc_acqe_fc_la_llink_spd, acqe_fc);
+	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+			"2896 Async FC event - Speed:%dGBaud Topology:x%x "
+			"LA Type:x%x Port Type:%d Port Number:%d Logical speed:"
+			"%dMbps Fault:%d\n",
+			phba->sli4_hba.link_state.speed,
+			phba->sli4_hba.link_state.topology,
+			phba->sli4_hba.link_state.status,
+			phba->sli4_hba.link_state.type,
+			phba->sli4_hba.link_state.number,
+			phba->sli4_hba.link_state.logical_speed * 10,
+			phba->sli4_hba.link_state.fault);
+	pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!pmb) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+				"2897 The mboxq allocation failed\n");
+		return;
+	}
+	mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+	if (!mp) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+				"2898 The lpfc_dmabuf allocation failed\n");
+		goto out_free_pmb;
+	}
+	mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
+	if (!mp->virt) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+				"2899 The mbuf allocation failed\n");
+		goto out_free_dmabuf;
+	}
+
+	/* Cleanup any outstanding ELS commands */
+	lpfc_els_flush_all_cmd(phba);
+
+	/* Block ELS IOCBs until we have done process link event */
+	phba->sli.ring[LPFC_ELS_RING].flag |= LPFC_STOP_IOCB_EVENT;
+
+	/* Update link event statistics */
+	phba->sli.slistat.link_event++;
+
+	/* Create lpfc_handle_latt mailbox command from link ACQE */
+	lpfc_read_topology(phba, pmb, mp);
+	pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
+	pmb->vport = phba->pport;
+
+	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+	if (rc == MBX_NOT_FINISHED)
+		goto out_free_dmabuf;
+	return;
+
+out_free_dmabuf:
+	kfree(mp);
+out_free_pmb:
+	mempool_free(pmb, phba->mbox_mem_pool);
+}
+
+/**
+ * lpfc_sli4_async_sli_evt - Process the asynchronous SLI link event
+ * @phba: pointer to lpfc hba data structure.
+ * @acqe_fc: pointer to the async SLI completion queue entry.
+ *
+ * This routine is to handle the SLI4 asynchronous SLI events.
+ **/
+static void
+lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
+{
+	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+			"2901 Async SLI event - Event Data1:x%08x Event Data2:"
+			"x%08x SLI Event Type:%d",
+			acqe_sli->event_data1, acqe_sli->event_data2,
+			bf_get(lpfc_trailer_type, acqe_sli));
+	return;
+}
+
+/**
  * lpfc_sli4_perform_vport_cvl - Perform clear virtual link on a vport
  * @vport: pointer to vport data structure.
  *
@@ -3247,10 +3402,12 @@
 		if (!ndlp)
 			return 0;
 	}
-	if (phba->pport->port_state < LPFC_FLOGI)
+	if ((phba->pport->port_state < LPFC_FLOGI) &&
+		(phba->pport->port_state != LPFC_VPORT_FAILED))
 		return NULL;
 	/* If virtual link is not yet instantiated ignore CVL */
-	if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC))
+	if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)
+		&& (vport->port_state != LPFC_VPORT_FAILED))
 		return NULL;
 	shost = lpfc_shost_from_vport(vport);
 	if (!shost)
@@ -3285,17 +3442,17 @@
 }
 
 /**
- * lpfc_sli4_async_fcoe_evt - Process the asynchronous fcoe event
+ * lpfc_sli4_async_fip_evt - Process the asynchronous FCoE FIP event
  * @phba: pointer to lpfc hba data structure.
  * @acqe_link: pointer to the async fcoe completion queue entry.
  *
  * This routine is to handle the SLI4 asynchronous fcoe event.
  **/
 static void
-lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
-			 struct lpfc_acqe_fcoe *acqe_fcoe)
+lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
+			struct lpfc_acqe_fip *acqe_fip)
 {
-	uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe);
+	uint8_t event_type = bf_get(lpfc_trailer_type, acqe_fip);
 	int rc;
 	struct lpfc_vport *vport;
 	struct lpfc_nodelist *ndlp;
@@ -3304,25 +3461,25 @@
 	struct lpfc_vport **vports;
 	int i;
 
-	phba->fc_eventTag = acqe_fcoe->event_tag;
-	phba->fcoe_eventtag = acqe_fcoe->event_tag;
+	phba->fc_eventTag = acqe_fip->event_tag;
+	phba->fcoe_eventtag = acqe_fip->event_tag;
 	switch (event_type) {
-	case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
-	case LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD:
-		if (event_type == LPFC_FCOE_EVENT_TYPE_NEW_FCF)
+	case LPFC_FIP_EVENT_TYPE_NEW_FCF:
+	case LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD:
+		if (event_type == LPFC_FIP_EVENT_TYPE_NEW_FCF)
 			lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
 					LOG_DISCOVERY,
 					"2546 New FCF event, evt_tag:x%x, "
 					"index:x%x\n",
-					acqe_fcoe->event_tag,
-					acqe_fcoe->index);
+					acqe_fip->event_tag,
+					acqe_fip->index);
 		else
 			lpfc_printf_log(phba, KERN_WARNING, LOG_FIP |
 					LOG_DISCOVERY,
 					"2788 FCF param modified event, "
 					"evt_tag:x%x, index:x%x\n",
-					acqe_fcoe->event_tag,
-					acqe_fcoe->index);
+					acqe_fip->event_tag,
+					acqe_fip->index);
 		if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
 			/*
 			 * During period of FCF discovery, read the FCF
@@ -3333,8 +3490,8 @@
 					LOG_DISCOVERY,
 					"2779 Read FCF (x%x) for updating "
 					"roundrobin FCF failover bmask\n",
-					acqe_fcoe->index);
-			rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index);
+					acqe_fip->index);
+			rc = lpfc_sli4_read_fcf_rec(phba, acqe_fip->index);
 		}
 
 		/* If the FCF discovery is in progress, do nothing. */
@@ -3360,7 +3517,7 @@
 		lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
 				"2770 Start FCF table scan per async FCF "
 				"event, evt_tag:x%x, index:x%x\n",
-				acqe_fcoe->event_tag, acqe_fcoe->index);
+				acqe_fip->event_tag, acqe_fip->index);
 		rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba,
 						     LPFC_FCOE_FCF_GET_FIRST);
 		if (rc)
@@ -3369,17 +3526,17 @@
 					"command failed (x%x)\n", rc);
 		break;
 
-	case LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL:
+	case LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL:
 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
 			"2548 FCF Table full count 0x%x tag 0x%x\n",
-			bf_get(lpfc_acqe_fcoe_fcf_count, acqe_fcoe),
-			acqe_fcoe->event_tag);
+			bf_get(lpfc_acqe_fip_fcf_count, acqe_fip),
+			acqe_fip->event_tag);
 		break;
 
-	case LPFC_FCOE_EVENT_TYPE_FCF_DEAD:
+	case LPFC_FIP_EVENT_TYPE_FCF_DEAD:
 		lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
 			"2549 FCF (x%x) disconnected from network, "
-			"tag:x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
+			"tag:x%x\n", acqe_fip->index, acqe_fip->event_tag);
 		/*
 		 * If we are in the middle of FCF failover process, clear
 		 * the corresponding FCF bit in the roundrobin bitmap.
@@ -3388,13 +3545,13 @@
 		if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
 			spin_unlock_irq(&phba->hbalock);
 			/* Update FLOGI FCF failover eligible FCF bmask */
-			lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index);
+			lpfc_sli4_fcf_rr_index_clear(phba, acqe_fip->index);
 			break;
 		}
 		spin_unlock_irq(&phba->hbalock);
 
 		/* If the event is not for currently used fcf do nothing */
-		if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index)
+		if (phba->fcf.current_rec.fcf_indx != acqe_fip->index)
 			break;
 
 		/*
@@ -3411,7 +3568,7 @@
 		lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY,
 				"2771 Start FCF fast failover process due to "
 				"FCF DEAD event: evt_tag:x%x, fcf_index:x%x "
-				"\n", acqe_fcoe->event_tag, acqe_fcoe->index);
+				"\n", acqe_fip->event_tag, acqe_fip->index);
 		rc = lpfc_sli4_redisc_fcf_table(phba);
 		if (rc) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
@@ -3438,12 +3595,12 @@
 			lpfc_sli4_perform_all_vport_cvl(phba);
 		}
 		break;
-	case LPFC_FCOE_EVENT_TYPE_CVL:
+	case LPFC_FIP_EVENT_TYPE_CVL:
 		lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
 			"2718 Clear Virtual Link Received for VPI 0x%x"
-			" tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
+			" tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag);
 		vport = lpfc_find_vport_by_vpid(phba,
-				acqe_fcoe->index - phba->vpi_base);
+				acqe_fip->index - phba->vpi_base);
 		ndlp = lpfc_sli4_perform_vport_cvl(vport);
 		if (!ndlp)
 			break;
@@ -3494,7 +3651,7 @@
 			lpfc_printf_log(phba, KERN_INFO, LOG_FIP |
 					LOG_DISCOVERY,
 					"2773 Start FCF failover per CVL, "
-					"evt_tag:x%x\n", acqe_fcoe->event_tag);
+					"evt_tag:x%x\n", acqe_fip->event_tag);
 			rc = lpfc_sli4_redisc_fcf_table(phba);
 			if (rc) {
 				lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
@@ -3522,7 +3679,7 @@
 	default:
 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
 			"0288 Unknown FCoE event type 0x%x event tag "
-			"0x%x\n", event_type, acqe_fcoe->event_tag);
+			"0x%x\n", event_type, acqe_fip->event_tag);
 		break;
 	}
 }
@@ -3599,8 +3756,7 @@
 						 &cq_event->cqe.acqe_link);
 			break;
 		case LPFC_TRAILER_CODE_FCOE:
-			lpfc_sli4_async_fcoe_evt(phba,
-						 &cq_event->cqe.acqe_fcoe);
+			lpfc_sli4_async_fip_evt(phba, &cq_event->cqe.acqe_fip);
 			break;
 		case LPFC_TRAILER_CODE_DCBX:
 			lpfc_sli4_async_dcbx_evt(phba,
@@ -3610,6 +3766,12 @@
 			lpfc_sli4_async_grp5_evt(phba,
 						 &cq_event->cqe.acqe_grp5);
 			break;
+		case LPFC_TRAILER_CODE_FC:
+			lpfc_sli4_async_fc_evt(phba, &cq_event->cqe.acqe_fc);
+			break;
+		case LPFC_TRAILER_CODE_SLI:
+			lpfc_sli4_async_sli_evt(phba, &cq_event->cqe.acqe_sli);
+			break;
 		default:
 			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
 					"1804 Invalid asynchrous event code: "
@@ -3948,7 +4110,7 @@
 	int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size;
 	uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
 	struct lpfc_mqe *mqe;
-	int longs;
+	int longs, sli_family;
 
 	/* Before proceed, wait for POST done and device ready */
 	rc = lpfc_sli4_post_status_check(phba);
@@ -3963,6 +4125,9 @@
 	init_timer(&phba->hb_tmofunc);
 	phba->hb_tmofunc.function = lpfc_hb_timeout;
 	phba->hb_tmofunc.data = (unsigned long)phba;
+	init_timer(&phba->rrq_tmr);
+	phba->rrq_tmr.function = lpfc_rrq_timeout;
+	phba->rrq_tmr.data = (unsigned long)phba;
 
 	psli = &phba->sli;
 	/* MBOX heartbeat timer */
@@ -4010,12 +4175,22 @@
 	 */
 	buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) +
 		    ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge)));
-	/* Feature Level 1 hardware is limited to 2 pages */
-	if ((bf_get(lpfc_sli_intf_featurelevel1, &phba->sli4_hba.sli_intf) ==
-	     LPFC_SLI_INTF_FEATURELEVEL1_1))
-		max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE;
-	else
-		max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
+
+	sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf);
+	max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
+	switch (sli_family) {
+	case LPFC_SLI_INTF_FAMILY_BE2:
+	case LPFC_SLI_INTF_FAMILY_BE3:
+		/* There is a single hint for BE - 2 pages per BPL. */
+		if (bf_get(lpfc_sli_intf_sli_hint1, &phba->sli4_hba.sli_intf) ==
+		    LPFC_SLI_INTF_SLI_HINT1_1)
+			max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE;
+		break;
+	case LPFC_SLI_INTF_FAMILY_LNCR_A0:
+	case LPFC_SLI_INTF_FAMILY_LNCR_B0:
+	default:
+		break;
+	}
 	for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE;
 	     dma_buf_size < max_buf_size && buf_size > dma_buf_size;
 	     dma_buf_size = dma_buf_size << 1)
@@ -4070,6 +4245,14 @@
 	if (rc)
 		return -ENOMEM;
 
+	/* IF Type 2 ports get initialized now. */
+	if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+	    LPFC_SLI_INTF_IF_TYPE_2) {
+		rc = lpfc_pci_function_reset(phba);
+		if (unlikely(rc))
+			return -ENODEV;
+	}
+
 	/* Create the bootstrap mailbox command */
 	rc = lpfc_create_bootstrap_mbox(phba);
 	if (unlikely(rc))
@@ -4080,19 +4263,18 @@
 	if (unlikely(rc))
 		goto out_free_bsmbx;
 
-	rc = lpfc_sli4_fw_cfg_check(phba);
-	if (unlikely(rc))
-		goto out_free_bsmbx;
-
 	/* Set up the hba's configuration parameters. */
 	rc = lpfc_sli4_read_config(phba);
 	if (unlikely(rc))
 		goto out_free_bsmbx;
 
-	/* Perform a function reset */
-	rc = lpfc_pci_function_reset(phba);
-	if (unlikely(rc))
-		goto out_free_bsmbx;
+	/* IF Type 0 ports get initialized now. */
+	if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+	    LPFC_SLI_INTF_IF_TYPE_0) {
+		rc = lpfc_pci_function_reset(phba);
+		if (unlikely(rc))
+			goto out_free_bsmbx;
+	}
 
 	mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
 						       GFP_KERNEL);
@@ -5190,97 +5372,183 @@
 int
 lpfc_sli4_post_status_check(struct lpfc_hba *phba)
 {
-	struct lpfc_register sta_reg, uerrlo_reg, uerrhi_reg;
-	int i, port_error = -ENODEV;
+	struct lpfc_register portsmphr_reg, uerrlo_reg, uerrhi_reg;
+	struct lpfc_register reg_data;
+	int i, port_error = 0;
+	uint32_t if_type;
 
-	if (!phba->sli4_hba.STAregaddr)
+	if (!phba->sli4_hba.PSMPHRregaddr)
 		return -ENODEV;
 
 	/* Wait up to 30 seconds for the SLI Port POST done and ready */
 	for (i = 0; i < 3000; i++) {
-		sta_reg.word0 = readl(phba->sli4_hba.STAregaddr);
-		/* Encounter fatal POST error, break out */
-		if (bf_get(lpfc_hst_state_perr, &sta_reg)) {
+		portsmphr_reg.word0 = readl(phba->sli4_hba.PSMPHRregaddr);
+		if (bf_get(lpfc_port_smphr_perr, &portsmphr_reg)) {
+			/* Port has a fatal POST error, break out */
 			port_error = -ENODEV;
 			break;
 		}
-		if (LPFC_POST_STAGE_ARMFW_READY ==
-		    bf_get(lpfc_hst_state_port_status, &sta_reg)) {
-			port_error = 0;
+		if (LPFC_POST_STAGE_PORT_READY ==
+		    bf_get(lpfc_port_smphr_port_status, &portsmphr_reg))
 			break;
-		}
 		msleep(10);
 	}
 
-	if (port_error)
+	/*
+	 * If there was a port error during POST, then don't proceed with
+	 * other register reads as the data may not be valid.  Just exit.
+	 */
+	if (port_error) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-			"1408 Failure HBA POST Status: sta_reg=0x%x, "
-			"perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, xrom=x%x, "
-			"dl=x%x, pstatus=x%x\n", sta_reg.word0,
-			bf_get(lpfc_hst_state_perr, &sta_reg),
-			bf_get(lpfc_hst_state_sfi, &sta_reg),
-			bf_get(lpfc_hst_state_nip, &sta_reg),
-			bf_get(lpfc_hst_state_ipc, &sta_reg),
-			bf_get(lpfc_hst_state_xrom, &sta_reg),
-			bf_get(lpfc_hst_state_dl, &sta_reg),
-			bf_get(lpfc_hst_state_port_status, &sta_reg));
-
-	/* Log device information */
-	phba->sli4_hba.sli_intf.word0 = readl(phba->sli4_hba.SLIINTFregaddr);
-	if (bf_get(lpfc_sli_intf_valid,
-		   &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_VALID) {
+			"1408 Port Failed POST - portsmphr=0x%x, "
+			"perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, scr1=x%x, "
+			"scr2=x%x, hscratch=x%x, pstatus=x%x\n",
+			portsmphr_reg.word0,
+			bf_get(lpfc_port_smphr_perr, &portsmphr_reg),
+			bf_get(lpfc_port_smphr_sfi, &portsmphr_reg),
+			bf_get(lpfc_port_smphr_nip, &portsmphr_reg),
+			bf_get(lpfc_port_smphr_ipc, &portsmphr_reg),
+			bf_get(lpfc_port_smphr_scr1, &portsmphr_reg),
+			bf_get(lpfc_port_smphr_scr2, &portsmphr_reg),
+			bf_get(lpfc_port_smphr_host_scratch, &portsmphr_reg),
+			bf_get(lpfc_port_smphr_port_status, &portsmphr_reg));
+	} else {
 		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-				"2534 Device Info: ChipType=0x%x, SliRev=0x%x, "
-				"FeatureL1=0x%x, FeatureL2=0x%x\n",
+				"2534 Device Info: SLIFamily=0x%x, "
+				"SLIRev=0x%x, IFType=0x%x, SLIHint_1=0x%x, "
+				"SLIHint_2=0x%x, FT=0x%x\n",
 				bf_get(lpfc_sli_intf_sli_family,
 				       &phba->sli4_hba.sli_intf),
 				bf_get(lpfc_sli_intf_slirev,
 				       &phba->sli4_hba.sli_intf),
-				bf_get(lpfc_sli_intf_featurelevel1,
+				bf_get(lpfc_sli_intf_if_type,
 				       &phba->sli4_hba.sli_intf),
-				bf_get(lpfc_sli_intf_featurelevel2,
+				bf_get(lpfc_sli_intf_sli_hint1,
+				       &phba->sli4_hba.sli_intf),
+				bf_get(lpfc_sli_intf_sli_hint2,
+				       &phba->sli4_hba.sli_intf),
+				bf_get(lpfc_sli_intf_func_type,
 				       &phba->sli4_hba.sli_intf));
+		/*
+		 * Check for other Port errors during the initialization
+		 * process.  Fail the load if the port did not come up
+		 * correctly.
+		 */
+		if_type = bf_get(lpfc_sli_intf_if_type,
+				 &phba->sli4_hba.sli_intf);
+		switch (if_type) {
+		case LPFC_SLI_INTF_IF_TYPE_0:
+			phba->sli4_hba.ue_mask_lo =
+			      readl(phba->sli4_hba.u.if_type0.UEMASKLOregaddr);
+			phba->sli4_hba.ue_mask_hi =
+			      readl(phba->sli4_hba.u.if_type0.UEMASKHIregaddr);
+			uerrlo_reg.word0 =
+			      readl(phba->sli4_hba.u.if_type0.UERRLOregaddr);
+			uerrhi_reg.word0 =
+				readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
+			if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) ||
+			    (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) {
+				lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+						"1422 Unrecoverable Error "
+						"Detected during POST "
+						"uerr_lo_reg=0x%x, "
+						"uerr_hi_reg=0x%x, "
+						"ue_mask_lo_reg=0x%x, "
+						"ue_mask_hi_reg=0x%x\n",
+						uerrlo_reg.word0,
+						uerrhi_reg.word0,
+						phba->sli4_hba.ue_mask_lo,
+						phba->sli4_hba.ue_mask_hi);
+				port_error = -ENODEV;
+			}
+			break;
+		case LPFC_SLI_INTF_IF_TYPE_2:
+			/* Final checks.  The port status should be clean. */
+			reg_data.word0 =
+				readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
+			if (bf_get(lpfc_sliport_status_err, &reg_data)) {
+				phba->work_status[0] =
+					readl(phba->sli4_hba.u.if_type2.
+					      ERR1regaddr);
+				phba->work_status[1] =
+					readl(phba->sli4_hba.u.if_type2.
+					      ERR2regaddr);
+				lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"2888 Port Error Detected "
+					"during POST: "
+					"port status reg 0x%x, "
+					"port_smphr reg 0x%x, "
+					"error 1=0x%x, error 2=0x%x\n",
+					reg_data.word0,
+					portsmphr_reg.word0,
+					phba->work_status[0],
+					phba->work_status[1]);
+				port_error = -ENODEV;
+			}
+			break;
+		case LPFC_SLI_INTF_IF_TYPE_1:
+		default:
+			break;
+		}
 	}
-	phba->sli4_hba.ue_mask_lo = readl(phba->sli4_hba.UEMASKLOregaddr);
-	phba->sli4_hba.ue_mask_hi = readl(phba->sli4_hba.UEMASKHIregaddr);
-	/* With uncoverable error, log the error message and return error */
-	uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr);
-	uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr);
-	if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) ||
-	    (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"1422 HBA Unrecoverable error: "
-				"uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
-				"ue_mask_lo_reg=0x%x, ue_mask_hi_reg=0x%x\n",
-				uerrlo_reg.word0, uerrhi_reg.word0,
-				phba->sli4_hba.ue_mask_lo,
-				phba->sli4_hba.ue_mask_hi);
-		return -ENODEV;
-	}
-
 	return port_error;
 }
 
 /**
  * lpfc_sli4_bar0_register_memmap - Set up SLI4 BAR0 register memory map.
  * @phba: pointer to lpfc hba data structure.
+ * @if_type:  The SLI4 interface type getting configured.
  *
  * This routine is invoked to set up SLI4 BAR0 PCI config space register
  * memory map.
  **/
 static void
-lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba)
+lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
 {
-	phba->sli4_hba.UERRLOregaddr = phba->sli4_hba.conf_regs_memmap_p +
-					LPFC_UERR_STATUS_LO;
-	phba->sli4_hba.UERRHIregaddr = phba->sli4_hba.conf_regs_memmap_p +
-					LPFC_UERR_STATUS_HI;
-	phba->sli4_hba.UEMASKLOregaddr = phba->sli4_hba.conf_regs_memmap_p +
-					LPFC_UE_MASK_LO;
-	phba->sli4_hba.UEMASKHIregaddr = phba->sli4_hba.conf_regs_memmap_p +
-					LPFC_UE_MASK_HI;
-	phba->sli4_hba.SLIINTFregaddr = phba->sli4_hba.conf_regs_memmap_p +
-					LPFC_SLI_INTF;
+	switch (if_type) {
+	case LPFC_SLI_INTF_IF_TYPE_0:
+		phba->sli4_hba.u.if_type0.UERRLOregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_UERR_STATUS_LO;
+		phba->sli4_hba.u.if_type0.UERRHIregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_UERR_STATUS_HI;
+		phba->sli4_hba.u.if_type0.UEMASKLOregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_UE_MASK_LO;
+		phba->sli4_hba.u.if_type0.UEMASKHIregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_UE_MASK_HI;
+		phba->sli4_hba.SLIINTFregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_SLI_INTF;
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_2:
+		phba->sli4_hba.u.if_type2.ERR1regaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_1;
+		phba->sli4_hba.u.if_type2.ERR2regaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_2;
+		phba->sli4_hba.u.if_type2.CTRLregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_CNTRL;
+		phba->sli4_hba.u.if_type2.STATUSregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_STATUS;
+		phba->sli4_hba.SLIINTFregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_SLI_INTF;
+		phba->sli4_hba.PSMPHRregaddr =
+		     phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_IF2_SMPHR;
+		phba->sli4_hba.RQDBregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_RQ_DOORBELL;
+		phba->sli4_hba.WQDBregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_WQ_DOORBELL;
+		phba->sli4_hba.EQCQDBregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL;
+		phba->sli4_hba.MQDBregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_MQ_DOORBELL;
+		phba->sli4_hba.BMBXregaddr =
+			phba->sli4_hba.conf_regs_memmap_p + LPFC_BMBX;
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_1:
+	default:
+		dev_printk(KERN_ERR, &phba->pcidev->dev,
+			   "FATAL - unsupported SLI4 interface type - %d\n",
+			   if_type);
+		break;
+	}
 }
 
 /**
@@ -5293,16 +5561,14 @@
 static void
 lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba)
 {
-
-	phba->sli4_hba.STAregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
-				    LPFC_HST_STATE;
+	phba->sli4_hba.PSMPHRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
+		LPFC_SLIPORT_IF0_SMPHR;
 	phba->sli4_hba.ISRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
-				    LPFC_HST_ISR0;
+		LPFC_HST_ISR0;
 	phba->sli4_hba.IMRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
-				    LPFC_HST_IMR0;
+		LPFC_HST_IMR0;
 	phba->sli4_hba.ISCRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
-				     LPFC_HST_ISCR0;
-	return;
+		LPFC_HST_ISCR0;
 }
 
 /**
@@ -5542,11 +5808,12 @@
 }
 
 /**
- * lpfc_dev_endian_order_setup - Notify the port of the host's endian order.
+ * lpfc_setup_endian_order - Write endian order to an SLI4 if_type 0 port.
  * @phba: pointer to lpfc hba data structure.
  *
- * This routine is invoked to setup the host-side endian order to the
- * HBA consistent with the SLI-4 interface spec.
+ * This routine is invoked to setup the port-side endian order when
+ * the port if_type is 0.  This routine has no function for other
+ * if_types.
  *
  * Return codes
  * 	0 - successful
@@ -5557,34 +5824,44 @@
 lpfc_setup_endian_order(struct lpfc_hba *phba)
 {
 	LPFC_MBOXQ_t *mboxq;
-	uint32_t rc = 0;
+	uint32_t if_type, rc = 0;
 	uint32_t endian_mb_data[2] = {HOST_ENDIAN_LOW_WORD0,
 				      HOST_ENDIAN_HIGH_WORD1};
 
-	mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mboxq) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"0492 Unable to allocate memory for issuing "
-				"SLI_CONFIG_SPECIAL mailbox command\n");
-		return -ENOMEM;
-	}
+	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+	switch (if_type) {
+	case LPFC_SLI_INTF_IF_TYPE_0:
+		mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+						       GFP_KERNEL);
+		if (!mboxq) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"0492 Unable to allocate memory for "
+					"issuing SLI_CONFIG_SPECIAL mailbox "
+					"command\n");
+			return -ENOMEM;
+		}
 
-	/*
-	 * The SLI4_CONFIG_SPECIAL mailbox command requires the first two
-	 * words to contain special data values and no other data.
-	 */
-	memset(mboxq, 0, sizeof(LPFC_MBOXQ_t));
-	memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data));
-	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-	if (rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"0493 SLI_CONFIG_SPECIAL mailbox failed with "
-				"status x%x\n",
-				rc);
-		rc = -EIO;
+		/*
+		 * The SLI4_CONFIG_SPECIAL mailbox command requires the first
+		 * two words to contain special data values and no other data.
+		 */
+		memset(mboxq, 0, sizeof(LPFC_MBOXQ_t));
+		memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data));
+		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+		if (rc != MBX_SUCCESS) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"0493 SLI_CONFIG_SPECIAL mailbox "
+					"failed with status x%x\n",
+					rc);
+			rc = -EIO;
+		}
+		mempool_free(mboxq, phba->mbox_mem_pool);
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_2:
+	case LPFC_SLI_INTF_IF_TYPE_1:
+	default:
+		break;
 	}
-
-	mempool_free(mboxq, phba->mbox_mem_pool);
 	return rc;
 }
 
@@ -6416,36 +6693,124 @@
 lpfc_pci_function_reset(struct lpfc_hba *phba)
 {
 	LPFC_MBOXQ_t *mboxq;
-	uint32_t rc = 0;
+	uint32_t rc = 0, if_type;
 	uint32_t shdr_status, shdr_add_status;
+	uint32_t rdy_chk, num_resets = 0, reset_again = 0;
 	union lpfc_sli4_cfg_shdr *shdr;
+	struct lpfc_register reg_data;
 
-	mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mboxq) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"0494 Unable to allocate memory for issuing "
-				"SLI_FUNCTION_RESET mailbox command\n");
-		return -ENOMEM;
+	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+	switch (if_type) {
+	case LPFC_SLI_INTF_IF_TYPE_0:
+		mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+						       GFP_KERNEL);
+		if (!mboxq) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"0494 Unable to allocate memory for "
+					"issuing SLI_FUNCTION_RESET mailbox "
+					"command\n");
+			return -ENOMEM;
+		}
+
+		/* Setup PCI function reset mailbox-ioctl command */
+		lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+				 LPFC_MBOX_OPCODE_FUNCTION_RESET, 0,
+				 LPFC_SLI4_MBX_EMBED);
+		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+		shdr = (union lpfc_sli4_cfg_shdr *)
+			&mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
+		shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
+		shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
+					 &shdr->response);
+		if (rc != MBX_TIMEOUT)
+			mempool_free(mboxq, phba->mbox_mem_pool);
+		if (shdr_status || shdr_add_status || rc) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"0495 SLI_FUNCTION_RESET mailbox "
+					"failed with status x%x add_status x%x,"
+					" mbx status x%x\n",
+					shdr_status, shdr_add_status, rc);
+			rc = -ENXIO;
+		}
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_2:
+		for (num_resets = 0;
+		     num_resets < MAX_IF_TYPE_2_RESETS;
+		     num_resets++) {
+			reg_data.word0 = 0;
+			bf_set(lpfc_sliport_ctrl_end, &reg_data,
+			       LPFC_SLIPORT_LITTLE_ENDIAN);
+			bf_set(lpfc_sliport_ctrl_ip, &reg_data,
+			       LPFC_SLIPORT_INIT_PORT);
+			writel(reg_data.word0, phba->sli4_hba.u.if_type2.
+			       CTRLregaddr);
+
+			/*
+			 * Poll the Port Status Register and wait for RDY for
+			 * up to 10 seconds.  If the port doesn't respond, treat
+			 * it as an error.  If the port responds with RN, start
+			 * the loop again.
+			 */
+			for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
+				reg_data.word0 =
+					readl(phba->sli4_hba.u.if_type2.
+					      STATUSregaddr);
+				if (bf_get(lpfc_sliport_status_rdy, &reg_data))
+					break;
+				if (bf_get(lpfc_sliport_status_rn, &reg_data)) {
+					reset_again++;
+					break;
+				}
+				msleep(10);
+			}
+
+			/*
+			 * If the port responds to the init request with
+			 * reset needed, delay for a bit and restart the loop.
+			 */
+			if (reset_again) {
+				msleep(10);
+				reset_again = 0;
+				continue;
+			}
+
+			/* Detect any port errors. */
+			reg_data.word0 = readl(phba->sli4_hba.u.if_type2.
+					       STATUSregaddr);
+			if ((bf_get(lpfc_sliport_status_err, &reg_data)) ||
+			    (rdy_chk >= 1000)) {
+				phba->work_status[0] = readl(
+					phba->sli4_hba.u.if_type2.ERR1regaddr);
+				phba->work_status[1] = readl(
+					phba->sli4_hba.u.if_type2.ERR2regaddr);
+				lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"2890 Port Error Detected "
+					"during Port Reset: "
+					"port status reg 0x%x, "
+					"error 1=0x%x, error 2=0x%x\n",
+					reg_data.word0,
+					phba->work_status[0],
+					phba->work_status[1]);
+				rc = -ENODEV;
+			}
+
+			/*
+			 * Terminate the outer loop provided the Port indicated
+			 * ready within 10 seconds.
+			 */
+			if (rdy_chk < 1000)
+				break;
+		}
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_1:
+	default:
+		break;
 	}
 
-	/* Set up PCI function reset SLI4_CONFIG mailbox-ioctl command */
-	lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
-			 LPFC_MBOX_OPCODE_FUNCTION_RESET, 0,
-			 LPFC_SLI4_MBX_EMBED);
-	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-	shdr = (union lpfc_sli4_cfg_shdr *)
-		&mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
-	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
-	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mboxq, phba->mbox_mem_pool);
-	if (shdr_status || shdr_add_status || rc) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"0495 SLI_FUNCTION_RESET mailbox failed with "
-				"status x%x add_status x%x, mbx status x%x\n",
-				shdr_status, shdr_add_status, rc);
-		rc = -ENXIO;
-	}
+	/* Catch the not-ready port failure after a port reset. */
+	if (num_resets >= MAX_IF_TYPE_2_RESETS)
+		rc = -ENODEV;
+
 	return rc;
 }
 
@@ -6536,6 +6901,7 @@
 	struct pci_dev *pdev;
 	unsigned long bar0map_len, bar1map_len, bar2map_len;
 	int error = -ENODEV;
+	uint32_t if_type;
 
 	/* Obtain PCI device reference */
 	if (!phba->pcidev)
@@ -6552,61 +6918,105 @@
 		}
 	}
 
-	/* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the
-	 * number of bytes required by each mapping. They are actually
-	 * mapping to the PCI BAR regions 0 or 1, 2, and 4 by the SLI4 device.
+	/*
+	 * The BARs and register set definitions and offset locations are
+	 * dependent on the if_type.
+	 */
+	if (pci_read_config_dword(pdev, LPFC_SLI_INTF,
+				  &phba->sli4_hba.sli_intf.word0)) {
+		return error;
+	}
+
+	/* There is no SLI3 failback for SLI4 devices. */
+	if (bf_get(lpfc_sli_intf_valid, &phba->sli4_hba.sli_intf) !=
+	    LPFC_SLI_INTF_VALID) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+				"2894 SLI_INTF reg contents invalid "
+				"sli_intf reg 0x%x\n",
+				phba->sli4_hba.sli_intf.word0);
+		return error;
+	}
+
+	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+	/*
+	 * Get the bus address of SLI4 device Bar regions and the
+	 * number of bytes required by each mapping. The mapping of the
+	 * particular PCI BARs regions is dependent on the type of
+	 * SLI4 device.
 	 */
 	if (pci_resource_start(pdev, 0)) {
 		phba->pci_bar0_map = pci_resource_start(pdev, 0);
 		bar0map_len = pci_resource_len(pdev, 0);
+
+		/*
+		 * Map SLI4 PCI Config Space Register base to a kernel virtual
+		 * addr
+		 */
+		phba->sli4_hba.conf_regs_memmap_p =
+			ioremap(phba->pci_bar0_map, bar0map_len);
+		if (!phba->sli4_hba.conf_regs_memmap_p) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "ioremap failed for SLI4 PCI config "
+				   "registers.\n");
+			goto out;
+		}
+		/* Set up BAR0 PCI config space register memory map */
+		lpfc_sli4_bar0_register_memmap(phba, if_type);
 	} else {
 		phba->pci_bar0_map = pci_resource_start(pdev, 1);
 		bar0map_len = pci_resource_len(pdev, 1);
-	}
-	phba->pci_bar1_map = pci_resource_start(pdev, 2);
-	bar1map_len = pci_resource_len(pdev, 2);
-
-	phba->pci_bar2_map = pci_resource_start(pdev, 4);
-	bar2map_len = pci_resource_len(pdev, 4);
-
-	/* Map SLI4 PCI Config Space Register base to a kernel virtual addr */
-	phba->sli4_hba.conf_regs_memmap_p =
+		if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
+			dev_printk(KERN_ERR, &pdev->dev,
+			   "FATAL - No BAR0 mapping for SLI4, if_type 2\n");
+			goto out;
+		}
+		phba->sli4_hba.conf_regs_memmap_p =
 				ioremap(phba->pci_bar0_map, bar0map_len);
-	if (!phba->sli4_hba.conf_regs_memmap_p) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "ioremap failed for SLI4 PCI config registers.\n");
-		goto out;
+		if (!phba->sli4_hba.conf_regs_memmap_p) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				"ioremap failed for SLI4 PCI config "
+				"registers.\n");
+				goto out;
+		}
+		lpfc_sli4_bar0_register_memmap(phba, if_type);
 	}
 
-	/* Map SLI4 HBA Control Register base to a kernel virtual address. */
-	phba->sli4_hba.ctrl_regs_memmap_p =
+	if (pci_resource_start(pdev, 2)) {
+		/*
+		 * Map SLI4 if type 0 HBA Control Register base to a kernel
+		 * virtual address and setup the registers.
+		 */
+		phba->pci_bar1_map = pci_resource_start(pdev, 2);
+		bar1map_len = pci_resource_len(pdev, 2);
+		phba->sli4_hba.ctrl_regs_memmap_p =
 				ioremap(phba->pci_bar1_map, bar1map_len);
-	if (!phba->sli4_hba.ctrl_regs_memmap_p) {
-		dev_printk(KERN_ERR, &pdev->dev,
+		if (!phba->sli4_hba.ctrl_regs_memmap_p) {
+			dev_printk(KERN_ERR, &pdev->dev,
 			   "ioremap failed for SLI4 HBA control registers.\n");
-		goto out_iounmap_conf;
+			goto out_iounmap_conf;
+		}
+		lpfc_sli4_bar1_register_memmap(phba);
 	}
 
-	/* Map SLI4 HBA Doorbell Register base to a kernel virtual address. */
-	phba->sli4_hba.drbl_regs_memmap_p =
+	if (pci_resource_start(pdev, 4)) {
+		/*
+		 * Map SLI4 if type 0 HBA Doorbell Register base to a kernel
+		 * virtual address and setup the registers.
+		 */
+		phba->pci_bar2_map = pci_resource_start(pdev, 4);
+		bar2map_len = pci_resource_len(pdev, 4);
+		phba->sli4_hba.drbl_regs_memmap_p =
 				ioremap(phba->pci_bar2_map, bar2map_len);
-	if (!phba->sli4_hba.drbl_regs_memmap_p) {
-		dev_printk(KERN_ERR, &pdev->dev,
+		if (!phba->sli4_hba.drbl_regs_memmap_p) {
+			dev_printk(KERN_ERR, &pdev->dev,
 			   "ioremap failed for SLI4 HBA doorbell registers.\n");
-		goto out_iounmap_ctrl;
+			goto out_iounmap_ctrl;
+		}
+		error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0);
+		if (error)
+			goto out_iounmap_all;
 	}
 
-	/* Set up BAR0 PCI config space register memory map */
-	lpfc_sli4_bar0_register_memmap(phba);
-
-	/* Set up BAR1 register memory map */
-	lpfc_sli4_bar1_register_memmap(phba);
-
-	/* Set up BAR2 register memory map */
-	error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0);
-	if (error)
-		goto out_iounmap_all;
-
 	return 0;
 
 out_iounmap_all:
@@ -8149,6 +8559,8 @@
 		goto out_unset_driver_resource_s4;
 	}
 
+	INIT_LIST_HEAD(&phba->active_rrq_list);
+
 	/* Set up common device driver resources */
 	error = lpfc_setup_driver_resource_phase2(phba);
 	if (error) {
@@ -8218,7 +8630,11 @@
 				"0451 Configure interrupt mode (%d) "
 				"failed active interrupt test.\n",
 				intr_mode);
-		/* Unset the preivous SLI-4 HBA setup */
+		/* Unset the previous SLI-4 HBA setup. */
+		/*
+		 * TODO:  Is this operation compatible with IF TYPE 2
+		 * devices?  All port state is deleted and cleared.
+		 */
 		lpfc_sli4_unset_hba(phba);
 		/* Try next level of interrupt mode */
 		cfg_mode = --intr_mode;
@@ -8990,6 +9406,10 @@
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS,
 		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE,
+		PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0 }
 };
 
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index bb59e92..e3b790e 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -33,7 +33,7 @@
 #define LOG_FCP_ERROR	0x00001000	/* log errors, not underruns */
 #define LOG_LIBDFC	0x00002000	/* Libdfc events */
 #define LOG_VPORT	0x00004000	/* NPIV events */
-#define LOF_SECURITY	0x00008000	/* Security events */
+#define LOG_SECURITY	0x00008000	/* Security events */
 #define LOG_EVENT	0x00010000	/* CT,TEMP,DUMP, logging */
 #define LOG_FIP		0x00020000	/* FIP events */
 #define LOG_ALL_MSG	0xffffffff	/* LOG all messages */
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 62d0957..23403c6 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -263,18 +263,19 @@
 }
 
 /**
- * lpfc_read_la - Prepare a mailbox command for reading HBA link attention
+ * lpfc_read_topology - Prepare a mailbox command for reading HBA topology
  * @phba: pointer to lpfc hba data structure.
  * @pmb: pointer to the driver internal queue element for mailbox command.
  * @mp: DMA buffer memory for reading the link attention information into.
  *
- * The read link attention mailbox command is issued to read the Link Event
- * Attention information indicated by the HBA port when the Link Event bit
- * of the Host Attention (HSTATT) register is set to 1. A Link Event
+ * The read topology mailbox command is issued to read the link topology
+ * information indicated by the HBA port when the Link Event bit of the Host
+ * Attention (HSTATT) register is set to 1 (For SLI-3) or when an FC Link
+ * Attention ACQE is received from the port (For SLI-4). A Link Event
  * Attention occurs based on an exception detected at the Fibre Channel link
  * interface.
  *
- * This routine prepares the mailbox command for reading HBA link attention
+ * This routine prepares the mailbox command for reading HBA link topology
  * information. A DMA memory has been set aside and address passed to the
  * HBA through @mp for the HBA to DMA link attention information into the
  * memory as part of the execution of the mailbox command.
@@ -283,7 +284,8 @@
  *    0 - Success (currently always return 0)
  **/
 int
-lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
+lpfc_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb,
+		   struct lpfc_dmabuf *mp)
 {
 	MAILBOX_t *mb;
 	struct lpfc_sli *psli;
@@ -293,15 +295,15 @@
 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
 
 	INIT_LIST_HEAD(&mp->list);
-	mb->mbxCommand = MBX_READ_LA64;
-	mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
-	mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
-	mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys);
+	mb->mbxCommand = MBX_READ_TOPOLOGY;
+	mb->un.varReadTop.lilpBde64.tus.f.bdeSize = LPFC_ALPA_MAP_SIZE;
+	mb->un.varReadTop.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
+	mb->un.varReadTop.lilpBde64.addrLow = putPaddrLow(mp->phys);
 
 	/* Save address for later completion and set the owner to host so that
 	 * the FW knows this mailbox is available for processing.
 	 */
-	pmb->context1 = (uint8_t *) mp;
+	pmb->context1 = (uint8_t *)mp;
 	mb->mbxOwner = OWN_HOST;
 	return (0);
 }
@@ -516,18 +518,33 @@
 	vpd = &phba->vpd;
 	if (vpd->rev.feaLevelHigh >= 0x02){
 		switch(linkspeed){
-			case LINK_SPEED_1G:
-			case LINK_SPEED_2G:
-			case LINK_SPEED_4G:
-			case LINK_SPEED_8G:
-				mb->un.varInitLnk.link_flags |=
-							FLAGS_LINK_SPEED;
-				mb->un.varInitLnk.link_speed = linkspeed;
+		case LPFC_USER_LINK_SPEED_1G:
+			mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
+			mb->un.varInitLnk.link_speed = LINK_SPEED_1G;
 			break;
-			case LINK_SPEED_AUTO:
-			default:
-				mb->un.varInitLnk.link_speed =
-							LINK_SPEED_AUTO;
+		case LPFC_USER_LINK_SPEED_2G:
+			mb->un.varInitLnk.link_flags |=	FLAGS_LINK_SPEED;
+			mb->un.varInitLnk.link_speed = LINK_SPEED_2G;
+			break;
+		case LPFC_USER_LINK_SPEED_4G:
+			mb->un.varInitLnk.link_flags |=	FLAGS_LINK_SPEED;
+			mb->un.varInitLnk.link_speed = LINK_SPEED_4G;
+			break;
+		case LPFC_USER_LINK_SPEED_8G:
+			mb->un.varInitLnk.link_flags |=	FLAGS_LINK_SPEED;
+			mb->un.varInitLnk.link_speed = LINK_SPEED_8G;
+			break;
+		case LPFC_USER_LINK_SPEED_10G:
+			mb->un.varInitLnk.link_flags |=	FLAGS_LINK_SPEED;
+			mb->un.varInitLnk.link_speed = LINK_SPEED_10G;
+			break;
+		case LPFC_USER_LINK_SPEED_16G:
+			mb->un.varInitLnk.link_flags |=	FLAGS_LINK_SPEED;
+			mb->un.varInitLnk.link_speed = LINK_SPEED_16G;
+			break;
+		case LPFC_USER_LINK_SPEED_AUTO:
+		default:
+			mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
 			break;
 		}
 
@@ -693,7 +710,7 @@
  * @did: remote port identifier.
  * @param: pointer to memory holding the server parameters.
  * @pmb: pointer to the driver internal queue element for mailbox command.
- * @flag: action flag to be passed back for the complete function.
+ * @rpi: the rpi to use in the registration (usually only used for SLI4.
  *
  * The registration login mailbox command is used to register an N_Port or
  * F_Port login. This registration allows the HBA to cache the remote N_Port
@@ -712,7 +729,7 @@
  **/
 int
 lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
-	       uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
+	     uint8_t *param, LPFC_MBOXQ_t *pmb, uint16_t rpi)
 {
 	MAILBOX_t *mb = &pmb->u.mb;
 	uint8_t *sparam;
@@ -722,17 +739,13 @@
 
 	mb->un.varRegLogin.rpi = 0;
 	if (phba->sli_rev == LPFC_SLI_REV4) {
-		mb->un.varRegLogin.rpi = lpfc_sli4_alloc_rpi(phba);
+		mb->un.varRegLogin.rpi = rpi;
 		if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR)
 			return 1;
 	}
-
 	mb->un.varRegLogin.vpi = vpi + phba->vpi_base;
 	mb->un.varRegLogin.did = did;
-	mb->un.varWords[30] = flag;	/* Set flag to issue action on cmpl */
-
 	mb->mbxOwner = OWN_HOST;
-
 	/* Get a buffer to hold NPorts Service Parameters */
 	mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
 	if (mp)
@@ -743,7 +756,7 @@
 		/* REG_LOGIN: no buffers */
 		lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
 				"0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, "
-				"flag x%x\n", vpi, did, flag);
+				"rpi x%x\n", vpi, did, rpi);
 		return (1);
 	}
 	INIT_LIST_HEAD(&mp->list);
@@ -1918,11 +1931,14 @@
 	struct lpfc_mbx_init_vfi *init_vfi;
 
 	memset(mbox, 0, sizeof(*mbox));
+	mbox->vport = vport;
 	init_vfi = &mbox->u.mqe.un.init_vfi;
 	bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VFI);
 	bf_set(lpfc_init_vfi_vr, init_vfi, 1);
 	bf_set(lpfc_init_vfi_vt, init_vfi, 1);
+	bf_set(lpfc_init_vfi_vp, init_vfi, 1);
 	bf_set(lpfc_init_vfi_vfi, init_vfi, vport->vfi + vport->phba->vfi_base);
+	bf_set(lpfc_init_vpi_vpi, init_vfi, vport->vpi + vport->phba->vpi_base);
 	bf_set(lpfc_init_vfi_fcfi, init_vfi, vport->phba->fcf.fcfi);
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 8f879e4..cbb48ee 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -113,11 +113,16 @@
 		goto fail_free_mbox_pool;
 
 	if (phba->sli_rev == LPFC_SLI_REV4) {
+		phba->rrq_pool =
+			mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
+						sizeof(struct lpfc_node_rrq));
+		if (!phba->rrq_pool)
+			goto fail_free_nlp_mem_pool;
 		phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool",
 					      phba->pcidev,
 					      LPFC_HDR_BUF_SIZE, align, 0);
 		if (!phba->lpfc_hrb_pool)
-			goto fail_free_nlp_mem_pool;
+			goto fail_free_rrq_mem_pool;
 
 		phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool",
 					      phba->pcidev,
@@ -147,6 +152,9 @@
  fail_free_hrb_pool:
 	pci_pool_destroy(phba->lpfc_hrb_pool);
 	phba->lpfc_hrb_pool = NULL;
+ fail_free_rrq_mem_pool:
+	mempool_destroy(phba->rrq_pool);
+	phba->rrq_pool = NULL;
  fail_free_nlp_mem_pool:
 	mempool_destroy(phba->nlp_mem_pool);
 	phba->nlp_mem_pool = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index bccc9c6..d85a742 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -386,7 +386,7 @@
 		goto out;
 
 	rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
-			    (uint8_t *) sp, mbox, 0);
+			    (uint8_t *) sp, mbox, ndlp->nlp_rpi);
 	if (rc) {
 		mempool_free(mbox, phba->mbox_mem_pool);
 		goto out;
@@ -632,7 +632,7 @@
 {
 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
-	if (!(ndlp->nlp_flag & NLP_RPI_VALID)) {
+	if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
 		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
 		return 0;
 	}
@@ -968,7 +968,7 @@
 	lpfc_unreg_rpi(vport, ndlp);
 
 	if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID,
-			   (uint8_t *) sp, mbox, 0) == 0) {
+			 (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) {
 		switch (ndlp->nlp_DID) {
 		case NameServer_DID:
 			mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
@@ -1338,12 +1338,6 @@
 	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
 		if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
 		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {
-			if (phba->sli_rev == LPFC_SLI_REV4) {
-				spin_unlock_irq(&phba->hbalock);
-				lpfc_sli4_free_rpi(phba,
-					mb->u.mb.un.varRegLogin.rpi);
-				spin_lock_irq(&phba->hbalock);
-			}
 			mp = (struct lpfc_dmabuf *) (mb->context1);
 			if (mp) {
 				__lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -1426,7 +1420,7 @@
 	}
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
-	ndlp->nlp_flag |= NLP_RPI_VALID;
+	ndlp->nlp_flag |= NLP_RPI_REGISTERED;
 
 	/* Only if we are not a fabric nport do we issue PRLI */
 	if (!(ndlp->nlp_type & NLP_FABRIC)) {
@@ -2027,7 +2021,7 @@
 
 	if (!mb->mbxStatus) {
 		ndlp->nlp_rpi = mb->un.varWords[0];
-		ndlp->nlp_flag |= NLP_RPI_VALID;
+		ndlp->nlp_flag |= NLP_RPI_REGISTERED;
 	} else {
 		if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
 			lpfc_drop_node(vport, ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 581837b..c97751c 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -621,10 +621,13 @@
 			  struct sli4_wcqe_xri_aborted *axri)
 {
 	uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
+	uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
 	struct lpfc_scsi_buf *psb, *next_psb;
 	unsigned long iflag = 0;
 	struct lpfc_iocbq *iocbq;
 	int i;
+	struct lpfc_nodelist *ndlp;
+	int rrq_empty = 0;
 	struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
 
 	spin_lock_irqsave(&phba->hbalock, iflag);
@@ -637,8 +640,14 @@
 			psb->status = IOSTAT_SUCCESS;
 			spin_unlock(
 				&phba->sli4_hba.abts_scsi_buf_list_lock);
+			ndlp = psb->rdata->pnode;
+			rrq_empty = list_empty(&phba->active_rrq_list);
 			spin_unlock_irqrestore(&phba->hbalock, iflag);
+			if (ndlp)
+				lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1);
 			lpfc_release_scsi_buf_s4(phba, psb);
+			if (rrq_empty)
+				lpfc_worker_wake_up(phba);
 			return;
 		}
 	}
@@ -914,7 +923,7 @@
 }
 
 /**
- * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
+ * lpfc_get_scsi_buf_s3 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
  * @phba: The HBA for which this call is being executed.
  *
  * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
@@ -925,7 +934,7 @@
  *   Pointer to lpfc_scsi_buf - Success
  **/
 static struct lpfc_scsi_buf*
-lpfc_get_scsi_buf(struct lpfc_hba * phba)
+lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
 	struct  lpfc_scsi_buf * lpfc_cmd = NULL;
 	struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
@@ -941,6 +950,67 @@
 	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
 	return  lpfc_cmd;
 }
+/**
+ * lpfc_get_scsi_buf_s4 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
+ * @phba: The HBA for which this call is being executed.
+ *
+ * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
+ * and returns to caller.
+ *
+ * Return codes:
+ *   NULL - Error
+ *   Pointer to lpfc_scsi_buf - Success
+ **/
+static struct lpfc_scsi_buf*
+lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+{
+	struct  lpfc_scsi_buf *lpfc_cmd = NULL;
+	struct  lpfc_scsi_buf *start_lpfc_cmd = NULL;
+	struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+	unsigned long iflag = 0;
+	int found = 0;
+
+	spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+	list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+	while (!found && lpfc_cmd) {
+		if (lpfc_test_rrq_active(phba, ndlp,
+					 lpfc_cmd->cur_iocbq.sli4_xritag)) {
+			lpfc_release_scsi_buf_s4(phba, lpfc_cmd);
+			spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+			list_remove_head(scsi_buf_list, lpfc_cmd,
+					 struct lpfc_scsi_buf, list);
+			spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
+						 iflag);
+			if (lpfc_cmd == start_lpfc_cmd) {
+				lpfc_cmd = NULL;
+				break;
+			} else
+				continue;
+		}
+		found = 1;
+		lpfc_cmd->seg_cnt = 0;
+		lpfc_cmd->nonsg_phys = 0;
+		lpfc_cmd->prot_seg_cnt = 0;
+	}
+	return  lpfc_cmd;
+}
+/**
+ * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
+ * @phba: The HBA for which this call is being executed.
+ *
+ * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
+ * and returns to caller.
+ *
+ * Return codes:
+ *   NULL - Error
+ *   Pointer to lpfc_scsi_buf - Success
+ **/
+static struct lpfc_scsi_buf*
+lpfc_get_scsi_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+{
+	return  phba->lpfc_get_scsi_buf(phba, ndlp);
+}
 
 /**
  * lpfc_release_scsi_buf - Return a scsi buffer back to hba scsi buf list
@@ -2744,18 +2814,19 @@
 
 	phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf;
 	phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd;
-	phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf;
 
 	switch (dev_grp) {
 	case LPFC_PCI_DEV_LP:
 		phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s3;
 		phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s3;
 		phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3;
+		phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3;
 		break;
 	case LPFC_PCI_DEV_OC:
 		phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s4;
 		phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4;
 		phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4;
+		phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4;
 		break;
 	default:
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -2764,7 +2835,6 @@
 		return -ENODEV;
 		break;
 	}
-	phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf;
 	phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth;
 	phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
 	return 0;
@@ -2940,7 +3010,7 @@
 	if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
 		goto out_host_busy;
 
-	lpfc_cmd = lpfc_get_scsi_buf(phba);
+	lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
 	if (lpfc_cmd == NULL) {
 		lpfc_rampdown_queue_depth(phba);
 
@@ -3239,7 +3309,7 @@
 	if (!pnode || !NLP_CHK_NODE_ACT(pnode))
 		return FAILED;
 
-	lpfc_cmd = lpfc_get_scsi_buf(phba);
+	lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode);
 	if (lpfc_cmd == NULL)
 		return FAILED;
 	lpfc_cmd->timeout = 60;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 554efa6..634b2fe 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -513,8 +513,344 @@
 }
 
 /**
+ * __lpfc_set_rrq_active - set RRQ active bit in the ndlp's xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: nodelist pointer for this target.
+ * @xritag: xri used in this exchange.
+ * @rxid: Remote Exchange ID.
+ * @send_rrq: Flag used to determine if we should send rrq els cmd.
+ *
+ * This function is called with hbalock held.
+ * The active bit is set in the ndlp's active rrq xri_bitmap. Allocates an
+ * rrq struct and adds it to the active_rrq_list.
+ *
+ * returns  0 for rrq slot for this xri
+ *         < 0  Were not able to get rrq mem or invalid parameter.
+ **/
+static int
+__lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+		uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
+{
+	uint16_t adj_xri;
+	struct lpfc_node_rrq *rrq;
+	int empty;
+
+	/*
+	 * set the active bit even if there is no mem available.
+	 */
+	adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
+	if (!ndlp)
+		return -EINVAL;
+	if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap))
+		return -EINVAL;
+	rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
+	if (rrq) {
+		rrq->send_rrq = send_rrq;
+		rrq->xritag = xritag;
+		rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
+		rrq->ndlp = ndlp;
+		rrq->nlp_DID = ndlp->nlp_DID;
+		rrq->vport = ndlp->vport;
+		rrq->rxid = rxid;
+		empty = list_empty(&phba->active_rrq_list);
+		if (phba->cfg_enable_rrq && send_rrq)
+			/*
+			 * We need the xri before we can add this to the
+			 * phba active rrq list.
+			 */
+			rrq->send_rrq = send_rrq;
+		else
+			rrq->send_rrq = 0;
+		list_add_tail(&rrq->list, &phba->active_rrq_list);
+		if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) {
+			phba->hba_flag |= HBA_RRQ_ACTIVE;
+			if (empty)
+				lpfc_worker_wake_up(phba);
+		}
+		return 0;
+	}
+	return -ENOMEM;
+}
+
+/**
+ * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @xritag: xri used in this exchange.
+ * @rrq: The RRQ to be cleared.
+ *
+ * This function is called with hbalock held. This function
+ **/
+static void
+__lpfc_clr_rrq_active(struct lpfc_hba *phba,
+			uint16_t xritag,
+			struct lpfc_node_rrq *rrq)
+{
+	uint16_t adj_xri;
+	struct lpfc_nodelist *ndlp;
+
+	ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
+
+	/* The target DID could have been swapped (cable swap)
+	 * we should use the ndlp from the findnode if it is
+	 * available.
+	 */
+	if (!ndlp)
+		ndlp = rrq->ndlp;
+
+	adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
+	if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) {
+		rrq->send_rrq = 0;
+		rrq->xritag = 0;
+		rrq->rrq_stop_time = 0;
+	}
+	mempool_free(rrq, phba->rrq_pool);
+}
+
+/**
+ * lpfc_handle_rrq_active - Checks if RRQ has waithed RATOV.
+ * @phba: Pointer to HBA context object.
+ *
+ * This function is called with hbalock held. This function
+ * Checks if stop_time (ratov from setting rrq active) has
+ * been reached, if it has and the send_rrq flag is set then
+ * it will call lpfc_send_rrq. If the send_rrq flag is not set
+ * then it will just call the routine to clear the rrq and
+ * free the rrq resource.
+ * The timer is set to the next rrq that is going to expire before
+ * leaving the routine.
+ *
+ **/
+void
+lpfc_handle_rrq_active(struct lpfc_hba *phba)
+{
+	struct lpfc_node_rrq *rrq;
+	struct lpfc_node_rrq *nextrrq;
+	unsigned long next_time;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+	next_time = jiffies + HZ * (phba->fc_ratov + 1);
+	list_for_each_entry_safe(rrq, nextrrq,
+			&phba->active_rrq_list, list) {
+		if (time_after(jiffies, rrq->rrq_stop_time)) {
+			list_del(&rrq->list);
+			if (!rrq->send_rrq)
+				/* this call will free the rrq */
+				__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+			else {
+			/* if we send the rrq then the completion handler
+			 *  will clear the bit in the xribitmap.
+			 */
+				spin_unlock_irqrestore(&phba->hbalock, iflags);
+				if (lpfc_send_rrq(phba, rrq)) {
+					lpfc_clr_rrq_active(phba, rrq->xritag,
+								 rrq);
+				}
+				spin_lock_irqsave(&phba->hbalock, iflags);
+			}
+		} else if  (time_before(rrq->rrq_stop_time, next_time))
+			next_time = rrq->rrq_stop_time;
+	}
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	if (!list_empty(&phba->active_rrq_list))
+		mod_timer(&phba->rrq_tmr, next_time);
+}
+
+/**
+ * lpfc_get_active_rrq - Get the active RRQ for this exchange.
+ * @vport: Pointer to vport context object.
+ * @xri: The xri used in the exchange.
+ * @did: The targets DID for this exchange.
+ *
+ * returns NULL = rrq not found in the phba->active_rrq_list.
+ *         rrq = rrq for this xri and target.
+ **/
+struct lpfc_node_rrq *
+lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did)
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_node_rrq *rrq;
+	struct lpfc_node_rrq *nextrrq;
+	unsigned long iflags;
+
+	if (phba->sli_rev != LPFC_SLI_REV4)
+		return NULL;
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+		if (rrq->vport == vport && rrq->xritag == xri &&
+				rrq->nlp_DID == did){
+			list_del(&rrq->list);
+			spin_unlock_irqrestore(&phba->hbalock, iflags);
+			return rrq;
+		}
+	}
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	return NULL;
+}
+
+/**
+ * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport.
+ * @vport: Pointer to vport context object.
+ *
+ * Remove all active RRQs for this vport from the phba->active_rrq_list and
+ * clear the rrq.
+ **/
+void
+lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport)
+
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_node_rrq *rrq;
+	struct lpfc_node_rrq *nextrrq;
+	unsigned long iflags;
+
+	if (phba->sli_rev != LPFC_SLI_REV4)
+		return;
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+		if (rrq->vport == vport) {
+			list_del(&rrq->list);
+			__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+		}
+	}
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+}
+
+/**
+ * lpfc_cleanup_wt_rrqs - Remove all rrq's from the active list.
+ * @phba: Pointer to HBA context object.
+ *
+ * Remove all rrqs from the phba->active_rrq_list and free them by
+ * calling __lpfc_clr_active_rrq
+ *
+ **/
+void
+lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
+{
+	struct lpfc_node_rrq *rrq;
+	struct lpfc_node_rrq *nextrrq;
+	unsigned long next_time;
+	unsigned long iflags;
+
+	if (phba->sli_rev != LPFC_SLI_REV4)
+		return;
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+	next_time = jiffies + HZ * (phba->fc_ratov * 2);
+	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+		list_del(&rrq->list);
+		__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+	}
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	if (!list_empty(&phba->active_rrq_list))
+		mod_timer(&phba->rrq_tmr, next_time);
+}
+
+
+/**
+ * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: Targets nodelist pointer for this exchange.
+ * @xritag the xri in the bitmap to test.
+ *
+ * This function is called with hbalock held. This function
+ * returns 0 = rrq not active for this xri
+ *         1 = rrq is valid for this xri.
+ **/
+static int
+__lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+			uint16_t  xritag)
+{
+	uint16_t adj_xri;
+
+	adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
+	if (!ndlp)
+		return 0;
+	if (test_bit(adj_xri, ndlp->active_rrqs.xri_bitmap))
+			return 1;
+	else
+		return 0;
+}
+
+/**
+ * lpfc_set_rrq_active - set RRQ active bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: nodelist pointer for this target.
+ * @xritag: xri used in this exchange.
+ * @rxid: Remote Exchange ID.
+ * @send_rrq: Flag used to determine if we should send rrq els cmd.
+ *
+ * This function takes the hbalock.
+ * The active bit is always set in the active rrq xri_bitmap even
+ * if there is no slot avaiable for the other rrq information.
+ *
+ * returns 0 rrq actived for this xri
+ *         < 0 No memory or invalid ndlp.
+ **/
+int
+lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+			uint16_t xritag, uint16_t rxid, uint16_t send_rrq)
+{
+	int ret;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	ret = __lpfc_set_rrq_active(phba, ndlp, xritag, rxid, send_rrq);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	return ret;
+}
+
+/**
+ * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @xritag: xri used in this exchange.
+ * @rrq: The RRQ to be cleared.
+ *
+ * This function is takes the hbalock.
+ **/
+void
+lpfc_clr_rrq_active(struct lpfc_hba *phba,
+			uint16_t xritag,
+			struct lpfc_node_rrq *rrq)
+{
+	unsigned long iflags;
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	__lpfc_clr_rrq_active(phba, xritag, rrq);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	return;
+}
+
+
+
+/**
+ * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
+ * @phba: Pointer to HBA context object.
+ * @ndlp: Targets nodelist pointer for this exchange.
+ * @xritag the xri in the bitmap to test.
+ *
+ * This function takes the hbalock.
+ * returns 0 = rrq not active for this xri
+ *         1 = rrq is valid for this xri.
+ **/
+int
+lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+			uint16_t  xritag)
+{
+	int ret;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	ret = __lpfc_test_rrq_active(phba, ndlp, xritag);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+	return ret;
+}
+
+/**
  * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool
  * @phba: Pointer to HBA context object.
+ * @piocb: Pointer to the iocbq.
  *
  * This function is called with hbalock held. This function
  * Gets a new driver sglq object from the sglq list. If the
@@ -522,17 +858,51 @@
  * allocated sglq object else it returns NULL.
  **/
 static struct lpfc_sglq *
-__lpfc_sli_get_sglq(struct lpfc_hba *phba)
+__lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
 {
 	struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list;
 	struct lpfc_sglq *sglq = NULL;
+	struct lpfc_sglq *start_sglq = NULL;
 	uint16_t adj_xri;
+	struct lpfc_scsi_buf *lpfc_cmd;
+	struct lpfc_nodelist *ndlp;
+	int found = 0;
+
+	if (piocbq->iocb_flag &  LPFC_IO_FCP) {
+		lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1;
+		ndlp = lpfc_cmd->rdata->pnode;
+	} else  if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) &&
+			!(piocbq->iocb_flag & LPFC_IO_LIBDFC))
+		ndlp = piocbq->context_un.ndlp;
+	else
+		ndlp = piocbq->context1;
+
 	list_remove_head(lpfc_sgl_list, sglq, struct lpfc_sglq, list);
-	if (!sglq)
-		return NULL;
-	adj_xri = sglq->sli4_xritag - phba->sli4_hba.max_cfg_param.xri_base;
-	phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq;
-	sglq->state = SGL_ALLOCATED;
+	start_sglq = sglq;
+	while (!found) {
+		if (!sglq)
+			return NULL;
+		adj_xri = sglq->sli4_xritag -
+				phba->sli4_hba.max_cfg_param.xri_base;
+		if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
+			/* This xri has an rrq outstanding for this DID.
+			 * put it back in the list and get another xri.
+			 */
+			list_add_tail(&sglq->list, lpfc_sgl_list);
+			sglq = NULL;
+			list_remove_head(lpfc_sgl_list, sglq,
+						struct lpfc_sglq, list);
+			if (sglq == start_sglq) {
+				sglq = NULL;
+				break;
+			} else
+				continue;
+		}
+		sglq->ndlp = ndlp;
+		found = 1;
+		phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq;
+		sglq->state = SGL_ALLOCATED;
+	}
 	return sglq;
 }
 
@@ -598,6 +968,7 @@
 				&phba->sli4_hba.abts_sgl_list_lock, iflag);
 		} else {
 			sglq->state = SGL_FREED;
+			sglq->ndlp = NULL;
 			list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list);
 
 			/* Check if TXQ queue needs to be serviced */
@@ -1634,7 +2005,6 @@
 	case MBX_READ_LNK_STAT:
 	case MBX_REG_LOGIN:
 	case MBX_UNREG_LOGIN:
-	case MBX_READ_LA:
 	case MBX_CLEAR_LA:
 	case MBX_DUMP_MEMORY:
 	case MBX_DUMP_CONTEXT:
@@ -1656,7 +2026,7 @@
 	case MBX_READ_SPARM64:
 	case MBX_READ_RPI64:
 	case MBX_REG_LOGIN64:
-	case MBX_READ_LA64:
+	case MBX_READ_TOPOLOGY:
 	case MBX_WRITE_WWN:
 	case MBX_SET_DEBUG:
 	case MBX_LOAD_EXP_ROM:
@@ -1746,11 +2116,6 @@
 		kfree(mp);
 	}
 
-	if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) &&
-	    (phba->sli_rev == LPFC_SLI_REV4) &&
-	    (pmb->u.mb.un.varUnregLogin.rsvd1 == 0x0))
-		lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi);
-
 	/*
 	 * If a REG_LOGIN succeeded  after node is destroyed or node
 	 * is in re-discovery driver need to cleanup the RPI.
@@ -3483,12 +3848,6 @@
 	phba->pport->fc_myDID = 0;
 	phba->pport->fc_prevDID = 0;
 
-	/* Turn off parity checking and serr during the physical reset */
-	pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
-	pci_write_config_word(phba->pcidev, PCI_COMMAND,
-			      (cfg_value &
-			      ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
-
 	spin_lock_irq(&phba->hbalock);
 	psli->sli_flag &= ~(LPFC_PROCESS_LA);
 	phba->fcf.fcf_flag = 0;
@@ -3508,9 +3867,18 @@
 	/* Now physically reset the device */
 	lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
 			"0389 Performing PCI function reset!\n");
+
+	/* Turn off parity checking and serr during the physical reset */
+	pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
+	pci_write_config_word(phba->pcidev, PCI_COMMAND, (cfg_value &
+			      ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
+
 	/* Perform FCoE PCI function reset */
 	lpfc_pci_function_reset(phba);
 
+	/* Restore PCI cmd register */
+	pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
+
 	return 0;
 }
 
@@ -4317,6 +4685,10 @@
 	struct lpfc_vport *vport = phba->pport;
 	struct lpfc_dmabuf *mp;
 
+	/*
+	 * TODO:  Why does this routine execute these task in a different
+	 * order from probe?
+	 */
 	/* Perform a PCI function reset to start from clean */
 	rc = lpfc_pci_function_reset(phba);
 	if (unlikely(rc))
@@ -4357,13 +4729,16 @@
 	}
 
 	rc = lpfc_sli4_read_rev(phba, mboxq, vpd, &vpd_size);
-	if (unlikely(rc))
-		goto out_free_vpd;
-
+	if (unlikely(rc)) {
+		kfree(vpd);
+		goto out_free_mbox;
+	}
 	mqe = &mboxq->u.mqe;
 	phba->sli_rev = bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev);
 	if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev))
-		phba->hba_flag |= HBA_FCOE_SUPPORT;
+		phba->hba_flag |= HBA_FCOE_MODE;
+	else
+		phba->hba_flag &= ~HBA_FCOE_MODE;
 
 	if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) ==
 		LPFC_DCBX_CEE_MODE)
@@ -4372,13 +4747,14 @@
 		phba->hba_flag &= ~HBA_FIP_SUPPORT;
 
 	if (phba->sli_rev != LPFC_SLI_REV4 ||
-	    !(phba->hba_flag & HBA_FCOE_SUPPORT)) {
+	    !(phba->hba_flag & HBA_FCOE_MODE)) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
 			"0376 READ_REV Error. SLI Level %d "
 			"FCoE enabled %d\n",
-			phba->sli_rev, phba->hba_flag & HBA_FCOE_SUPPORT);
+			phba->sli_rev, phba->hba_flag & HBA_FCOE_MODE);
 		rc = -EIO;
-		goto out_free_vpd;
+		kfree(vpd);
+		goto out_free_mbox;
 	}
 	/*
 	 * Evaluate the read rev and vpd data. Populate the driver
@@ -4392,6 +4768,7 @@
 				"Using defaults.\n", rc);
 		rc = 0;
 	}
+	kfree(vpd);
 
 	/* Save information as VPD data */
 	phba->vpd.rev.biuRev = mqe->un.read_rev.first_hw_rev;
@@ -4428,7 +4805,7 @@
 	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
 	if (unlikely(rc)) {
 		rc = -EIO;
-		goto out_free_vpd;
+		goto out_free_mbox;
 	}
 
 	/*
@@ -4476,7 +4853,7 @@
 	if (rc) {
 		phba->link_state = LPFC_HBA_ERROR;
 		rc = -ENOMEM;
-		goto out_free_vpd;
+		goto out_free_mbox;
 	}
 
 	mboxq->vport = vport;
@@ -4501,7 +4878,7 @@
 				rc, bf_get(lpfc_mqe_status, mqe));
 		phba->link_state = LPFC_HBA_ERROR;
 		rc = -EIO;
-		goto out_free_vpd;
+		goto out_free_mbox;
 	}
 
 	if (phba->cfg_soft_wwnn)
@@ -4526,7 +4903,7 @@
 				"0582 Error %d during sgl post operation\n",
 					rc);
 		rc = -ENODEV;
-		goto out_free_vpd;
+		goto out_free_mbox;
 	}
 
 	/* Register SCSI SGL pool to the device */
@@ -4538,7 +4915,7 @@
 		/* Some Scsi buffers were moved to the abort scsi list */
 		/* A pci function reset will repost them */
 		rc = -ENODEV;
-		goto out_free_vpd;
+		goto out_free_mbox;
 	}
 
 	/* Post the rpi header region to the device. */
@@ -4548,7 +4925,7 @@
 				"0393 Error %d during rpi post operation\n",
 				rc);
 		rc = -ENODEV;
-		goto out_free_vpd;
+		goto out_free_mbox;
 	}
 
 	/* Set up all the queues to the device */
@@ -4608,33 +4985,33 @@
 		}
 	}
 
+	if (!(phba->hba_flag & HBA_FCOE_MODE)) {
+		/*
+		 * The FC Port needs to register FCFI (index 0)
+		 */
+		lpfc_reg_fcfi(phba, mboxq);
+		mboxq->vport = phba->pport;
+		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+		if (rc == MBX_SUCCESS)
+			rc = 0;
+		else
+			goto out_unset_queue;
+	}
 	/*
 	 * The port is ready, set the host's link state to LINK_DOWN
 	 * in preparation for link interrupts.
 	 */
-	lpfc_init_link(phba, mboxq, phba->cfg_topology, phba->cfg_link_speed);
-	mboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-	lpfc_set_loopback_flag(phba);
-	/* Change driver state to LPFC_LINK_DOWN right before init link */
 	spin_lock_irq(&phba->hbalock);
 	phba->link_state = LPFC_LINK_DOWN;
 	spin_unlock_irq(&phba->hbalock);
-	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
-	if (unlikely(rc != MBX_NOT_FINISHED)) {
-		kfree(vpd);
-		return 0;
-	} else
-		rc = -EIO;
-
+	rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+out_unset_queue:
 	/* Unset all the queues set up in this routine when error out */
 	if (rc)
 		lpfc_sli4_queue_unset(phba);
-
 out_stop_timers:
 	if (rc)
 		lpfc_stop_hba_timers(phba);
-out_free_vpd:
-	kfree(vpd);
 out_free_mbox:
 	mempool_free(mboxq, phba->mbox_mem_pool);
 	return rc;
@@ -5863,6 +6240,8 @@
 	IOCB_t *icmd;
 	int numBdes = 0;
 	int i = 0;
+	uint32_t offset = 0; /* accumulated offset in the sg request list */
+	int inbound = 0; /* number of sg reply entries inbound from firmware */
 
 	if (!piocbq || !sglq)
 		return xritag;
@@ -5897,6 +6276,20 @@
 			 */
 			bde.tus.w = le32_to_cpu(bpl->tus.w);
 			sgl->sge_len = cpu_to_le32(bde.tus.f.bdeSize);
+			/* The offsets in the sgl need to be accumulated
+			 * separately for the request and reply lists.
+			 * The request is always first, the reply follows.
+			 */
+			if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) {
+				/* add up the reply sg entries */
+				if (bpl->tus.f.bdeFlags == BUFF_TYPE_BDE_64I)
+					inbound++;
+				/* first inbound? reset the offset */
+				if (inbound == 1)
+					offset = 0;
+				bf_set(lpfc_sli4_sge_offset, sgl, offset);
+				offset += bde.tus.f.bdeSize;
+			}
 			bpl++;
 			sgl++;
 		}
@@ -6028,11 +6421,6 @@
 		bf_set(els_req64_vf, &wqe->els_req, 0);
 		/* And a VFID for word 12 */
 		bf_set(els_req64_vfid, &wqe->els_req, 0);
-		/*
-		 * Set ct field to 3, indicates that the context_tag field
-		 * contains the FCFI and remote N_Port_ID is
-		 * in word 5.
-		 */
 		ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l);
 		bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com,
 		       iocbq->iocb.ulpContext);
@@ -6140,6 +6528,18 @@
 		bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0);
 	break;
 	case CMD_GEN_REQUEST64_CR:
+		/* For this command calculate the xmit length of the
+		 * request bde.
+		 */
+		xmit_len = 0;
+		numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
+			sizeof(struct ulp_bde64);
+		for (i = 0; i < numBdes; i++) {
+			if (bpl[i].tus.f.bdeFlags != BUFF_TYPE_BDE_64)
+				break;
+			bde.tus.w = le32_to_cpu(bpl[i].tus.w);
+			xmit_len += bde.tus.f.bdeSize;
+		}
 		/* word3 iocb=IO_TAG wqe=request_payload_len */
 		wqe->gen_req.request_payload_len = xmit_len;
 		/* word4 iocb=parameter wqe=relative_offset memcpy */
@@ -6320,7 +6720,7 @@
 					return IOCB_BUSY;
 				}
 			} else {
-			sglq = __lpfc_sli_get_sglq(phba);
+			sglq = __lpfc_sli_get_sglq(phba, piocb);
 				if (!sglq) {
 					if (!(flag & SLI_IOCB_RET_IOCB)) {
 						__lpfc_sli_ringtx_put(phba,
@@ -8033,29 +8433,66 @@
 lpfc_sli4_eratt_read(struct lpfc_hba *phba)
 {
 	uint32_t uerr_sta_hi, uerr_sta_lo;
+	uint32_t if_type, portsmphr;
+	struct lpfc_register portstat_reg;
 
-	/* For now, use the SLI4 device internal unrecoverable error
+	/*
+	 * For now, use the SLI4 device internal unrecoverable error
 	 * registers for error attention. This can be changed later.
 	 */
-	uerr_sta_lo = readl(phba->sli4_hba.UERRLOregaddr);
-	uerr_sta_hi = readl(phba->sli4_hba.UERRHIregaddr);
-	if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
-	    (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
+	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+	switch (if_type) {
+	case LPFC_SLI_INTF_IF_TYPE_0:
+		uerr_sta_lo = readl(phba->sli4_hba.u.if_type0.UERRLOregaddr);
+		uerr_sta_hi = readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
+		if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
+		    (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"1423 HBA Unrecoverable error: "
+					"uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
+					"ue_mask_lo_reg=0x%x, "
+					"ue_mask_hi_reg=0x%x\n",
+					uerr_sta_lo, uerr_sta_hi,
+					phba->sli4_hba.ue_mask_lo,
+					phba->sli4_hba.ue_mask_hi);
+			phba->work_status[0] = uerr_sta_lo;
+			phba->work_status[1] = uerr_sta_hi;
+			phba->work_ha |= HA_ERATT;
+			phba->hba_flag |= HBA_ERATT_HANDLED;
+			return 1;
+		}
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_2:
+		portstat_reg.word0 =
+			readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
+		portsmphr = readl(phba->sli4_hba.PSMPHRregaddr);
+		if (bf_get(lpfc_sliport_status_err, &portstat_reg)) {
+			phba->work_status[0] =
+				readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
+			phba->work_status[1] =
+				readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
+			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+					"2885 Port Error Detected: "
+					"port status reg 0x%x, "
+					"port smphr reg 0x%x, "
+					"error 1=0x%x, error 2=0x%x\n",
+					portstat_reg.word0,
+					portsmphr,
+					phba->work_status[0],
+					phba->work_status[1]);
+			phba->work_ha |= HA_ERATT;
+			phba->hba_flag |= HBA_ERATT_HANDLED;
+			return 1;
+		}
+		break;
+	case LPFC_SLI_INTF_IF_TYPE_1:
+	default:
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"1423 HBA Unrecoverable error: "
-				"uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
-				"ue_mask_lo_reg=0x%x, ue_mask_hi_reg=0x%x\n",
-				uerr_sta_lo, uerr_sta_hi,
-				phba->sli4_hba.ue_mask_lo,
-				phba->sli4_hba.ue_mask_hi);
-		phba->work_status[0] = uerr_sta_lo;
-		phba->work_status[1] = uerr_sta_hi;
-		/* Set the driver HA work bitmap */
-		phba->work_ha |= HA_ERATT;
-		/* Indicate polling handles this ERATT */
-		phba->hba_flag |= HBA_ERATT_HANDLED;
+				"2886 HBA Error Attention on unsupported "
+				"if type %d.", if_type);
 		return 1;
 	}
+
 	return 0;
 }
 
@@ -8110,7 +8547,7 @@
 		ha_copy = lpfc_sli_eratt_read(phba);
 		break;
 	case LPFC_SLI_REV4:
-		/* Read devcie Uncoverable Error (UERR) registers */
+		/* Read device Uncoverable Error (UERR) registers */
 		ha_copy = lpfc_sli4_eratt_read(phba);
 		break;
 	default:
@@ -10155,16 +10592,20 @@
 			 length, LPFC_SLI4_MBX_EMBED);
 
 	mq_create_ext = &mbox->u.mqe.un.mq_create_ext;
-	bf_set(lpfc_mbx_mq_create_ext_num_pages, &mq_create_ext->u.request,
-		    mq->page_count);
-	bf_set(lpfc_mbx_mq_create_ext_async_evt_link, &mq_create_ext->u.request,
-	       1);
-	bf_set(lpfc_mbx_mq_create_ext_async_evt_fcfste,
+	bf_set(lpfc_mbx_mq_create_ext_num_pages,
+	       &mq_create_ext->u.request, mq->page_count);
+	bf_set(lpfc_mbx_mq_create_ext_async_evt_link,
+	       &mq_create_ext->u.request, 1);
+	bf_set(lpfc_mbx_mq_create_ext_async_evt_fip,
 	       &mq_create_ext->u.request, 1);
 	bf_set(lpfc_mbx_mq_create_ext_async_evt_group5,
 	       &mq_create_ext->u.request, 1);
-	bf_set(lpfc_mq_context_cq_id, &mq_create_ext->u.request.context,
-	       cq->queue_id);
+	bf_set(lpfc_mbx_mq_create_ext_async_evt_fc,
+	       &mq_create_ext->u.request, 1);
+	bf_set(lpfc_mbx_mq_create_ext_async_evt_sli,
+	       &mq_create_ext->u.request, 1);
+	bf_set(lpfc_mq_context_cq_id,
+	       &mq_create_ext->u.request.context, cq->queue_id);
 	bf_set(lpfc_mq_context_valid, &mq_create_ext->u.request.context, 1);
 	switch (mq->entry_count) {
 	default:
@@ -11137,7 +11578,8 @@
 static int
 lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
 {
-	char *rctl_names[] = FC_RCTL_NAMES_INIT;
+	/*  make rctl_names static to save stack space */
+	static char *rctl_names[] = FC_RCTL_NAMES_INIT;
 	char *type_names[] = FC_TYPE_NAMES_INIT;
 	struct fc_vft_header *fc_vft_hdr;
 
@@ -11538,6 +11980,10 @@
 				"SID:x%x\n", oxid, sid);
 		return;
 	}
+	if (rxid >= phba->sli4_hba.max_cfg_param.xri_base
+		&& rxid <= (phba->sli4_hba.max_cfg_param.max_xri
+		+ phba->sli4_hba.max_cfg_param.xri_base))
+		lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0);
 
 	/* Allocate buffer for acc iocb */
 	ctiocb = lpfc_sli_get_iocbq(phba);
@@ -11560,6 +12006,7 @@
 	icmd->ulpLe = 1;
 	icmd->ulpClass = CLASS3;
 	icmd->ulpContext = ndlp->nlp_rpi;
+	ctiocb->context1 = ndlp;
 
 	ctiocb->iocb_cmpl = NULL;
 	ctiocb->vport = phba->pport;
@@ -12129,42 +12576,37 @@
 
 /**
  * lpfc_sli4_init_vpi - Initialize a vpi with the port
- * @phba: pointer to lpfc hba data structure.
- * @vpi: vpi value to activate with the port.
+ * @vport: Pointer to the vport for which the vpi is being initialized
  *
- * This routine is invoked to activate a vpi with the
- * port when the host intends to use vports with a
- * nonzero vpi.
+ * This routine is invoked to activate a vpi with the port.
  *
  * Returns:
  *    0 success
  *    -Evalue otherwise
  **/
 int
-lpfc_sli4_init_vpi(struct lpfc_hba *phba, uint16_t vpi)
+lpfc_sli4_init_vpi(struct lpfc_vport *vport)
 {
 	LPFC_MBOXQ_t *mboxq;
 	int rc = 0;
 	int retval = MBX_SUCCESS;
 	uint32_t mbox_tmo;
-
-	if (vpi == 0)
-		return -EINVAL;
+	struct lpfc_hba *phba = vport->phba;
 	mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!mboxq)
 		return -ENOMEM;
-	lpfc_init_vpi(phba, mboxq, vpi);
+	lpfc_init_vpi(phba, mboxq, vport->vpi);
 	mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI);
 	rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
 	if (rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+		lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
 				"2022 INIT VPI Mailbox failed "
 				"status %d, mbxStatus x%x\n", rc,
 				bf_get(lpfc_mqe_status, &mboxq->u.mqe));
 		retval = -EIO;
 	}
 	if (rc != MBX_TIMEOUT)
-		mempool_free(mboxq, phba->mbox_mem_pool);
+		mempool_free(mboxq, vport->phba->mbox_mem_pool);
 
 	return retval;
 }
@@ -12854,6 +13296,7 @@
 	struct lpfc_nodelist *act_mbx_ndlp = NULL;
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	LIST_HEAD(mbox_cmd_list);
+	uint8_t restart_loop;
 
 	/* Clean up internally queued mailbox commands with the vport */
 	spin_lock_irq(&phba->hbalock);
@@ -12882,15 +13325,44 @@
 			mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
 		}
 	}
+	/* Cleanup any mailbox completions which are not yet processed */
+	do {
+		restart_loop = 0;
+		list_for_each_entry(mb, &phba->sli.mboxq_cmpl, list) {
+			/*
+			 * If this mailox is already processed or it is
+			 * for another vport ignore it.
+			 */
+			if ((mb->vport != vport) ||
+				(mb->mbox_flag & LPFC_MBX_IMED_UNREG))
+				continue;
+
+			if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) &&
+				(mb->u.mb.mbxCommand != MBX_REG_VPI))
+				continue;
+
+			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+				ndlp = (struct lpfc_nodelist *)mb->context2;
+				/* Unregister the RPI when mailbox complete */
+				mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
+				restart_loop = 1;
+				spin_unlock_irq(&phba->hbalock);
+				spin_lock(shost->host_lock);
+				ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
+				spin_unlock(shost->host_lock);
+				spin_lock_irq(&phba->hbalock);
+				break;
+			}
+		}
+	} while (restart_loop);
+
 	spin_unlock_irq(&phba->hbalock);
 
 	/* Release the cleaned-up mailbox commands */
 	while (!list_empty(&mbox_cmd_list)) {
 		list_remove_head(&mbox_cmd_list, mb, LPFC_MBOXQ_t, list);
 		if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
-			if (phba->sli_rev == LPFC_SLI_REV4)
-				__lpfc_sli4_free_rpi(phba,
-						mb->u.mb.un.varRegLogin.rpi);
 			mp = (struct lpfc_dmabuf *) (mb->context1);
 			if (mp) {
 				__lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -12948,12 +13420,13 @@
 	while (pring->txq_cnt) {
 		spin_lock_irqsave(&phba->hbalock, iflags);
 
-		sglq = __lpfc_sli_get_sglq(phba);
+		piocbq = lpfc_sli_ringtx_get(phba, pring);
+		sglq = __lpfc_sli_get_sglq(phba, piocbq);
 		if (!sglq) {
+			__lpfc_sli_ringtx_put(phba, pring, piocbq);
 			spin_unlock_irqrestore(&phba->hbalock, iflags);
 			break;
 		} else {
-			piocbq = lpfc_sli_ringtx_get(phba, pring);
 			if (!piocbq) {
 				/* The txq_cnt out of sync. This should
 				 * never happen
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index cd56d6c..453577c 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -34,9 +34,11 @@
 	union {
 		struct lpfc_mcqe		mcqe_cmpl;
 		struct lpfc_acqe_link		acqe_link;
-		struct lpfc_acqe_fcoe		acqe_fcoe;
+		struct lpfc_acqe_fip		acqe_fip;
 		struct lpfc_acqe_dcbx		acqe_dcbx;
 		struct lpfc_acqe_grp5		acqe_grp5;
+		struct lpfc_acqe_fc_la		acqe_fc;
+		struct lpfc_acqe_sli		acqe_sli;
 		struct lpfc_rcqe		rcqe_cmpl;
 		struct sli4_wcqe_xri_aborted	wcqe_axri;
 		struct lpfc_wcqe_complete	wcqe_cmpl;
@@ -82,6 +84,7 @@
 		struct lpfc_iocbq    *rsp_iocb;
 		struct lpfcMboxq     *mbox;
 		struct lpfc_nodelist *ndlp;
+		struct lpfc_node_rrq *rrq;
 	} context_un;
 
 	void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index c4483fe..c7217d5 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -137,9 +137,11 @@
 	uint8_t speed;
 	uint8_t duplex;
 	uint8_t status;
-	uint8_t physical;
+	uint8_t type;
+	uint8_t number;
 	uint8_t fault;
 	uint16_t logical_speed;
+	uint16_t topology;
 };
 
 struct lpfc_fcf_rec {
@@ -367,23 +369,39 @@
 					     PCI BAR1, control registers */
 	void __iomem *drbl_regs_memmap_p; /* Kernel memory mapped address for
 					     PCI BAR2, doorbell registers */
-	/* BAR0 PCI config space register memory map */
-	void __iomem *UERRLOregaddr; /* Address to UERR_STATUS_LO register */
-	void __iomem *UERRHIregaddr; /* Address to UERR_STATUS_HI register */
-	void __iomem *UEMASKLOregaddr; /* Address to UE_MASK_LO register */
-	void __iomem *UEMASKHIregaddr; /* Address to UE_MASK_HI register */
-	void __iomem *SLIINTFregaddr; /* Address to SLI_INTF register */
-	/* BAR1 FCoE function CSR register memory map */
-	void __iomem *STAregaddr;    /* Address to HST_STATE register */
-	void __iomem *ISRregaddr;    /* Address to HST_ISR register */
-	void __iomem *IMRregaddr;    /* Address to HST_IMR register */
-	void __iomem *ISCRregaddr;   /* Address to HST_ISCR register */
-	/* BAR2 VF-0 doorbell register memory map */
-	void __iomem *RQDBregaddr;   /* Address to RQ_DOORBELL register */
-	void __iomem *WQDBregaddr;   /* Address to WQ_DOORBELL register */
-	void __iomem *EQCQDBregaddr; /* Address to EQCQ_DOORBELL register */
-	void __iomem *MQDBregaddr;   /* Address to MQ_DOORBELL register */
-	void __iomem *BMBXregaddr;   /* Address to BootStrap MBX register */
+	union {
+		struct {
+			/* IF Type 0, BAR 0 PCI cfg space reg mem map */
+			void __iomem *UERRLOregaddr;
+			void __iomem *UERRHIregaddr;
+			void __iomem *UEMASKLOregaddr;
+			void __iomem *UEMASKHIregaddr;
+		} if_type0;
+		struct {
+			/* IF Type 2, BAR 0 PCI cfg space reg mem map. */
+			void __iomem *STATUSregaddr;
+			void __iomem *CTRLregaddr;
+			void __iomem *ERR1regaddr;
+			void __iomem *ERR2regaddr;
+		} if_type2;
+	} u;
+
+	/* IF type 0, BAR1 and if type 2, Bar 0 CSR register memory map */
+	void __iomem *PSMPHRregaddr;
+
+	/* Well-known SLI INTF register memory map. */
+	void __iomem *SLIINTFregaddr;
+
+	/* IF type 0, BAR 1 function CSR register memory map */
+	void __iomem *ISRregaddr;	/* HST_ISR register */
+	void __iomem *IMRregaddr;	/* HST_IMR register */
+	void __iomem *ISCRregaddr;	/* HST_ISCR register */
+	/* IF type 0, BAR 0 and if type 2, BAR 0 doorbell register memory map */
+	void __iomem *RQDBregaddr;	/* RQ_DOORBELL register */
+	void __iomem *WQDBregaddr;	/* WQ_DOORBELL register */
+	void __iomem *EQCQDBregaddr;	/* EQCQ_DOORBELL register */
+	void __iomem *MQDBregaddr;	/* MQ_DOORBELL register */
+	void __iomem *BMBXregaddr;	/* BootStrap MBX register */
 
 	uint32_t ue_mask_lo;
 	uint32_t ue_mask_hi;
@@ -466,6 +484,7 @@
 	struct list_head clist;
 	enum lpfc_sge_type buff_type; /* is this a scsi sgl */
 	enum lpfc_sgl_state state;
+	struct lpfc_nodelist *ndlp; /* ndlp associated with IO */
 	uint16_t iotag;         /* pre-assigned IO tag */
 	uint16_t sli4_xritag;   /* pre-assigned XRI, (OXID) tag. */
 	struct sli4_sge *sgl;	/* pre-assigned SGL */
@@ -532,7 +551,6 @@
 struct lpfc_rpi_hdr *lpfc_sli4_create_rpi_hdr(struct lpfc_hba *);
 void lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *);
 int lpfc_sli4_alloc_rpi(struct lpfc_hba *);
-void __lpfc_sli4_free_rpi(struct lpfc_hba *, int);
 void lpfc_sli4_free_rpi(struct lpfc_hba *, int);
 void lpfc_sli4_remove_rpis(struct lpfc_hba *);
 void lpfc_sli4_async_event_proc(struct lpfc_hba *);
@@ -548,7 +566,7 @@
 int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *);
 void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *);
 int lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *);
-int lpfc_sli4_init_vpi(struct lpfc_hba *, uint16_t);
+int lpfc_sli4_init_vpi(struct lpfc_vport *);
 uint32_t lpfc_sli4_cq_release(struct lpfc_queue *, bool);
 uint32_t lpfc_sli4_eq_release(struct lpfc_queue *, bool);
 void lpfc_sli4_fcfi_unreg(struct lpfc_hba *, uint16_t);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 7a1b5b1..386cf92 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.18"
+#define LPFC_DRIVER_VERSION "8.3.20"
 #define LPFC_DRIVER_NAME		"lpfc"
 #define LPFC_SP_DRIVER_HANDLER_NAME	"lpfc:sp"
 #define LPFC_FP_DRIVER_HANDLER_NAME	"lpfc:fp"
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index a5281ce..6b8d295 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -395,8 +395,8 @@
 	 * by the port.
 	 */
 	if ((phba->sli_rev == LPFC_SLI_REV4) &&
-		(pport->fc_flag & FC_VFI_REGISTERED)) {
-		rc = lpfc_sli4_init_vpi(phba, vpi);
+	    (pport->fc_flag & FC_VFI_REGISTERED)) {
+		rc = lpfc_sli4_init_vpi(vport);
 		if (rc) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
 					"1838 Failed to INIT_VPI on vpi %d "
@@ -418,7 +418,7 @@
 
 	if ((phba->link_state < LPFC_LINK_UP) ||
 	    (pport->port_state < LPFC_FABRIC_CFG_LINK) ||
-	    (phba->fc_topology == TOPOLOGY_LOOP)) {
+	    (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
 		lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
 		rc = VPORT_OK;
 		goto out;
@@ -514,7 +514,7 @@
 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
 	if ((phba->link_state < LPFC_LINK_UP) ||
-	    (phba->fc_topology == TOPOLOGY_LOOP)) {
+	    (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
 		lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
 		return VPORT_OK;
 	}
@@ -665,7 +665,7 @@
 	if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
 	    ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
 	    phba->link_state >= LPFC_LINK_UP &&
-	    phba->fc_topology != TOPOLOGY_LOOP) {
+	    phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
 		if (vport->cfg_enable_da_id) {
 			timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
 			if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile
index f469915..5826ed5 100644
--- a/drivers/scsi/megaraid/Makefile
+++ b/drivers/scsi/megaraid/Makefile
@@ -1,3 +1,5 @@
 obj-$(CONFIG_MEGARAID_MM)	+= megaraid_mm.o
 obj-$(CONFIG_MEGARAID_MAILBOX)	+= megaraid_mbox.o
 obj-$(CONFIG_MEGARAID_SAS)	+= megaraid_sas.o
+megaraid_sas-objs := megaraid_sas_base.o megaraid_sas_fusion.o \
+	megaraid_sas_fp.o
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
deleted file mode 100644
index 7451bc0..0000000
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ /dev/null
@@ -1,5193 +0,0 @@
-/*
- *
- *		Linux MegaRAID driver for SAS based RAID controllers
- *
- * Copyright (c) 2003-2005  LSI 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.
- *
- * FILE		: megaraid_sas.c
- * Version     : v00.00.04.31-rc1
- *
- * Authors:
- *	(email-id : megaraidlinux@lsi.com)
- * 	Sreenivas Bagalkote
- * 	Sumant Patro
- *	Bo Yang
- *
- * List of supported controllers
- *
- * OEM	Product Name			VID	DID	SSVID	SSID
- * ---	------------			---	---	----	----
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/list.h>
-#include <linux/moduleparam.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/uio.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-#include <linux/fs.h>
-#include <linux/compat.h>
-#include <linux/blkdev.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include "megaraid_sas.h"
-
-/*
- * poll_mode_io:1- schedule complete completion from q cmd
- */
-static unsigned int poll_mode_io;
-module_param_named(poll_mode_io, poll_mode_io, int, 0);
-MODULE_PARM_DESC(poll_mode_io,
-	"Complete cmds from IO path, (default=0)");
-
-/*
- * Number of sectors per IO command
- * Will be set in megasas_init_mfi if user does not provide
- */
-static unsigned int max_sectors;
-module_param_named(max_sectors, max_sectors, int, 0);
-MODULE_PARM_DESC(max_sectors,
-	"Maximum number of sectors per IO command");
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MEGASAS_VERSION);
-MODULE_AUTHOR("megaraidlinux@lsi.com");
-MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
-
-static int megasas_transition_to_ready(struct megasas_instance *instance);
-static int megasas_get_pd_list(struct megasas_instance *instance);
-static int megasas_issue_init_mfi(struct megasas_instance *instance);
-static int megasas_register_aen(struct megasas_instance *instance,
-				u32 seq_num, u32 class_locale_word);
-/*
- * PCI ID table for all supported controllers
- */
-static struct pci_device_id megasas_pci_table[] = {
-
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)},
-	/* xscale IOP */
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
-	/* ppc IOP */
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
-	/* ppc IOP */
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
-	/* gen2*/
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
-	/* gen2*/
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)},
-	/* skinny*/
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)},
-	/* skinny*/
-	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
-	/* xscale IOP, vega */
-	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
-	/* xscale IOP */
-	{}
-};
-
-MODULE_DEVICE_TABLE(pci, megasas_pci_table);
-
-static int megasas_mgmt_majorno;
-static struct megasas_mgmt_info megasas_mgmt_info;
-static struct fasync_struct *megasas_async_queue;
-static DEFINE_MUTEX(megasas_async_queue_mutex);
-
-static int megasas_poll_wait_aen;
-static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
-static u32 support_poll_for_event;
-static u32 megasas_dbg_lvl;
-static u32 support_device_change;
-
-/* define lock for aen poll */
-spinlock_t poll_aen_lock;
-
-static void
-megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
-		     u8 alt_status);
-
-/**
- * megasas_get_cmd -	Get a command from the free pool
- * @instance:		Adapter soft state
- *
- * Returns a free command from the pool
- */
-static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
-						  *instance)
-{
-	unsigned long flags;
-	struct megasas_cmd *cmd = NULL;
-
-	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
-
-	if (!list_empty(&instance->cmd_pool)) {
-		cmd = list_entry((&instance->cmd_pool)->next,
-				 struct megasas_cmd, list);
-		list_del_init(&cmd->list);
-	} else {
-		printk(KERN_ERR "megasas: Command pool empty!\n");
-	}
-
-	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
-	return cmd;
-}
-
-/**
- * megasas_return_cmd -	Return a cmd to free command pool
- * @instance:		Adapter soft state
- * @cmd:		Command packet to be returned to free command pool
- */
-static inline void
-megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
-
-	cmd->scmd = NULL;
-	list_add_tail(&cmd->list, &instance->cmd_pool);
-
-	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
-}
-
-
-/**
-*	The following functions are defined for xscale 
-*	(deviceid : 1064R, PERC5) controllers
-*/
-
-/**
- * megasas_enable_intr_xscale -	Enables interrupts
- * @regs:			MFI register set
- */
-static inline void
-megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
-{
-	writel(0, &(regs)->outbound_intr_mask);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_disable_intr_xscale -Disables interrupt
- * @regs:			MFI register set
- */
-static inline void
-megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs)
-{
-	u32 mask = 0x1f;
-	writel(mask, &regs->outbound_intr_mask);
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_read_fw_status_reg_xscale - returns the current FW status value
- * @regs:			MFI register set
- */
-static u32
-megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs)
-{
-	return readl(&(regs)->outbound_msg_0);
-}
-/**
- * megasas_clear_interrupt_xscale -	Check & clear interrupt
- * @regs:				MFI register set
- */
-static int 
-megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
-{
-	u32 status;
-	u32 mfiStatus = 0;
-	/*
-	 * Check if it is our interrupt
-	 */
-	status = readl(&regs->outbound_intr_status);
-
-	if (status & MFI_OB_INTR_STATUS_MASK)
-		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
-	if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT)
-		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
-
-	/*
-	 * Clear the interrupt by writing back the same value
-	 */
-	if (mfiStatus)
-		writel(status, &regs->outbound_intr_status);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_status);
-
-	return mfiStatus;
-}
-
-/**
- * megasas_fire_cmd_xscale -	Sends command to the FW
- * @frame_phys_addr :		Physical address of cmd
- * @frame_count :		Number of frames for the command
- * @regs :			MFI register set
- */
-static inline void 
-megasas_fire_cmd_xscale(struct megasas_instance *instance,
-		dma_addr_t frame_phys_addr,
-		u32 frame_count,
-		struct megasas_register_set __iomem *regs)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	writel((frame_phys_addr >> 3)|(frame_count),
-	       &(regs)->inbound_queue_port);
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-}
-
-/**
- * megasas_adp_reset_xscale -  For controller reset
- * @regs:                              MFI register set
- */
-static int
-megasas_adp_reset_xscale(struct megasas_instance *instance,
-	struct megasas_register_set __iomem *regs)
-{
-	u32 i;
-	u32 pcidata;
-	writel(MFI_ADP_RESET, &regs->inbound_doorbell);
-
-	for (i = 0; i < 3; i++)
-		msleep(1000); /* sleep for 3 secs */
-	pcidata  = 0;
-	pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata);
-	printk(KERN_NOTICE "pcidata = %x\n", pcidata);
-	if (pcidata & 0x2) {
-		printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata);
-		pcidata &= ~0x2;
-		pci_write_config_dword(instance->pdev,
-				MFI_1068_PCSR_OFFSET, pcidata);
-
-		for (i = 0; i < 2; i++)
-			msleep(1000); /* need to wait 2 secs again */
-
-		pcidata  = 0;
-		pci_read_config_dword(instance->pdev,
-				MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata);
-		printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
-		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
-			printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata);
-			pcidata = 0;
-			pci_write_config_dword(instance->pdev,
-				MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
-		}
-	}
-	return 0;
-}
-
-/**
- * megasas_check_reset_xscale -	For controller reset check
- * @regs:				MFI register set
- */
-static int
-megasas_check_reset_xscale(struct megasas_instance *instance,
-		struct megasas_register_set __iomem *regs)
-{
-	u32 consumer;
-	consumer = *instance->consumer;
-
-	if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) &&
-		(*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
-		return 1;
-	}
-	return 0;
-}
-
-static struct megasas_instance_template megasas_instance_template_xscale = {
-
-	.fire_cmd = megasas_fire_cmd_xscale,
-	.enable_intr = megasas_enable_intr_xscale,
-	.disable_intr = megasas_disable_intr_xscale,
-	.clear_intr = megasas_clear_intr_xscale,
-	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
-	.adp_reset = megasas_adp_reset_xscale,
-	.check_reset = megasas_check_reset_xscale,
-};
-
-/**
-*	This is the end of set of functions & definitions specific 
-*	to xscale (deviceid : 1064R, PERC5) controllers
-*/
-
-/**
-*	The following functions are defined for ppc (deviceid : 0x60) 
-* 	controllers
-*/
-
-/**
- * megasas_enable_intr_ppc -	Enables interrupts
- * @regs:			MFI register set
- */
-static inline void
-megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
-{
-	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
-    
-	writel(~0x80000000, &(regs)->outbound_intr_mask);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_disable_intr_ppc -	Disable interrupt
- * @regs:			MFI register set
- */
-static inline void
-megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs)
-{
-	u32 mask = 0xFFFFFFFF;
-	writel(mask, &regs->outbound_intr_mask);
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_read_fw_status_reg_ppc - returns the current FW status value
- * @regs:			MFI register set
- */
-static u32
-megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
-{
-	return readl(&(regs)->outbound_scratch_pad);
-}
-
-/**
- * megasas_clear_interrupt_ppc -	Check & clear interrupt
- * @regs:				MFI register set
- */
-static int 
-megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
-{
-	u32 status;
-	/*
-	 * Check if it is our interrupt
-	 */
-	status = readl(&regs->outbound_intr_status);
-
-	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
-		return 0;
-	}
-
-	/*
-	 * Clear the interrupt by writing back the same value
-	 */
-	writel(status, &regs->outbound_doorbell_clear);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_doorbell_clear);
-
-	return 1;
-}
-/**
- * megasas_fire_cmd_ppc -	Sends command to the FW
- * @frame_phys_addr :		Physical address of cmd
- * @frame_count :		Number of frames for the command
- * @regs :			MFI register set
- */
-static inline void 
-megasas_fire_cmd_ppc(struct megasas_instance *instance,
-		dma_addr_t frame_phys_addr,
-		u32 frame_count,
-		struct megasas_register_set __iomem *regs)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	writel((frame_phys_addr | (frame_count<<1))|1, 
-			&(regs)->inbound_queue_port);
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-}
-
-/**
- * megasas_adp_reset_ppc -	For controller reset
- * @regs:				MFI register set
- */
-static int
-megasas_adp_reset_ppc(struct megasas_instance *instance,
-			struct megasas_register_set __iomem *regs)
-{
-	return 0;
-}
-
-/**
- * megasas_check_reset_ppc -	For controller reset check
- * @regs:				MFI register set
- */
-static int
-megasas_check_reset_ppc(struct megasas_instance *instance,
-			struct megasas_register_set __iomem *regs)
-{
-	return 0;
-}
-static struct megasas_instance_template megasas_instance_template_ppc = {
-	
-	.fire_cmd = megasas_fire_cmd_ppc,
-	.enable_intr = megasas_enable_intr_ppc,
-	.disable_intr = megasas_disable_intr_ppc,
-	.clear_intr = megasas_clear_intr_ppc,
-	.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
-	.adp_reset = megasas_adp_reset_ppc,
-	.check_reset = megasas_check_reset_ppc,
-};
-
-/**
- * megasas_enable_intr_skinny -	Enables interrupts
- * @regs:			MFI register set
- */
-static inline void
-megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
-{
-	writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
-
-	writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_disable_intr_skinny -	Disables interrupt
- * @regs:			MFI register set
- */
-static inline void
-megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
-{
-	u32 mask = 0xFFFFFFFF;
-	writel(mask, &regs->outbound_intr_mask);
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_read_fw_status_reg_skinny - returns the current FW status value
- * @regs:			MFI register set
- */
-static u32
-megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs)
-{
-	return readl(&(regs)->outbound_scratch_pad);
-}
-
-/**
- * megasas_clear_interrupt_skinny -	Check & clear interrupt
- * @regs:				MFI register set
- */
-static int
-megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
-{
-	u32 status;
-	/*
-	 * Check if it is our interrupt
-	 */
-	status = readl(&regs->outbound_intr_status);
-
-	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
-		return 0;
-	}
-
-	/*
-	 * Clear the interrupt by writing back the same value
-	 */
-	writel(status, &regs->outbound_intr_status);
-
-	/*
-	* dummy read to flush PCI
-	*/
-	readl(&regs->outbound_intr_status);
-
-	return 1;
-}
-
-/**
- * megasas_fire_cmd_skinny -	Sends command to the FW
- * @frame_phys_addr :		Physical address of cmd
- * @frame_count :		Number of frames for the command
- * @regs :			MFI register set
- */
-static inline void
-megasas_fire_cmd_skinny(struct megasas_instance *instance,
-			dma_addr_t frame_phys_addr,
-			u32 frame_count,
-			struct megasas_register_set __iomem *regs)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	writel(0, &(regs)->inbound_high_queue_port);
-	writel((frame_phys_addr | (frame_count<<1))|1,
-		&(regs)->inbound_low_queue_port);
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-}
-
-/**
- * megasas_adp_reset_skinny -	For controller reset
- * @regs:				MFI register set
- */
-static int
-megasas_adp_reset_skinny(struct megasas_instance *instance,
-			struct megasas_register_set __iomem *regs)
-{
-	return 0;
-}
-
-/**
- * megasas_check_reset_skinny -	For controller reset check
- * @regs:				MFI register set
- */
-static int
-megasas_check_reset_skinny(struct megasas_instance *instance,
-				struct megasas_register_set __iomem *regs)
-{
-	return 0;
-}
-
-static struct megasas_instance_template megasas_instance_template_skinny = {
-
-	.fire_cmd = megasas_fire_cmd_skinny,
-	.enable_intr = megasas_enable_intr_skinny,
-	.disable_intr = megasas_disable_intr_skinny,
-	.clear_intr = megasas_clear_intr_skinny,
-	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
-	.adp_reset = megasas_adp_reset_skinny,
-	.check_reset = megasas_check_reset_skinny,
-};
-
-
-/**
-*	The following functions are defined for gen2 (deviceid : 0x78 0x79)
-*	controllers
-*/
-
-/**
- * megasas_enable_intr_gen2 -  Enables interrupts
- * @regs:                      MFI register set
- */
-static inline void
-megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
-{
-	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
-
-	/* write ~0x00000005 (4 & 1) to the intr mask*/
-	writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_disable_intr_gen2 - Disables interrupt
- * @regs:                      MFI register set
- */
-static inline void
-megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
-{
-	u32 mask = 0xFFFFFFFF;
-	writel(mask, &regs->outbound_intr_mask);
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_mask);
-}
-
-/**
- * megasas_read_fw_status_reg_gen2 - returns the current FW status value
- * @regs:                      MFI register set
- */
-static u32
-megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
-{
-	return readl(&(regs)->outbound_scratch_pad);
-}
-
-/**
- * megasas_clear_interrupt_gen2 -      Check & clear interrupt
- * @regs:                              MFI register set
- */
-static int
-megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
-{
-	u32 status;
-	u32 mfiStatus = 0;
-	/*
-	 * Check if it is our interrupt
-	 */
-	status = readl(&regs->outbound_intr_status);
-
-	if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) {
-		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
-	}
-	if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) {
-		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
-	}
-
-	/*
-	 * Clear the interrupt by writing back the same value
-	 */
-	if (mfiStatus)
-		writel(status, &regs->outbound_doorbell_clear);
-
-	/* Dummy readl to force pci flush */
-	readl(&regs->outbound_intr_status);
-
-	return mfiStatus;
-}
-/**
- * megasas_fire_cmd_gen2 -     Sends command to the FW
- * @frame_phys_addr :          Physical address of cmd
- * @frame_count :              Number of frames for the command
- * @regs :                     MFI register set
- */
-static inline void
-megasas_fire_cmd_gen2(struct megasas_instance *instance,
-			dma_addr_t frame_phys_addr,
-			u32 frame_count,
-			struct megasas_register_set __iomem *regs)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	writel((frame_phys_addr | (frame_count<<1))|1,
-			&(regs)->inbound_queue_port);
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-}
-
-/**
- * megasas_adp_reset_gen2 -	For controller reset
- * @regs:				MFI register set
- */
-static int
-megasas_adp_reset_gen2(struct megasas_instance *instance,
-			struct megasas_register_set __iomem *reg_set)
-{
-	u32			retry = 0 ;
-	u32			HostDiag;
-
-	writel(0, &reg_set->seq_offset);
-	writel(4, &reg_set->seq_offset);
-	writel(0xb, &reg_set->seq_offset);
-	writel(2, &reg_set->seq_offset);
-	writel(7, &reg_set->seq_offset);
-	writel(0xd, &reg_set->seq_offset);
-	msleep(1000);
-
-	HostDiag = (u32)readl(&reg_set->host_diag);
-
-	while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
-		msleep(100);
-		HostDiag = (u32)readl(&reg_set->host_diag);
-		printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
-					retry, HostDiag);
-
-		if (retry++ >= 100)
-			return 1;
-
-	}
-
-	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
-
-	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
-
-	ssleep(10);
-
-	HostDiag = (u32)readl(&reg_set->host_diag);
-	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
-		msleep(100);
-		HostDiag = (u32)readl(&reg_set->host_diag);
-		printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
-				retry, HostDiag);
-
-		if (retry++ >= 1000)
-			return 1;
-
-	}
-	return 0;
-}
-
-/**
- * megasas_check_reset_gen2 -	For controller reset check
- * @regs:				MFI register set
- */
-static int
-megasas_check_reset_gen2(struct megasas_instance *instance,
-		struct megasas_register_set __iomem *regs)
-{
-	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
-		return 1;
-	}
-
-	return 0;
-}
-
-static struct megasas_instance_template megasas_instance_template_gen2 = {
-
-	.fire_cmd = megasas_fire_cmd_gen2,
-	.enable_intr = megasas_enable_intr_gen2,
-	.disable_intr = megasas_disable_intr_gen2,
-	.clear_intr = megasas_clear_intr_gen2,
-	.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
-	.adp_reset = megasas_adp_reset_gen2,
-	.check_reset = megasas_check_reset_gen2,
-};
-
-/**
-*	This is the end of set of functions & definitions
-*       specific to gen2 (deviceid : 0x78, 0x79) controllers
-*/
-
-/**
- * megasas_issue_polled -	Issues a polling command
- * @instance:			Adapter soft state
- * @cmd:			Command packet to be issued 
- *
- * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
- */
-static int
-megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
-{
-	int i;
-	u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
-
-	struct megasas_header *frame_hdr = &cmd->frame->hdr;
-
-	frame_hdr->cmd_status = 0xFF;
-	frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
-
-	/*
-	 * Issue the frame using inbound queue port
-	 */
-	instance->instancet->fire_cmd(instance,
-			cmd->frame_phys_addr, 0, instance->reg_set);
-
-	/*
-	 * Wait for cmd_status to change
-	 */
-	for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
-		rmb();
-		msleep(1);
-	}
-
-	if (frame_hdr->cmd_status == 0xff)
-		return -ETIME;
-
-	return 0;
-}
-
-/**
- * megasas_issue_blocked_cmd -	Synchronous wrapper around regular FW cmds
- * @instance:			Adapter soft state
- * @cmd:			Command to be issued
- *
- * This function waits on an event for the command to be returned from ISR.
- * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
- * Used to issue ioctl commands.
- */
-static int
-megasas_issue_blocked_cmd(struct megasas_instance *instance,
-			  struct megasas_cmd *cmd)
-{
-	cmd->cmd_status = ENODATA;
-
-	instance->instancet->fire_cmd(instance,
-			cmd->frame_phys_addr, 0, instance->reg_set);
-
-	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
-
-	return 0;
-}
-
-/**
- * megasas_issue_blocked_abort_cmd -	Aborts previously issued cmd
- * @instance:				Adapter soft state
- * @cmd_to_abort:			Previously issued cmd to be aborted
- *
- * MFI firmware can abort previously issued AEN comamnd (automatic event
- * notification). The megasas_issue_blocked_abort_cmd() issues such abort
- * cmd and waits for return status.
- * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
- */
-static int
-megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
-				struct megasas_cmd *cmd_to_abort)
-{
-	struct megasas_cmd *cmd;
-	struct megasas_abort_frame *abort_fr;
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd)
-		return -1;
-
-	abort_fr = &cmd->frame->abort;
-
-	/*
-	 * Prepare and issue the abort frame
-	 */
-	abort_fr->cmd = MFI_CMD_ABORT;
-	abort_fr->cmd_status = 0xFF;
-	abort_fr->flags = 0;
-	abort_fr->abort_context = cmd_to_abort->index;
-	abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
-	abort_fr->abort_mfi_phys_addr_hi = 0;
-
-	cmd->sync_cmd = 1;
-	cmd->cmd_status = 0xFF;
-
-	instance->instancet->fire_cmd(instance,
-			cmd->frame_phys_addr, 0, instance->reg_set);
-
-	/*
-	 * Wait for this cmd to complete
-	 */
-	wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
-	cmd->sync_cmd = 0;
-
-	megasas_return_cmd(instance, cmd);
-	return 0;
-}
-
-/**
- * megasas_make_sgl32 -	Prepares 32-bit SGL
- * @instance:		Adapter soft state
- * @scp:		SCSI command from the mid-layer
- * @mfi_sgl:		SGL to be filled in
- *
- * If successful, this function returns the number of SG elements. Otherwise,
- * it returnes -1.
- */
-static int
-megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
-		   union megasas_sgl *mfi_sgl)
-{
-	int i;
-	int sge_count;
-	struct scatterlist *os_sgl;
-
-	sge_count = scsi_dma_map(scp);
-	BUG_ON(sge_count < 0);
-
-	if (sge_count) {
-		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
-			mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
-			mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
-		}
-	}
-	return sge_count;
-}
-
-/**
- * megasas_make_sgl64 -	Prepares 64-bit SGL
- * @instance:		Adapter soft state
- * @scp:		SCSI command from the mid-layer
- * @mfi_sgl:		SGL to be filled in
- *
- * If successful, this function returns the number of SG elements. Otherwise,
- * it returnes -1.
- */
-static int
-megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
-		   union megasas_sgl *mfi_sgl)
-{
-	int i;
-	int sge_count;
-	struct scatterlist *os_sgl;
-
-	sge_count = scsi_dma_map(scp);
-	BUG_ON(sge_count < 0);
-
-	if (sge_count) {
-		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
-			mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
-			mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
-		}
-	}
-	return sge_count;
-}
-
-/**
- * megasas_make_sgl_skinny - Prepares IEEE SGL
- * @instance:           Adapter soft state
- * @scp:                SCSI command from the mid-layer
- * @mfi_sgl:            SGL to be filled in
- *
- * If successful, this function returns the number of SG elements. Otherwise,
- * it returnes -1.
- */
-static int
-megasas_make_sgl_skinny(struct megasas_instance *instance,
-		struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
-{
-	int i;
-	int sge_count;
-	struct scatterlist *os_sgl;
-
-	sge_count = scsi_dma_map(scp);
-
-	if (sge_count) {
-		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
-			mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
-			mfi_sgl->sge_skinny[i].phys_addr =
-						sg_dma_address(os_sgl);
-			mfi_sgl->sge_skinny[i].flag = 0;
-		}
-	}
-	return sge_count;
-}
-
- /**
- * megasas_get_frame_count - Computes the number of frames
- * @frame_type		: type of frame- io or pthru frame
- * @sge_count		: number of sg elements
- *
- * Returns the number of frames required for numnber of sge's (sge_count)
- */
-
-static u32 megasas_get_frame_count(struct megasas_instance *instance,
-			u8 sge_count, u8 frame_type)
-{
-	int num_cnt;
-	int sge_bytes;
-	u32 sge_sz;
-	u32 frame_count=0;
-
-	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
-	    sizeof(struct megasas_sge32);
-
-	if (instance->flag_ieee) {
-		sge_sz = sizeof(struct megasas_sge_skinny);
-	}
-
-	/*
-	 * Main frame can contain 2 SGEs for 64-bit SGLs and
-	 * 3 SGEs for 32-bit SGLs for ldio &
-	 * 1 SGEs for 64-bit SGLs and
-	 * 2 SGEs for 32-bit SGLs for pthru frame
-	 */
-	if (unlikely(frame_type == PTHRU_FRAME)) {
-		if (instance->flag_ieee == 1) {
-			num_cnt = sge_count - 1;
-		} else if (IS_DMA64)
-			num_cnt = sge_count - 1;
-		else
-			num_cnt = sge_count - 2;
-	} else {
-		if (instance->flag_ieee == 1) {
-			num_cnt = sge_count - 1;
-		} else if (IS_DMA64)
-			num_cnt = sge_count - 2;
-		else
-			num_cnt = sge_count - 3;
-	}
-
-	if(num_cnt>0){
-		sge_bytes = sge_sz * num_cnt;
-
-		frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
-		    ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ;
-	}
-	/* Main frame */
-	frame_count +=1;
-
-	if (frame_count > 7)
-		frame_count = 8;
-	return frame_count;
-}
-
-/**
- * megasas_build_dcdb -	Prepares a direct cdb (DCDB) command
- * @instance:		Adapter soft state
- * @scp:		SCSI command
- * @cmd:		Command to be prepared in
- *
- * This function prepares CDB commands. These are typcially pass-through
- * commands to the devices.
- */
-static int
-megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
-		   struct megasas_cmd *cmd)
-{
-	u32 is_logical;
-	u32 device_id;
-	u16 flags = 0;
-	struct megasas_pthru_frame *pthru;
-
-	is_logical = MEGASAS_IS_LOGICAL(scp);
-	device_id = MEGASAS_DEV_INDEX(instance, scp);
-	pthru = (struct megasas_pthru_frame *)cmd->frame;
-
-	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
-		flags = MFI_FRAME_DIR_WRITE;
-	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
-		flags = MFI_FRAME_DIR_READ;
-	else if (scp->sc_data_direction == PCI_DMA_NONE)
-		flags = MFI_FRAME_DIR_NONE;
-
-	if (instance->flag_ieee == 1) {
-		flags |= MFI_FRAME_IEEE;
-	}
-
-	/*
-	 * Prepare the DCDB frame
-	 */
-	pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO;
-	pthru->cmd_status = 0x0;
-	pthru->scsi_status = 0x0;
-	pthru->target_id = device_id;
-	pthru->lun = scp->device->lun;
-	pthru->cdb_len = scp->cmd_len;
-	pthru->timeout = 0;
-	pthru->pad_0 = 0;
-	pthru->flags = flags;
-	pthru->data_xfer_len = scsi_bufflen(scp);
-
-	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
-
-	/*
-	* If the command is for the tape device, set the
-	* pthru timeout to the os layer timeout value.
-	*/
-	if (scp->device->type == TYPE_TAPE) {
-		if ((scp->request->timeout / HZ) > 0xFFFF)
-			pthru->timeout = 0xFFFF;
-		else
-			pthru->timeout = scp->request->timeout / HZ;
-	}
-
-	/*
-	 * Construct SGL
-	 */
-	if (instance->flag_ieee == 1) {
-		pthru->flags |= MFI_FRAME_SGL64;
-		pthru->sge_count = megasas_make_sgl_skinny(instance, scp,
-						      &pthru->sgl);
-	} else if (IS_DMA64) {
-		pthru->flags |= MFI_FRAME_SGL64;
-		pthru->sge_count = megasas_make_sgl64(instance, scp,
-						      &pthru->sgl);
-	} else
-		pthru->sge_count = megasas_make_sgl32(instance, scp,
-						      &pthru->sgl);
-
-	if (pthru->sge_count > instance->max_num_sge) {
-		printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n",
-			pthru->sge_count);
-		return 0;
-	}
-
-	/*
-	 * Sense info specific
-	 */
-	pthru->sense_len = SCSI_SENSE_BUFFERSIZE;
-	pthru->sense_buf_phys_addr_hi = 0;
-	pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
-
-	/*
-	 * Compute the total number of frames this command consumes. FW uses
-	 * this number to pull sufficient number of frames from host memory.
-	 */
-	cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count,
-							PTHRU_FRAME);
-
-	return cmd->frame_count;
-}
-
-/**
- * megasas_build_ldio -	Prepares IOs to logical devices
- * @instance:		Adapter soft state
- * @scp:		SCSI command
- * @cmd:		Command to be prepared
- *
- * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
- */
-static int
-megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
-		   struct megasas_cmd *cmd)
-{
-	u32 device_id;
-	u8 sc = scp->cmnd[0];
-	u16 flags = 0;
-	struct megasas_io_frame *ldio;
-
-	device_id = MEGASAS_DEV_INDEX(instance, scp);
-	ldio = (struct megasas_io_frame *)cmd->frame;
-
-	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
-		flags = MFI_FRAME_DIR_WRITE;
-	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
-		flags = MFI_FRAME_DIR_READ;
-
-	if (instance->flag_ieee == 1) {
-		flags |= MFI_FRAME_IEEE;
-	}
-
-	/*
-	 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
-	 */
-	ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ;
-	ldio->cmd_status = 0x0;
-	ldio->scsi_status = 0x0;
-	ldio->target_id = device_id;
-	ldio->timeout = 0;
-	ldio->reserved_0 = 0;
-	ldio->pad_0 = 0;
-	ldio->flags = flags;
-	ldio->start_lba_hi = 0;
-	ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0;
-
-	/*
-	 * 6-byte READ(0x08) or WRITE(0x0A) cdb
-	 */
-	if (scp->cmd_len == 6) {
-		ldio->lba_count = (u32) scp->cmnd[4];
-		ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) |
-		    ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
-
-		ldio->start_lba_lo &= 0x1FFFFF;
-	}
-
-	/*
-	 * 10-byte READ(0x28) or WRITE(0x2A) cdb
-	 */
-	else if (scp->cmd_len == 10) {
-		ldio->lba_count = (u32) scp->cmnd[8] |
-		    ((u32) scp->cmnd[7] << 8);
-		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
-		    ((u32) scp->cmnd[3] << 16) |
-		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
-	}
-
-	/*
-	 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
-	 */
-	else if (scp->cmd_len == 12) {
-		ldio->lba_count = ((u32) scp->cmnd[6] << 24) |
-		    ((u32) scp->cmnd[7] << 16) |
-		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
-
-		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
-		    ((u32) scp->cmnd[3] << 16) |
-		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
-	}
-
-	/*
-	 * 16-byte READ(0x88) or WRITE(0x8A) cdb
-	 */
-	else if (scp->cmd_len == 16) {
-		ldio->lba_count = ((u32) scp->cmnd[10] << 24) |
-		    ((u32) scp->cmnd[11] << 16) |
-		    ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
-
-		ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) |
-		    ((u32) scp->cmnd[7] << 16) |
-		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
-
-		ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) |
-		    ((u32) scp->cmnd[3] << 16) |
-		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
-
-	}
-
-	/*
-	 * Construct SGL
-	 */
-	if (instance->flag_ieee) {
-		ldio->flags |= MFI_FRAME_SGL64;
-		ldio->sge_count = megasas_make_sgl_skinny(instance, scp,
-					      &ldio->sgl);
-	} else if (IS_DMA64) {
-		ldio->flags |= MFI_FRAME_SGL64;
-		ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
-	} else
-		ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
-
-	if (ldio->sge_count > instance->max_num_sge) {
-		printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n",
-			ldio->sge_count);
-		return 0;
-	}
-
-	/*
-	 * Sense info specific
-	 */
-	ldio->sense_len = SCSI_SENSE_BUFFERSIZE;
-	ldio->sense_buf_phys_addr_hi = 0;
-	ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
-
-	/*
-	 * Compute the total number of frames this command consumes. FW uses
-	 * this number to pull sufficient number of frames from host memory.
-	 */
-	cmd->frame_count = megasas_get_frame_count(instance,
-			ldio->sge_count, IO_FRAME);
-
-	return cmd->frame_count;
-}
-
-/**
- * megasas_is_ldio -		Checks if the cmd is for logical drive
- * @scmd:			SCSI command
- *	
- * Called by megasas_queue_command to find out if the command to be queued
- * is a logical drive command	
- */
-static inline int megasas_is_ldio(struct scsi_cmnd *cmd)
-{
-	if (!MEGASAS_IS_LOGICAL(cmd))
-		return 0;
-	switch (cmd->cmnd[0]) {
-	case READ_10:
-	case WRITE_10:
-	case READ_12:
-	case WRITE_12:
-	case READ_6:
-	case WRITE_6:
-	case READ_16:
-	case WRITE_16:
-		return 1;
-	default:
-		return 0;
-	}
-}
-
- /**
- * megasas_dump_pending_frames -	Dumps the frame address of all pending cmds
- *                              	in FW
- * @instance:				Adapter soft state
- */
-static inline void
-megasas_dump_pending_frames(struct megasas_instance *instance)
-{
-	struct megasas_cmd *cmd;
-	int i,n;
-	union megasas_sgl *mfi_sgl;
-	struct megasas_io_frame *ldio;
-	struct megasas_pthru_frame *pthru;
-	u32 sgcount;
-	u32 max_cmd = instance->max_fw_cmds;
-
-	printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no);
-	printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding));
-	if (IS_DMA64)
-		printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no);
-	else
-		printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no);
-
-	printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no);
-	for (i = 0; i < max_cmd; i++) {
-		cmd = instance->cmd_list[i];
-		if(!cmd->scmd)
-			continue;
-		printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr);
-		if (megasas_is_ldio(cmd->scmd)){
-			ldio = (struct megasas_io_frame *)cmd->frame;
-			mfi_sgl = &ldio->sgl;
-			sgcount = ldio->sge_count;
-			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount);
-		}
-		else {
-			pthru = (struct megasas_pthru_frame *) cmd->frame;
-			mfi_sgl = &pthru->sgl;
-			sgcount = pthru->sge_count;
-			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount);
-		}
-	if(megasas_dbg_lvl & MEGASAS_DBG_LVL){
-		for (n = 0; n < sgcount; n++){
-			if (IS_DMA64)
-				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ;
-			else
-				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ;
-			}
-		}
-		printk(KERN_ERR "\n");
-	} /*for max_cmd*/
-	printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no);
-	for (i = 0; i < max_cmd; i++) {
-
-		cmd = instance->cmd_list[i];
-
-		if(cmd->sync_cmd == 1){
-			printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr);
-		}
-	}
-	printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
-}
-
-/**
- * megasas_queue_command -	Queue entry point
- * @scmd:			SCSI command to be queued
- * @done:			Callback entry point
- */
-static int
-megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
-{
-	u32 frame_count;
-	struct megasas_cmd *cmd;
-	struct megasas_instance *instance;
-	unsigned long flags;
-
-	instance = (struct megasas_instance *)
-	    scmd->device->host->hostdata;
-
-	if (instance->issuepend_done == 0)
-		return SCSI_MLQUEUE_HOST_BUSY;
-
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-		return SCSI_MLQUEUE_HOST_BUSY;
-	}
-
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-	scmd->scsi_done = done;
-	scmd->result = 0;
-
-	if (MEGASAS_IS_LOGICAL(scmd) &&
-	    (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
-		scmd->result = DID_BAD_TARGET << 16;
-		goto out_done;
-	}
-
-	switch (scmd->cmnd[0]) {
-	case SYNCHRONIZE_CACHE:
-		/*
-		 * FW takes care of flush cache on its own
-		 * No need to send it down
-		 */
-		scmd->result = DID_OK << 16;
-		goto out_done;
-	default:
-		break;
-	}
-
-	cmd = megasas_get_cmd(instance);
-	if (!cmd)
-		return SCSI_MLQUEUE_HOST_BUSY;
-
-	/*
-	 * Logical drive command
-	 */
-	if (megasas_is_ldio(scmd))
-		frame_count = megasas_build_ldio(instance, scmd, cmd);
-	else
-		frame_count = megasas_build_dcdb(instance, scmd, cmd);
-
-	if (!frame_count)
-		goto out_return_cmd;
-
-	cmd->scmd = scmd;
-	scmd->SCp.ptr = (char *)cmd;
-
-	/*
-	 * Issue the command to the FW
-	 */
-	atomic_inc(&instance->fw_outstanding);
-
-	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
-				cmd->frame_count-1, instance->reg_set);
-	/*
-	 * Check if we have pend cmds to be completed
-	 */
-	if (poll_mode_io && atomic_read(&instance->fw_outstanding))
-		tasklet_schedule(&instance->isr_tasklet);
-
-
-	return 0;
-
- out_return_cmd:
-	megasas_return_cmd(instance, cmd);
- out_done:
-	done(scmd);
-	return 0;
-}
-
-static DEF_SCSI_QCMD(megasas_queue_command)
-
-static struct megasas_instance *megasas_lookup_instance(u16 host_no)
-{
-	int i;
-
-	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-
-		if ((megasas_mgmt_info.instance[i]) &&
-		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
-			return megasas_mgmt_info.instance[i];
-	}
-
-	return NULL;
-}
-
-static int megasas_slave_configure(struct scsi_device *sdev)
-{
-	u16             pd_index = 0;
-	struct  megasas_instance *instance ;
-
-	instance = megasas_lookup_instance(sdev->host->host_no);
-
-	/*
-	* Don't export physical disk devices to the disk driver.
-	*
-	* FIXME: Currently we don't export them to the midlayer at all.
-	*        That will be fixed once LSI engineers have audited the
-	*        firmware for possible issues.
-	*/
-	if (sdev->channel < MEGASAS_MAX_PD_CHANNELS &&
-				sdev->type == TYPE_DISK) {
-		pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
-								sdev->id;
-		if (instance->pd_list[pd_index].driveState ==
-						MR_PD_STATE_SYSTEM) {
-			blk_queue_rq_timeout(sdev->request_queue,
-				MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
-			return 0;
-		}
-		return -ENXIO;
-	}
-
-	/*
-	* The RAID firmware may require extended timeouts.
-	*/
-	blk_queue_rq_timeout(sdev->request_queue,
-		MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
-	return 0;
-}
-
-static int megasas_slave_alloc(struct scsi_device *sdev)
-{
-	u16             pd_index = 0;
-	struct megasas_instance *instance ;
-	instance = megasas_lookup_instance(sdev->host->host_no);
-	if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) &&
-				(sdev->type == TYPE_DISK)) {
-		/*
-		 * Open the OS scan to the SYSTEM PD
-		 */
-		pd_index =
-			(sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
-			sdev->id;
-		if ((instance->pd_list[pd_index].driveState ==
-					MR_PD_STATE_SYSTEM) &&
-			(instance->pd_list[pd_index].driveType ==
-						TYPE_DISK)) {
-			return 0;
-		}
-		return -ENXIO;
-	}
-	return 0;
-}
-
-static void megaraid_sas_kill_hba(struct megasas_instance *instance)
-{
-	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-		writel(MFI_STOP_ADP,
-			&instance->reg_set->reserved_0[0]);
-	} else {
-		writel(MFI_STOP_ADP,
-			&instance->reg_set->inbound_doorbell);
-	}
-}
-
-/**
- * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
- * @instance_addr:			Address of adapter soft state
- *
- * Tasklet to complete cmds
- */
-static void megasas_complete_cmd_dpc(unsigned long instance_addr)
-{
-	u32 producer;
-	u32 consumer;
-	u32 context;
-	struct megasas_cmd *cmd;
-	struct megasas_instance *instance =
-				(struct megasas_instance *)instance_addr;
-	unsigned long flags;
-
-	/* If we have already declared adapter dead, donot complete cmds */
-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
-		return;
-
-	spin_lock_irqsave(&instance->completion_lock, flags);
-
-	producer = *instance->producer;
-	consumer = *instance->consumer;
-
-	while (consumer != producer) {
-		context = instance->reply_queue[consumer];
-		if (context >= instance->max_fw_cmds) {
-			printk(KERN_ERR "Unexpected context value %x\n",
-				context);
-			BUG();
-		}
-
-		cmd = instance->cmd_list[context];
-
-		megasas_complete_cmd(instance, cmd, DID_OK);
-
-		consumer++;
-		if (consumer == (instance->max_fw_cmds + 1)) {
-			consumer = 0;
-		}
-	}
-
-	*instance->consumer = producer;
-
-	spin_unlock_irqrestore(&instance->completion_lock, flags);
-
-	/*
-	 * Check if we can restore can_queue
-	 */
-	if (instance->flag & MEGASAS_FW_BUSY
-		&& time_after(jiffies, instance->last_time + 5 * HZ)
-		&& atomic_read(&instance->fw_outstanding) < 17) {
-
-		spin_lock_irqsave(instance->host->host_lock, flags);
-		instance->flag &= ~MEGASAS_FW_BUSY;
-		if ((instance->pdev->device ==
-			PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-			(instance->pdev->device ==
-			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-			instance->host->can_queue =
-				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
-		} else
-			instance->host->can_queue =
-				instance->max_fw_cmds - MEGASAS_INT_CMDS;
-
-		spin_unlock_irqrestore(instance->host->host_lock, flags);
-	}
-}
-
-static void
-megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
-
-static void
-process_fw_state_change_wq(struct work_struct *work);
-
-void megasas_do_ocr(struct megasas_instance *instance)
-{
-	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
-	(instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
-	(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
-		*instance->consumer     = MEGASAS_ADPRESET_INPROG_SIGN;
-	}
-	instance->instancet->disable_intr(instance->reg_set);
-	instance->adprecovery   = MEGASAS_ADPRESET_SM_INFAULT;
-	instance->issuepend_done = 0;
-
-	atomic_set(&instance->fw_outstanding, 0);
-	megasas_internal_reset_defer_cmds(instance);
-	process_fw_state_change_wq(&instance->work_init);
-}
-
-/**
- * megasas_wait_for_outstanding -	Wait for all outstanding cmds
- * @instance:				Adapter soft state
- *
- * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
- * complete all its outstanding commands. Returns error if one or more IOs
- * are pending after this time period. It also marks the controller dead.
- */
-static int megasas_wait_for_outstanding(struct megasas_instance *instance)
-{
-	int i;
-	u32 reset_index;
-	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
-	u8 adprecovery;
-	unsigned long flags;
-	struct list_head clist_local;
-	struct megasas_cmd *reset_cmd;
-	u32 fw_state;
-	u8 kill_adapter_flag;
-
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	adprecovery = instance->adprecovery;
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
-
-		INIT_LIST_HEAD(&clist_local);
-		spin_lock_irqsave(&instance->hba_lock, flags);
-		list_splice_init(&instance->internal_reset_pending_q,
-				&clist_local);
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-		printk(KERN_NOTICE "megasas: HBA reset wait ...\n");
-		for (i = 0; i < wait_time; i++) {
-			msleep(1000);
-			spin_lock_irqsave(&instance->hba_lock, flags);
-			adprecovery = instance->adprecovery;
-			spin_unlock_irqrestore(&instance->hba_lock, flags);
-			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
-				break;
-		}
-
-		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
-			printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
-			spin_lock_irqsave(&instance->hba_lock, flags);
-			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
-			spin_unlock_irqrestore(&instance->hba_lock, flags);
-			return FAILED;
-		}
-
-		reset_index	= 0;
-		while (!list_empty(&clist_local)) {
-			reset_cmd	= list_entry((&clist_local)->next,
-						struct megasas_cmd, list);
-			list_del_init(&reset_cmd->list);
-			if (reset_cmd->scmd) {
-				reset_cmd->scmd->result = DID_RESET << 16;
-				printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n",
-					reset_index, reset_cmd,
-					reset_cmd->scmd->cmnd[0],
-					reset_cmd->scmd->serial_number);
-
-				reset_cmd->scmd->scsi_done(reset_cmd->scmd);
-				megasas_return_cmd(instance, reset_cmd);
-			} else if (reset_cmd->sync_cmd) {
-				printk(KERN_NOTICE "megasas:%p synch cmds"
-						"reset queue\n",
-						reset_cmd);
-
-				reset_cmd->cmd_status = ENODATA;
-				instance->instancet->fire_cmd(instance,
-						reset_cmd->frame_phys_addr,
-						0, instance->reg_set);
-			} else {
-				printk(KERN_NOTICE "megasas: %p unexpected"
-					"cmds lst\n",
-					reset_cmd);
-			}
-			reset_index++;
-		}
-
-		return SUCCESS;
-	}
-
-	for (i = 0; i < wait_time; i++) {
-
-		int outstanding = atomic_read(&instance->fw_outstanding);
-
-		if (!outstanding)
-			break;
-
-		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
-			printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
-			       "commands to complete\n",i,outstanding);
-			/*
-			 * Call cmd completion routine. Cmd to be
-			 * be completed directly without depending on isr.
-			 */
-			megasas_complete_cmd_dpc((unsigned long)instance);
-		}
-
-		msleep(1000);
-	}
-
-	i = 0;
-	kill_adapter_flag = 0;
-	do {
-		fw_state = instance->instancet->read_fw_status_reg(
-					instance->reg_set) & MFI_STATE_MASK;
-		if ((fw_state == MFI_STATE_FAULT) &&
-			(instance->disableOnlineCtrlReset == 0)) {
-			if (i == 3) {
-				kill_adapter_flag = 2;
-				break;
-			}
-			megasas_do_ocr(instance);
-			kill_adapter_flag = 1;
-
-			/* wait for 1 secs to let FW finish the pending cmds */
-			msleep(1000);
-		}
-		i++;
-	} while (i <= 3);
-
-	if (atomic_read(&instance->fw_outstanding) &&
-					!kill_adapter_flag) {
-		if (instance->disableOnlineCtrlReset == 0) {
-
-			megasas_do_ocr(instance);
-
-			/* wait for 5 secs to let FW finish the pending cmds */
-			for (i = 0; i < wait_time; i++) {
-				int outstanding =
-					atomic_read(&instance->fw_outstanding);
-				if (!outstanding)
-					return SUCCESS;
-				msleep(1000);
-			}
-		}
-	}
-
-	if (atomic_read(&instance->fw_outstanding) ||
-					(kill_adapter_flag == 2)) {
-		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
-		/*
-		* Send signal to FW to stop processing any pending cmds.
-		* The controller will be taken offline by the OS now.
-		*/
-		if ((instance->pdev->device ==
-			PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-			(instance->pdev->device ==
-			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-			writel(MFI_STOP_ADP,
-				&instance->reg_set->reserved_0[0]);
-		} else {
-			writel(MFI_STOP_ADP,
-				&instance->reg_set->inbound_doorbell);
-		}
-		megasas_dump_pending_frames(instance);
-		spin_lock_irqsave(&instance->hba_lock, flags);
-		instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-		return FAILED;
-	}
-
-	printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
-
-	return SUCCESS;
-}
-
-/**
- * megasas_generic_reset -	Generic reset routine
- * @scmd:			Mid-layer SCSI command
- *
- * This routine implements a generic reset handler for device, bus and host
- * reset requests. Device, bus and host specific reset handlers can use this
- * function after they do their specific tasks.
- */
-static int megasas_generic_reset(struct scsi_cmnd *scmd)
-{
-	int ret_val;
-	struct megasas_instance *instance;
-
-	instance = (struct megasas_instance *)scmd->device->host->hostdata;
-
-	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
-		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
-
-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
-		printk(KERN_ERR "megasas: cannot recover from previous reset "
-		       "failures\n");
-		return FAILED;
-	}
-
-	ret_val = megasas_wait_for_outstanding(instance);
-	if (ret_val == SUCCESS)
-		printk(KERN_NOTICE "megasas: reset successful \n");
-	else
-		printk(KERN_ERR "megasas: failed to do reset\n");
-
-	return ret_val;
-}
-
-/**
- * megasas_reset_timer - quiesce the adapter if required
- * @scmd:		scsi cmnd
- *
- * Sets the FW busy flag and reduces the host->can_queue if the
- * cmd has not been completed within the timeout period.
- */
-static enum
-blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
-{
-	struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
-	struct megasas_instance *instance;
-	unsigned long flags;
-
-	if (time_after(jiffies, scmd->jiffies_at_alloc +
-				(MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
-		return BLK_EH_NOT_HANDLED;
-	}
-
-	instance = cmd->instance;
-	if (!(instance->flag & MEGASAS_FW_BUSY)) {
-		/* FW is busy, throttle IO */
-		spin_lock_irqsave(instance->host->host_lock, flags);
-
-		instance->host->can_queue = 16;
-		instance->last_time = jiffies;
-		instance->flag |= MEGASAS_FW_BUSY;
-
-		spin_unlock_irqrestore(instance->host->host_lock, flags);
-	}
-	return BLK_EH_RESET_TIMER;
-}
-
-/**
- * megasas_reset_device -	Device reset handler entry point
- */
-static int megasas_reset_device(struct scsi_cmnd *scmd)
-{
-	int ret;
-
-	/*
-	 * First wait for all commands to complete
-	 */
-	ret = megasas_generic_reset(scmd);
-
-	return ret;
-}
-
-/**
- * megasas_reset_bus_host -	Bus & host reset handler entry point
- */
-static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
-{
-	int ret;
-
-	/*
-	 * First wait for all commands to complete
-	 */
-	ret = megasas_generic_reset(scmd);
-
-	return ret;
-}
-
-/**
- * megasas_bios_param - Returns disk geometry for a disk
- * @sdev: 		device handle
- * @bdev:		block device
- * @capacity:		drive capacity
- * @geom:		geometry parameters
- */
-static int
-megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
-		 sector_t capacity, int geom[])
-{
-	int heads;
-	int sectors;
-	sector_t cylinders;
-	unsigned long tmp;
-	/* Default heads (64) & sectors (32) */
-	heads = 64;
-	sectors = 32;
-
-	tmp = heads * sectors;
-	cylinders = capacity;
-
-	sector_div(cylinders, tmp);
-
-	/*
-	 * Handle extended translation size for logical drives > 1Gb
-	 */
-
-	if (capacity >= 0x200000) {
-		heads = 255;
-		sectors = 63;
-		tmp = heads*sectors;
-		cylinders = capacity;
-		sector_div(cylinders, tmp);
-	}
-
-	geom[0] = heads;
-	geom[1] = sectors;
-	geom[2] = cylinders;
-
-	return 0;
-}
-
-static void megasas_aen_polling(struct work_struct *work);
-
-/**
- * megasas_service_aen -	Processes an event notification
- * @instance:			Adapter soft state
- * @cmd:			AEN command completed by the ISR
- *
- * For AEN, driver sends a command down to FW that is held by the FW till an
- * event occurs. When an event of interest occurs, FW completes the command
- * that it was previously holding.
- *
- * This routines sends SIGIO signal to processes that have registered with the
- * driver for AEN.
- */
-static void
-megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
-{
-	unsigned long flags;
-	/*
-	 * Don't signal app if it is just an aborted previously registered aen
-	 */
-	if ((!cmd->abort_aen) && (instance->unload == 0)) {
-		spin_lock_irqsave(&poll_aen_lock, flags);
-		megasas_poll_wait_aen = 1;
-		spin_unlock_irqrestore(&poll_aen_lock, flags);
-		wake_up(&megasas_poll_wait);
-		kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
-	}
-	else
-		cmd->abort_aen = 0;
-
-	instance->aen_cmd = NULL;
-	megasas_return_cmd(instance, cmd);
-
-	if ((instance->unload == 0) &&
-		((instance->issuepend_done == 1))) {
-		struct megasas_aen_event *ev;
-		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-		if (!ev) {
-			printk(KERN_ERR "megasas_service_aen: out of memory\n");
-		} else {
-			ev->instance = instance;
-			instance->ev = ev;
-			INIT_WORK(&ev->hotplug_work, megasas_aen_polling);
-			schedule_delayed_work(
-				(struct delayed_work *)&ev->hotplug_work, 0);
-		}
-	}
-}
-
-/*
- * Scsi host template for megaraid_sas driver
- */
-static struct scsi_host_template megasas_template = {
-
-	.module = THIS_MODULE,
-	.name = "LSI SAS based MegaRAID driver",
-	.proc_name = "megaraid_sas",
-	.slave_configure = megasas_slave_configure,
-	.slave_alloc = megasas_slave_alloc,
-	.queuecommand = megasas_queue_command,
-	.eh_device_reset_handler = megasas_reset_device,
-	.eh_bus_reset_handler = megasas_reset_bus_host,
-	.eh_host_reset_handler = megasas_reset_bus_host,
-	.eh_timed_out = megasas_reset_timer,
-	.bios_param = megasas_bios_param,
-	.use_clustering = ENABLE_CLUSTERING,
-};
-
-/**
- * megasas_complete_int_cmd -	Completes an internal command
- * @instance:			Adapter soft state
- * @cmd:			Command to be completed
- *
- * The megasas_issue_blocked_cmd() function waits for a command to complete
- * after it issues a command. This function wakes up that waiting routine by
- * calling wake_up() on the wait queue.
- */
-static void
-megasas_complete_int_cmd(struct megasas_instance *instance,
-			 struct megasas_cmd *cmd)
-{
-	cmd->cmd_status = cmd->frame->io.cmd_status;
-
-	if (cmd->cmd_status == ENODATA) {
-		cmd->cmd_status = 0;
-	}
-	wake_up(&instance->int_cmd_wait_q);
-}
-
-/**
- * megasas_complete_abort -	Completes aborting a command
- * @instance:			Adapter soft state
- * @cmd:			Cmd that was issued to abort another cmd
- *
- * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q 
- * after it issues an abort on a previously issued command. This function 
- * wakes up all functions waiting on the same wait queue.
- */
-static void
-megasas_complete_abort(struct megasas_instance *instance,
-		       struct megasas_cmd *cmd)
-{
-	if (cmd->sync_cmd) {
-		cmd->sync_cmd = 0;
-		cmd->cmd_status = 0;
-		wake_up(&instance->abort_cmd_wait_q);
-	}
-
-	return;
-}
-
-/**
- * megasas_complete_cmd -	Completes a command
- * @instance:			Adapter soft state
- * @cmd:			Command to be completed
- * @alt_status:			If non-zero, use this value as status to 
- * 				SCSI mid-layer instead of the value returned
- * 				by the FW. This should be used if caller wants
- * 				an alternate status (as in the case of aborted
- * 				commands)
- */
-static void
-megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
-		     u8 alt_status)
-{
-	int exception = 0;
-	struct megasas_header *hdr = &cmd->frame->hdr;
-	unsigned long flags;
-
-	/* flag for the retry reset */
-	cmd->retry_for_fw_reset = 0;
-
-	if (cmd->scmd)
-		cmd->scmd->SCp.ptr = NULL;
-
-	switch (hdr->cmd) {
-
-	case MFI_CMD_PD_SCSI_IO:
-	case MFI_CMD_LD_SCSI_IO:
-
-		/*
-		 * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been
-		 * issued either through an IO path or an IOCTL path. If it
-		 * was via IOCTL, we will send it to internal completion.
-		 */
-		if (cmd->sync_cmd) {
-			cmd->sync_cmd = 0;
-			megasas_complete_int_cmd(instance, cmd);
-			break;
-		}
-
-	case MFI_CMD_LD_READ:
-	case MFI_CMD_LD_WRITE:
-
-		if (alt_status) {
-			cmd->scmd->result = alt_status << 16;
-			exception = 1;
-		}
-
-		if (exception) {
-
-			atomic_dec(&instance->fw_outstanding);
-
-			scsi_dma_unmap(cmd->scmd);
-			cmd->scmd->scsi_done(cmd->scmd);
-			megasas_return_cmd(instance, cmd);
-
-			break;
-		}
-
-		switch (hdr->cmd_status) {
-
-		case MFI_STAT_OK:
-			cmd->scmd->result = DID_OK << 16;
-			break;
-
-		case MFI_STAT_SCSI_IO_FAILED:
-		case MFI_STAT_LD_INIT_IN_PROGRESS:
-			cmd->scmd->result =
-			    (DID_ERROR << 16) | hdr->scsi_status;
-			break;
-
-		case MFI_STAT_SCSI_DONE_WITH_ERROR:
-
-			cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status;
-
-			if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) {
-				memset(cmd->scmd->sense_buffer, 0,
-				       SCSI_SENSE_BUFFERSIZE);
-				memcpy(cmd->scmd->sense_buffer, cmd->sense,
-				       hdr->sense_len);
-
-				cmd->scmd->result |= DRIVER_SENSE << 24;
-			}
-
-			break;
-
-		case MFI_STAT_LD_OFFLINE:
-		case MFI_STAT_DEVICE_NOT_FOUND:
-			cmd->scmd->result = DID_BAD_TARGET << 16;
-			break;
-
-		default:
-			printk(KERN_DEBUG "megasas: MFI FW status %#x\n",
-			       hdr->cmd_status);
-			cmd->scmd->result = DID_ERROR << 16;
-			break;
-		}
-
-		atomic_dec(&instance->fw_outstanding);
-
-		scsi_dma_unmap(cmd->scmd);
-		cmd->scmd->scsi_done(cmd->scmd);
-		megasas_return_cmd(instance, cmd);
-
-		break;
-
-	case MFI_CMD_SMP:
-	case MFI_CMD_STP:
-	case MFI_CMD_DCMD:
-		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
-			cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
-			spin_lock_irqsave(&poll_aen_lock, flags);
-			megasas_poll_wait_aen = 0;
-			spin_unlock_irqrestore(&poll_aen_lock, flags);
-		}
-
-		/*
-		 * See if got an event notification
-		 */
-		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT)
-			megasas_service_aen(instance, cmd);
-		else
-			megasas_complete_int_cmd(instance, cmd);
-
-		break;
-
-	case MFI_CMD_ABORT:
-		/*
-		 * Cmd issued to abort another cmd returned
-		 */
-		megasas_complete_abort(instance, cmd);
-		break;
-
-	default:
-		printk("megasas: Unknown command completed! [0x%X]\n",
-		       hdr->cmd);
-		break;
-	}
-}
-
-/**
- * megasas_issue_pending_cmds_again -	issue all pending cmds
- *                              	in FW again because of the fw reset
- * @instance:				Adapter soft state
- */
-static inline void
-megasas_issue_pending_cmds_again(struct megasas_instance *instance)
-{
-	struct megasas_cmd *cmd;
-	struct list_head clist_local;
-	union megasas_evt_class_locale class_locale;
-	unsigned long flags;
-	u32 seq_num;
-
-	INIT_LIST_HEAD(&clist_local);
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	list_splice_init(&instance->internal_reset_pending_q, &clist_local);
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-	while (!list_empty(&clist_local)) {
-		cmd	= list_entry((&clist_local)->next,
-					struct megasas_cmd, list);
-		list_del_init(&cmd->list);
-
-		if (cmd->sync_cmd || cmd->scmd) {
-			printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d"
-				"detected to be pending while HBA reset.\n",
-					cmd, cmd->scmd, cmd->sync_cmd);
-
-			cmd->retry_for_fw_reset++;
-
-			if (cmd->retry_for_fw_reset == 3) {
-				printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
-					"was tried multiple times during reset."
-					"Shutting down the HBA\n",
-					cmd, cmd->scmd, cmd->sync_cmd);
-				megaraid_sas_kill_hba(instance);
-
-				instance->adprecovery =
-						MEGASAS_HW_CRITICAL_ERROR;
-				return;
-			}
-		}
-
-		if (cmd->sync_cmd == 1) {
-			if (cmd->scmd) {
-				printk(KERN_NOTICE "megaraid_sas: unexpected"
-					"cmd attached to internal command!\n");
-			}
-			printk(KERN_NOTICE "megasas: %p synchronous cmd"
-						"on the internal reset queue,"
-						"issue it again.\n", cmd);
-			cmd->cmd_status = ENODATA;
-			instance->instancet->fire_cmd(instance,
-							cmd->frame_phys_addr ,
-							0, instance->reg_set);
-		} else if (cmd->scmd) {
-			printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
-			"detected on the internal queue, issue again.\n",
-			cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
-
-			atomic_inc(&instance->fw_outstanding);
-			instance->instancet->fire_cmd(instance,
-					cmd->frame_phys_addr,
-					cmd->frame_count-1, instance->reg_set);
-		} else {
-			printk(KERN_NOTICE "megasas: %p unexpected cmd on the"
-				"internal reset defer list while re-issue!!\n",
-				cmd);
-		}
-	}
-
-	if (instance->aen_cmd) {
-		printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n");
-		megasas_return_cmd(instance, instance->aen_cmd);
-
-		instance->aen_cmd	= NULL;
-	}
-
-	/*
-	* Initiate AEN (Asynchronous Event Notification)
-	*/
-	seq_num = instance->last_seq_num;
-	class_locale.members.reserved = 0;
-	class_locale.members.locale = MR_EVT_LOCALE_ALL;
-	class_locale.members.class = MR_EVT_CLASS_DEBUG;
-
-	megasas_register_aen(instance, seq_num, class_locale.word);
-}
-
-/**
- * Move the internal reset pending commands to a deferred queue.
- *
- * We move the commands pending at internal reset time to a
- * pending queue. This queue would be flushed after successful
- * completion of the internal reset sequence. if the internal reset
- * did not complete in time, the kernel reset handler would flush
- * these commands.
- **/
-static void
-megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
-{
-	struct megasas_cmd *cmd;
-	int i;
-	u32 max_cmd = instance->max_fw_cmds;
-	u32 defer_index;
-	unsigned long flags;
-
-	defer_index     = 0;
-	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
-	for (i = 0; i < max_cmd; i++) {
-		cmd = instance->cmd_list[i];
-		if (cmd->sync_cmd == 1 || cmd->scmd) {
-			printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
-					"on the defer queue as internal\n",
-				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
-
-			if (!list_empty(&cmd->list)) {
-				printk(KERN_NOTICE "megaraid_sas: ERROR while"
-					" moving this cmd:%p, %d %p, it was"
-					"discovered on some list?\n",
-					cmd, cmd->sync_cmd, cmd->scmd);
-
-				list_del_init(&cmd->list);
-			}
-			defer_index++;
-			list_add_tail(&cmd->list,
-				&instance->internal_reset_pending_q);
-		}
-	}
-	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
-}
-
-
-static void
-process_fw_state_change_wq(struct work_struct *work)
-{
-	struct megasas_instance *instance =
-		container_of(work, struct megasas_instance, work_init);
-	u32 wait;
-	unsigned long flags;
-
-	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
-		printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
-				instance->adprecovery);
-		return ;
-	}
-
-	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
-		printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
-					"state, restarting it...\n");
-
-		instance->instancet->disable_intr(instance->reg_set);
-		atomic_set(&instance->fw_outstanding, 0);
-
-		atomic_set(&instance->fw_reset_no_pci_access, 1);
-		instance->instancet->adp_reset(instance, instance->reg_set);
-		atomic_set(&instance->fw_reset_no_pci_access, 0 );
-
-		printk(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
-					"initiating next stage...\n");
-
-		printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine,"
-					"state 2 starting...\n");
-
-		/*waitting for about 20 second before start the second init*/
-		for (wait = 0; wait < 30; wait++) {
-			msleep(1000);
-		}
-
-		if (megasas_transition_to_ready(instance)) {
-			printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
-
-			megaraid_sas_kill_hba(instance);
-			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
-			return ;
-		}
-
-		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
-			(instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
-			(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)
-			) {
-			*instance->consumer = *instance->producer;
-		} else {
-			*instance->consumer = 0;
-			*instance->producer = 0;
-		}
-
-		megasas_issue_init_mfi(instance);
-
-		spin_lock_irqsave(&instance->hba_lock, flags);
-		instance->adprecovery	= MEGASAS_HBA_OPERATIONAL;
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-		instance->instancet->enable_intr(instance->reg_set);
-
-		megasas_issue_pending_cmds_again(instance);
-		instance->issuepend_done = 1;
-	}
-	return ;
-}
-
-/**
- * megasas_deplete_reply_queue -	Processes all completed commands
- * @instance:				Adapter soft state
- * @alt_status:				Alternate status to be returned to
- * 					SCSI mid-layer instead of the status
- * 					returned by the FW
- * Note: this must be called with hba lock held
- */
-static int
-megasas_deplete_reply_queue(struct megasas_instance *instance,
-					u8 alt_status)
-{
-	u32 mfiStatus;
-	u32 fw_state;
-
-	if ((mfiStatus = instance->instancet->check_reset(instance,
-					instance->reg_set)) == 1) {
-		return IRQ_HANDLED;
-	}
-
-	if ((mfiStatus = instance->instancet->clear_intr(
-						instance->reg_set)
-						) == 0) {
-		return IRQ_NONE;
-	}
-
-	instance->mfiStatus = mfiStatus;
-
-	if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
-		fw_state = instance->instancet->read_fw_status_reg(
-				instance->reg_set) & MFI_STATE_MASK;
-
-		if (fw_state != MFI_STATE_FAULT) {
-			printk(KERN_NOTICE "megaraid_sas: fw state:%x\n",
-						fw_state);
-		}
-
-		if ((fw_state == MFI_STATE_FAULT) &&
-				(instance->disableOnlineCtrlReset == 0)) {
-			printk(KERN_NOTICE "megaraid_sas: wait adp restart\n");
-
-			if ((instance->pdev->device ==
-					PCI_DEVICE_ID_LSI_SAS1064R) ||
-				(instance->pdev->device ==
-					PCI_DEVICE_ID_DELL_PERC5) ||
-				(instance->pdev->device ==
-					PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
-
-				*instance->consumer =
-					MEGASAS_ADPRESET_INPROG_SIGN;
-			}
-
-
-			instance->instancet->disable_intr(instance->reg_set);
-			instance->adprecovery	= MEGASAS_ADPRESET_SM_INFAULT;
-			instance->issuepend_done = 0;
-
-			atomic_set(&instance->fw_outstanding, 0);
-			megasas_internal_reset_defer_cmds(instance);
-
-			printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
-					fw_state, instance->adprecovery);
-
-			schedule_work(&instance->work_init);
-			return IRQ_HANDLED;
-
-		} else {
-			printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
-				fw_state, instance->disableOnlineCtrlReset);
-		}
-	}
-
-	tasklet_schedule(&instance->isr_tasklet);
-	return IRQ_HANDLED;
-}
-/**
- * megasas_isr - isr entry point
- */
-static irqreturn_t megasas_isr(int irq, void *devp)
-{
-	struct megasas_instance *instance;
-	unsigned long flags;
-	irqreturn_t	rc;
-
-	if (atomic_read(
-		&(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
-		return IRQ_HANDLED;
-
-	instance = (struct megasas_instance *)devp;
-
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	rc =  megasas_deplete_reply_queue(instance, DID_OK);
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-	return rc;
-}
-
-/**
- * megasas_transition_to_ready -	Move the FW to READY state
- * @instance:				Adapter soft state
- *
- * During the initialization, FW passes can potentially be in any one of
- * several possible states. If the FW in operational, waiting-for-handshake
- * states, driver must take steps to bring it to ready state. Otherwise, it
- * has to wait for the ready state.
- */
-static int
-megasas_transition_to_ready(struct megasas_instance* instance)
-{
-	int i;
-	u8 max_wait;
-	u32 fw_state;
-	u32 cur_state;
-	u32 abs_state, curr_abs_state;
-
-	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
-
-	if (fw_state != MFI_STATE_READY)
- 		printk(KERN_INFO "megasas: Waiting for FW to come to ready"
- 		       " state\n");
-
-	while (fw_state != MFI_STATE_READY) {
-
-		abs_state =
-		instance->instancet->read_fw_status_reg(instance->reg_set);
-
-		switch (fw_state) {
-
-		case MFI_STATE_FAULT:
-
-			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
-			return -ENODEV;
-
-		case MFI_STATE_WAIT_HANDSHAKE:
-			/*
-			 * Set the CLR bit in inbound doorbell
-			 */
-			if ((instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-				(instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-
-				writel(
-				  MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
-				  &instance->reg_set->reserved_0[0]);
-			} else {
-				writel(
-				    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
-					&instance->reg_set->inbound_doorbell);
-			}
-
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_WAIT_HANDSHAKE;
-			break;
-
-		case MFI_STATE_BOOT_MESSAGE_PENDING:
-			if ((instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-			(instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-				writel(MFI_INIT_HOTPLUG,
-				&instance->reg_set->reserved_0[0]);
-			} else
-				writel(MFI_INIT_HOTPLUG,
-					&instance->reg_set->inbound_doorbell);
-
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
-			break;
-
-		case MFI_STATE_OPERATIONAL:
-			/*
-			 * Bring it to READY state; assuming max wait 10 secs
-			 */
-			instance->instancet->disable_intr(instance->reg_set);
-			if ((instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-				(instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-				writel(MFI_RESET_FLAGS,
-					&instance->reg_set->reserved_0[0]);
-			} else
-				writel(MFI_RESET_FLAGS,
-					&instance->reg_set->inbound_doorbell);
-
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_OPERATIONAL;
-			break;
-
-		case MFI_STATE_UNDEFINED:
-			/*
-			 * This state should not last for more than 2 seconds
-			 */
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_UNDEFINED;
-			break;
-
-		case MFI_STATE_BB_INIT:
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_BB_INIT;
-			break;
-
-		case MFI_STATE_FW_INIT:
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_FW_INIT;
-			break;
-
-		case MFI_STATE_FW_INIT_2:
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_FW_INIT_2;
-			break;
-
-		case MFI_STATE_DEVICE_SCAN:
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_DEVICE_SCAN;
-			break;
-
-		case MFI_STATE_FLUSH_CACHE:
-			max_wait = MEGASAS_RESET_WAIT_TIME;
-			cur_state = MFI_STATE_FLUSH_CACHE;
-			break;
-
-		default:
-			printk(KERN_DEBUG "megasas: Unknown state 0x%x\n",
-			       fw_state);
-			return -ENODEV;
-		}
-
-		/*
-		 * The cur_state should not last for more than max_wait secs
-		 */
-		for (i = 0; i < (max_wait * 1000); i++) {
-			fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &  
-					MFI_STATE_MASK ;
-		curr_abs_state =
-		instance->instancet->read_fw_status_reg(instance->reg_set);
-
-			if (abs_state == curr_abs_state) {
-				msleep(1);
-			} else
-				break;
-		}
-
-		/*
-		 * Return error if fw_state hasn't changed after max_wait
-		 */
-		if (curr_abs_state == abs_state) {
-			printk(KERN_DEBUG "FW state [%d] hasn't changed "
-			       "in %d secs\n", fw_state, max_wait);
-			return -ENODEV;
-		}
-	}
- 	printk(KERN_INFO "megasas: FW now in Ready state\n");
-
-	return 0;
-}
-
-/**
- * megasas_teardown_frame_pool -	Destroy the cmd frame DMA pool
- * @instance:				Adapter soft state
- */
-static void megasas_teardown_frame_pool(struct megasas_instance *instance)
-{
-	int i;
-	u32 max_cmd = instance->max_fw_cmds;
-	struct megasas_cmd *cmd;
-
-	if (!instance->frame_dma_pool)
-		return;
-
-	/*
-	 * Return all frames to pool
-	 */
-	for (i = 0; i < max_cmd; i++) {
-
-		cmd = instance->cmd_list[i];
-
-		if (cmd->frame)
-			pci_pool_free(instance->frame_dma_pool, cmd->frame,
-				      cmd->frame_phys_addr);
-
-		if (cmd->sense)
-			pci_pool_free(instance->sense_dma_pool, cmd->sense,
-				      cmd->sense_phys_addr);
-	}
-
-	/*
-	 * Now destroy the pool itself
-	 */
-	pci_pool_destroy(instance->frame_dma_pool);
-	pci_pool_destroy(instance->sense_dma_pool);
-
-	instance->frame_dma_pool = NULL;
-	instance->sense_dma_pool = NULL;
-}
-
-/**
- * megasas_create_frame_pool -	Creates DMA pool for cmd frames
- * @instance:			Adapter soft state
- *
- * Each command packet has an embedded DMA memory buffer that is used for
- * filling MFI frame and the SG list that immediately follows the frame. This
- * function creates those DMA memory buffers for each command packet by using
- * PCI pool facility.
- */
-static int megasas_create_frame_pool(struct megasas_instance *instance)
-{
-	int i;
-	u32 max_cmd;
-	u32 sge_sz;
-	u32 sgl_sz;
-	u32 total_sz;
-	u32 frame_count;
-	struct megasas_cmd *cmd;
-
-	max_cmd = instance->max_fw_cmds;
-
-	/*
-	 * Size of our frame is 64 bytes for MFI frame, followed by max SG
-	 * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer
-	 */
-	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
-	    sizeof(struct megasas_sge32);
-
-	if (instance->flag_ieee) {
-		sge_sz = sizeof(struct megasas_sge_skinny);
-	}
-
-	/*
-	 * Calculated the number of 64byte frames required for SGL
-	 */
-	sgl_sz = sge_sz * instance->max_num_sge;
-	frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
-	frame_count = 15;
-
-	/*
-	 * We need one extra frame for the MFI command
-	 */
-	frame_count++;
-
-	total_sz = MEGAMFI_FRAME_SIZE * frame_count;
-	/*
-	 * Use DMA pool facility provided by PCI layer
-	 */
-	instance->frame_dma_pool = pci_pool_create("megasas frame pool",
-						   instance->pdev, total_sz, 64,
-						   0);
-
-	if (!instance->frame_dma_pool) {
-		printk(KERN_DEBUG "megasas: failed to setup frame pool\n");
-		return -ENOMEM;
-	}
-
-	instance->sense_dma_pool = pci_pool_create("megasas sense pool",
-						   instance->pdev, 128, 4, 0);
-
-	if (!instance->sense_dma_pool) {
-		printk(KERN_DEBUG "megasas: failed to setup sense pool\n");
-
-		pci_pool_destroy(instance->frame_dma_pool);
-		instance->frame_dma_pool = NULL;
-
-		return -ENOMEM;
-	}
-
-	/*
-	 * Allocate and attach a frame to each of the commands in cmd_list.
-	 * By making cmd->index as the context instead of the &cmd, we can
-	 * always use 32bit context regardless of the architecture
-	 */
-	for (i = 0; i < max_cmd; i++) {
-
-		cmd = instance->cmd_list[i];
-
-		cmd->frame = pci_pool_alloc(instance->frame_dma_pool,
-					    GFP_KERNEL, &cmd->frame_phys_addr);
-
-		cmd->sense = pci_pool_alloc(instance->sense_dma_pool,
-					    GFP_KERNEL, &cmd->sense_phys_addr);
-
-		/*
-		 * megasas_teardown_frame_pool() takes care of freeing
-		 * whatever has been allocated
-		 */
-		if (!cmd->frame || !cmd->sense) {
-			printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n");
-			megasas_teardown_frame_pool(instance);
-			return -ENOMEM;
-		}
-
-		memset(cmd->frame, 0, total_sz);
-		cmd->frame->io.context = cmd->index;
-		cmd->frame->io.pad_0 = 0;
-	}
-
-	return 0;
-}
-
-/**
- * megasas_free_cmds -	Free all the cmds in the free cmd pool
- * @instance:		Adapter soft state
- */
-static void megasas_free_cmds(struct megasas_instance *instance)
-{
-	int i;
-	/* First free the MFI frame pool */
-	megasas_teardown_frame_pool(instance);
-
-	/* Free all the commands in the cmd_list */
-	for (i = 0; i < instance->max_fw_cmds; i++)
-		kfree(instance->cmd_list[i]);
-
-	/* Free the cmd_list buffer itself */
-	kfree(instance->cmd_list);
-	instance->cmd_list = NULL;
-
-	INIT_LIST_HEAD(&instance->cmd_pool);
-}
-
-/**
- * megasas_alloc_cmds -	Allocates the command packets
- * @instance:		Adapter soft state
- *
- * Each command that is issued to the FW, whether IO commands from the OS or
- * internal commands like IOCTLs, are wrapped in local data structure called
- * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to
- * the FW.
- *
- * Each frame has a 32-bit field called context (tag). This context is used
- * to get back the megasas_cmd from the frame when a frame gets completed in
- * the ISR. Typically the address of the megasas_cmd itself would be used as
- * the context. But we wanted to keep the differences between 32 and 64 bit
- * systems to the mininum. We always use 32 bit integers for the context. In
- * this driver, the 32 bit values are the indices into an array cmd_list.
- * This array is used only to look up the megasas_cmd given the context. The
- * free commands themselves are maintained in a linked list called cmd_pool.
- */
-static int megasas_alloc_cmds(struct megasas_instance *instance)
-{
-	int i;
-	int j;
-	u32 max_cmd;
-	struct megasas_cmd *cmd;
-
-	max_cmd = instance->max_fw_cmds;
-
-	/*
-	 * instance->cmd_list is an array of struct megasas_cmd pointers.
-	 * Allocate the dynamic array first and then allocate individual
-	 * commands.
-	 */
-	instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL);
-
-	if (!instance->cmd_list) {
-		printk(KERN_DEBUG "megasas: out of memory\n");
-		return -ENOMEM;
-	}
-
-
-	for (i = 0; i < max_cmd; i++) {
-		instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),
-						GFP_KERNEL);
-
-		if (!instance->cmd_list[i]) {
-
-			for (j = 0; j < i; j++)
-				kfree(instance->cmd_list[j]);
-
-			kfree(instance->cmd_list);
-			instance->cmd_list = NULL;
-
-			return -ENOMEM;
-		}
-	}
-
-	/*
-	 * Add all the commands to command pool (instance->cmd_pool)
-	 */
-	for (i = 0; i < max_cmd; i++) {
-		cmd = instance->cmd_list[i];
-		memset(cmd, 0, sizeof(struct megasas_cmd));
-		cmd->index = i;
-		cmd->scmd = NULL;
-		cmd->instance = instance;
-
-		list_add_tail(&cmd->list, &instance->cmd_pool);
-	}
-
-	/*
-	 * Create a frame pool and assign one frame to each cmd
-	 */
-	if (megasas_create_frame_pool(instance)) {
-		printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
-		megasas_free_cmds(instance);
-	}
-
-	return 0;
-}
-
-/*
- * megasas_get_pd_list_info -	Returns FW's pd_list structure
- * @instance:				Adapter soft state
- * @pd_list:				pd_list structure
- *
- * Issues an internal command (DCMD) to get the FW's controller PD
- * list structure.  This information is mainly used to find out SYSTEM
- * supported by the FW.
- */
-static int
-megasas_get_pd_list(struct megasas_instance *instance)
-{
-	int ret = 0, pd_index = 0;
-	struct megasas_cmd *cmd;
-	struct megasas_dcmd_frame *dcmd;
-	struct MR_PD_LIST *ci;
-	struct MR_PD_ADDRESS *pd_addr;
-	dma_addr_t ci_h = 0;
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd) {
-		printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
-		return -ENOMEM;
-	}
-
-	dcmd = &cmd->frame->dcmd;
-
-	ci = pci_alloc_consistent(instance->pdev,
-		  MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
-
-	if (!ci) {
-		printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
-		megasas_return_cmd(instance, cmd);
-		return -ENOMEM;
-	}
-
-	memset(ci, 0, sizeof(*ci));
-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-	dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
-	dcmd->mbox.b[1] = 0;
-	dcmd->cmd = MFI_CMD_DCMD;
-	dcmd->cmd_status = 0xFF;
-	dcmd->sge_count = 1;
-	dcmd->flags = MFI_FRAME_DIR_READ;
-	dcmd->timeout = 0;
-	dcmd->pad_0 = 0;
-	dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
-	dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
-	dcmd->sgl.sge32[0].phys_addr = ci_h;
-	dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
-
-	if (!megasas_issue_polled(instance, cmd)) {
-		ret = 0;
-	} else {
-		ret = -1;
-	}
-
-	/*
-	* the following function will get the instance PD LIST.
-	*/
-
-	pd_addr = ci->addr;
-
-	if ( ret == 0 &&
-		(ci->count <
-		  (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
-
-		memset(instance->pd_list, 0,
-			MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
-
-		for (pd_index = 0; pd_index < ci->count; pd_index++) {
-
-			instance->pd_list[pd_addr->deviceId].tid	=
-							pd_addr->deviceId;
-			instance->pd_list[pd_addr->deviceId].driveType	=
-							pd_addr->scsiDevType;
-			instance->pd_list[pd_addr->deviceId].driveState	=
-							MR_PD_STATE_SYSTEM;
-			pd_addr++;
-		}
-	}
-
-	pci_free_consistent(instance->pdev,
-				MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
-				ci, ci_h);
-	megasas_return_cmd(instance, cmd);
-
-	return ret;
-}
-
-/*
- * megasas_get_ld_list_info -	Returns FW's ld_list structure
- * @instance:				Adapter soft state
- * @ld_list:				ld_list structure
- *
- * Issues an internal command (DCMD) to get the FW's controller PD
- * list structure.  This information is mainly used to find out SYSTEM
- * supported by the FW.
- */
-static int
-megasas_get_ld_list(struct megasas_instance *instance)
-{
-	int ret = 0, ld_index = 0, ids = 0;
-	struct megasas_cmd *cmd;
-	struct megasas_dcmd_frame *dcmd;
-	struct MR_LD_LIST *ci;
-	dma_addr_t ci_h = 0;
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd) {
-		printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n");
-		return -ENOMEM;
-	}
-
-	dcmd = &cmd->frame->dcmd;
-
-	ci = pci_alloc_consistent(instance->pdev,
-				sizeof(struct MR_LD_LIST),
-				&ci_h);
-
-	if (!ci) {
-		printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n");
-		megasas_return_cmd(instance, cmd);
-		return -ENOMEM;
-	}
-
-	memset(ci, 0, sizeof(*ci));
-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-	dcmd->cmd = MFI_CMD_DCMD;
-	dcmd->cmd_status = 0xFF;
-	dcmd->sge_count = 1;
-	dcmd->flags = MFI_FRAME_DIR_READ;
-	dcmd->timeout = 0;
-	dcmd->data_xfer_len = sizeof(struct MR_LD_LIST);
-	dcmd->opcode = MR_DCMD_LD_GET_LIST;
-	dcmd->sgl.sge32[0].phys_addr = ci_h;
-	dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
-	dcmd->pad_0  = 0;
-
-	if (!megasas_issue_polled(instance, cmd)) {
-		ret = 0;
-	} else {
-		ret = -1;
-	}
-
-	/* the following function will get the instance PD LIST */
-
-	if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) {
-		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
-
-		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
-			if (ci->ldList[ld_index].state != 0) {
-				ids = ci->ldList[ld_index].ref.targetId;
-				instance->ld_ids[ids] =
-					ci->ldList[ld_index].ref.targetId;
-			}
-		}
-	}
-
-	pci_free_consistent(instance->pdev,
-				sizeof(struct MR_LD_LIST),
-				ci,
-				ci_h);
-
-	megasas_return_cmd(instance, cmd);
-	return ret;
-}
-
-/**
- * megasas_get_controller_info -	Returns FW's controller structure
- * @instance:				Adapter soft state
- * @ctrl_info:				Controller information structure
- *
- * Issues an internal command (DCMD) to get the FW's controller structure.
- * This information is mainly used to find out the maximum IO transfer per
- * command supported by the FW.
- */
-static int
-megasas_get_ctrl_info(struct megasas_instance *instance,
-		      struct megasas_ctrl_info *ctrl_info)
-{
-	int ret = 0;
-	struct megasas_cmd *cmd;
-	struct megasas_dcmd_frame *dcmd;
-	struct megasas_ctrl_info *ci;
-	dma_addr_t ci_h = 0;
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd) {
-		printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");
-		return -ENOMEM;
-	}
-
-	dcmd = &cmd->frame->dcmd;
-
-	ci = pci_alloc_consistent(instance->pdev,
-				  sizeof(struct megasas_ctrl_info), &ci_h);
-
-	if (!ci) {
-		printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n");
-		megasas_return_cmd(instance, cmd);
-		return -ENOMEM;
-	}
-
-	memset(ci, 0, sizeof(*ci));
-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-	dcmd->cmd = MFI_CMD_DCMD;
-	dcmd->cmd_status = 0xFF;
-	dcmd->sge_count = 1;
-	dcmd->flags = MFI_FRAME_DIR_READ;
-	dcmd->timeout = 0;
-	dcmd->pad_0 = 0;
-	dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);
-	dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
-	dcmd->sgl.sge32[0].phys_addr = ci_h;
-	dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info);
-
-	if (!megasas_issue_polled(instance, cmd)) {
-		ret = 0;
-		memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
-	} else {
-		ret = -1;
-	}
-
-	pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
-			    ci, ci_h);
-
-	megasas_return_cmd(instance, cmd);
-	return ret;
-}
-
-/**
- * megasas_issue_init_mfi -	Initializes the FW
- * @instance:		Adapter soft state
- *
- * Issues the INIT MFI cmd
- */
-static int
-megasas_issue_init_mfi(struct megasas_instance *instance)
-{
-	u32 context;
-
-	struct megasas_cmd *cmd;
-
-	struct megasas_init_frame *init_frame;
-	struct megasas_init_queue_info *initq_info;
-	dma_addr_t init_frame_h;
-	dma_addr_t initq_info_h;
-
-	/*
-	 * Prepare a init frame. Note the init frame points to queue info
-	 * structure. Each frame has SGL allocated after first 64 bytes. For
-	 * this frame - since we don't need any SGL - we use SGL's space as
-	 * queue info structure
-	 *
-	 * We will not get a NULL command below. We just created the pool.
-	 */
-	cmd = megasas_get_cmd(instance);
-
-	init_frame = (struct megasas_init_frame *)cmd->frame;
-	initq_info = (struct megasas_init_queue_info *)
-		((unsigned long)init_frame + 64);
-
-	init_frame_h = cmd->frame_phys_addr;
-	initq_info_h = init_frame_h + 64;
-
-	context = init_frame->context;
-	memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
-	memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
-	init_frame->context = context;
-
-	initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
-	initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
-
-	initq_info->producer_index_phys_addr_lo = instance->producer_h;
-	initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
-
-	init_frame->cmd = MFI_CMD_INIT;
-	init_frame->cmd_status = 0xFF;
-	init_frame->queue_info_new_phys_addr_lo = initq_info_h;
-
-	init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
-
-	/*
-	 * disable the intr before firing the init frame to FW
-	 */
-	instance->instancet->disable_intr(instance->reg_set);
-
-	/*
-	 * Issue the init frame in polled mode
-	 */
-
-	if (megasas_issue_polled(instance, cmd)) {
-		printk(KERN_ERR "megasas: Failed to init firmware\n");
-		megasas_return_cmd(instance, cmd);
-		goto fail_fw_init;
-	}
-
-	megasas_return_cmd(instance, cmd);
-
-	return 0;
-
-fail_fw_init:
-	return -EINVAL;
-}
-
-/**
- * megasas_start_timer - Initializes a timer object
- * @instance:		Adapter soft state
- * @timer:		timer object to be initialized
- * @fn:			timer function
- * @interval:		time interval between timer function call
- */
-static inline void
-megasas_start_timer(struct megasas_instance *instance,
-			struct timer_list *timer,
-			void *fn, unsigned long interval)
-{
-	init_timer(timer);
-	timer->expires = jiffies + interval;
-	timer->data = (unsigned long)instance;
-	timer->function = fn;
-	add_timer(timer);
-}
-
-/**
- * megasas_io_completion_timer - Timer fn
- * @instance_addr:	Address of adapter soft state
- *
- * Schedules tasklet for cmd completion
- * if poll_mode_io is set
- */
-static void
-megasas_io_completion_timer(unsigned long instance_addr)
-{
-	struct megasas_instance *instance =
-			(struct megasas_instance *)instance_addr;
-
-	if (atomic_read(&instance->fw_outstanding))
-		tasklet_schedule(&instance->isr_tasklet);
-
-	/* Restart timer */
-	if (poll_mode_io)
-		mod_timer(&instance->io_completion_timer,
-			jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
-}
-
-/**
- * megasas_init_mfi -	Initializes the FW
- * @instance:		Adapter soft state
- *
- * This is the main function for initializing MFI firmware.
- */
-static int megasas_init_mfi(struct megasas_instance *instance)
-{
-	u32 context_sz;
-	u32 reply_q_sz;
-	u32 max_sectors_1;
-	u32 max_sectors_2;
-	u32 tmp_sectors;
-	struct megasas_register_set __iomem *reg_set;
-	struct megasas_ctrl_info *ctrl_info;
-	/*
-	 * Map the message registers
-	 */
-	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
-		instance->base_addr = pci_resource_start(instance->pdev, 1);
-	} else {
-		instance->base_addr = pci_resource_start(instance->pdev, 0);
-	}
-
-	if (pci_request_selected_regions(instance->pdev,
-		pci_select_bars(instance->pdev, IORESOURCE_MEM),
-		"megasas: LSI")) {
-		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
-		return -EBUSY;
-	}
-
-	instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
-
-	if (!instance->reg_set) {
-		printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
-		goto fail_ioremap;
-	}
-
-	reg_set = instance->reg_set;
-
-	switch(instance->pdev->device)
-	{
-		case PCI_DEVICE_ID_LSI_SAS1078R:
-		case PCI_DEVICE_ID_LSI_SAS1078DE:
-			instance->instancet = &megasas_instance_template_ppc;
-			break;
-		case PCI_DEVICE_ID_LSI_SAS1078GEN2:
-		case PCI_DEVICE_ID_LSI_SAS0079GEN2:
-			instance->instancet = &megasas_instance_template_gen2;
-			break;
-		case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
-		case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
-			instance->instancet = &megasas_instance_template_skinny;
-			break;
-		case PCI_DEVICE_ID_LSI_SAS1064R:
-		case PCI_DEVICE_ID_DELL_PERC5:
-		default:
-			instance->instancet = &megasas_instance_template_xscale;
-			break;
-	}
-
-	/*
-	 * We expect the FW state to be READY
-	 */
-	if (megasas_transition_to_ready(instance))
-		goto fail_ready_state;
-
-	/*
-	 * Get various operational parameters from status register
-	 */
-	instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
-	/*
-	 * Reduce the max supported cmds by 1. This is to ensure that the
-	 * reply_q_sz (1 more than the max cmd that driver may send)
-	 * does not exceed max cmds that the FW can support
-	 */
-	instance->max_fw_cmds = instance->max_fw_cmds-1;
-	instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> 
-					0x10;
-	/*
-	 * Create a pool of commands
-	 */
-	if (megasas_alloc_cmds(instance))
-		goto fail_alloc_cmds;
-
-	/*
-	 * Allocate memory for reply queue. Length of reply queue should
-	 * be _one_ more than the maximum commands handled by the firmware.
-	 *
-	 * Note: When FW completes commands, it places corresponding contex
-	 * values in this circular reply queue. This circular queue is a fairly
-	 * typical producer-consumer queue. FW is the producer (of completed
-	 * commands) and the driver is the consumer.
-	 */
-	context_sz = sizeof(u32);
-	reply_q_sz = context_sz * (instance->max_fw_cmds + 1);
-
-	instance->reply_queue = pci_alloc_consistent(instance->pdev,
-						     reply_q_sz,
-						     &instance->reply_queue_h);
-
-	if (!instance->reply_queue) {
-		printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n");
-		goto fail_reply_queue;
-	}
-
-	if (megasas_issue_init_mfi(instance))
-		goto fail_fw_init;
-
-	instance->fw_support_ieee = 0;
-	instance->fw_support_ieee =
-		(instance->instancet->read_fw_status_reg(reg_set) &
-		0x04000000);
-
-	printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d",
-			instance->fw_support_ieee);
-
-	if (instance->fw_support_ieee)
-		instance->flag_ieee = 1;
-
-	/** for passthrough
-	* the following function will get the PD LIST.
-	*/
-
-	memset(instance->pd_list, 0 ,
-		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
-	megasas_get_pd_list(instance);
-
-	memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
-	megasas_get_ld_list(instance);
-
-	ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
-
-	/*
-	 * Compute the max allowed sectors per IO: The controller info has two
-	 * limits on max sectors. Driver should use the minimum of these two.
-	 *
-	 * 1 << stripe_sz_ops.min = max sectors per strip
-	 *
-	 * Note that older firmwares ( < FW ver 30) didn't report information
-	 * to calculate max_sectors_1. So the number ended up as zero always.
-	 */
-	tmp_sectors = 0;
-	if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
-
-		max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
-		    ctrl_info->max_strips_per_io;
-		max_sectors_2 = ctrl_info->max_request_size;
-
-		tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
-		instance->disableOnlineCtrlReset =
-		ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
-	}
-
-	instance->max_sectors_per_req = instance->max_num_sge *
-						PAGE_SIZE / 512;
-	if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
-		instance->max_sectors_per_req = tmp_sectors;
-
-	kfree(ctrl_info);
-
-        /*
-	* Setup tasklet for cmd completion
-	*/
-
-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
-		(unsigned long)instance);
-
-	/* Initialize the cmd completion timer */
-	if (poll_mode_io)
-		megasas_start_timer(instance, &instance->io_completion_timer,
-				megasas_io_completion_timer,
-				MEGASAS_COMPLETION_TIMER_INTERVAL);
-	return 0;
-
-      fail_fw_init:
-
-	pci_free_consistent(instance->pdev, reply_q_sz,
-			    instance->reply_queue, instance->reply_queue_h);
-      fail_reply_queue:
-	megasas_free_cmds(instance);
-
-      fail_alloc_cmds:
-      fail_ready_state:
-	iounmap(instance->reg_set);
-
-      fail_ioremap:
-	pci_release_selected_regions(instance->pdev,
-		pci_select_bars(instance->pdev, IORESOURCE_MEM));
-
-	return -EINVAL;
-}
-
-/**
- * megasas_release_mfi -	Reverses the FW initialization
- * @intance:			Adapter soft state
- */
-static void megasas_release_mfi(struct megasas_instance *instance)
-{
-	u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1);
-
-	pci_free_consistent(instance->pdev, reply_q_sz,
-			    instance->reply_queue, instance->reply_queue_h);
-
-	megasas_free_cmds(instance);
-
-	iounmap(instance->reg_set);
-
-	pci_release_selected_regions(instance->pdev,
-		pci_select_bars(instance->pdev, IORESOURCE_MEM));
-}
-
-/**
- * megasas_get_seq_num -	Gets latest event sequence numbers
- * @instance:			Adapter soft state
- * @eli:			FW event log sequence numbers information
- *
- * FW maintains a log of all events in a non-volatile area. Upper layers would
- * usually find out the latest sequence number of the events, the seq number at
- * the boot etc. They would "read" all the events below the latest seq number
- * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq
- * number), they would subsribe to AEN (asynchronous event notification) and
- * wait for the events to happen.
- */
-static int
-megasas_get_seq_num(struct megasas_instance *instance,
-		    struct megasas_evt_log_info *eli)
-{
-	struct megasas_cmd *cmd;
-	struct megasas_dcmd_frame *dcmd;
-	struct megasas_evt_log_info *el_info;
-	dma_addr_t el_info_h = 0;
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd) {
-		return -ENOMEM;
-	}
-
-	dcmd = &cmd->frame->dcmd;
-	el_info = pci_alloc_consistent(instance->pdev,
-				       sizeof(struct megasas_evt_log_info),
-				       &el_info_h);
-
-	if (!el_info) {
-		megasas_return_cmd(instance, cmd);
-		return -ENOMEM;
-	}
-
-	memset(el_info, 0, sizeof(*el_info));
-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-	dcmd->cmd = MFI_CMD_DCMD;
-	dcmd->cmd_status = 0x0;
-	dcmd->sge_count = 1;
-	dcmd->flags = MFI_FRAME_DIR_READ;
-	dcmd->timeout = 0;
-	dcmd->pad_0 = 0;
-	dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
-	dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
-	dcmd->sgl.sge32[0].phys_addr = el_info_h;
-	dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info);
-
-	megasas_issue_blocked_cmd(instance, cmd);
-
-	/*
-	 * Copy the data back into callers buffer
-	 */
-	memcpy(eli, el_info, sizeof(struct megasas_evt_log_info));
-
-	pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info),
-			    el_info, el_info_h);
-
-	megasas_return_cmd(instance, cmd);
-
-	return 0;
-}
-
-/**
- * megasas_register_aen -	Registers for asynchronous event notification
- * @instance:			Adapter soft state
- * @seq_num:			The starting sequence number
- * @class_locale:		Class of the event
- *
- * This function subscribes for AEN for events beyond the @seq_num. It requests
- * to be notified if and only if the event is of type @class_locale
- */
-static int
-megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
-		     u32 class_locale_word)
-{
-	int ret_val;
-	struct megasas_cmd *cmd;
-	struct megasas_dcmd_frame *dcmd;
-	union megasas_evt_class_locale curr_aen;
-	union megasas_evt_class_locale prev_aen;
-
-	/*
-	 * If there an AEN pending already (aen_cmd), check if the
-	 * class_locale of that pending AEN is inclusive of the new
-	 * AEN request we currently have. If it is, then we don't have
-	 * to do anything. In other words, whichever events the current
-	 * AEN request is subscribing to, have already been subscribed
-	 * to.
-	 *
-	 * If the old_cmd is _not_ inclusive, then we have to abort
-	 * that command, form a class_locale that is superset of both
-	 * old and current and re-issue to the FW
-	 */
-
-	curr_aen.word = class_locale_word;
-
-	if (instance->aen_cmd) {
-
-		prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1];
-
-		/*
-		 * A class whose enum value is smaller is inclusive of all
-		 * higher values. If a PROGRESS (= -1) was previously
-		 * registered, then a new registration requests for higher
-		 * classes need not be sent to FW. They are automatically
-		 * included.
-		 *
-		 * Locale numbers don't have such hierarchy. They are bitmap
-		 * values
-		 */
-		if ((prev_aen.members.class <= curr_aen.members.class) &&
-		    !((prev_aen.members.locale & curr_aen.members.locale) ^
-		      curr_aen.members.locale)) {
-			/*
-			 * Previously issued event registration includes
-			 * current request. Nothing to do.
-			 */
-			return 0;
-		} else {
-			curr_aen.members.locale |= prev_aen.members.locale;
-
-			if (prev_aen.members.class < curr_aen.members.class)
-				curr_aen.members.class = prev_aen.members.class;
-
-			instance->aen_cmd->abort_aen = 1;
-			ret_val = megasas_issue_blocked_abort_cmd(instance,
-								  instance->
-								  aen_cmd);
-
-			if (ret_val) {
-				printk(KERN_DEBUG "megasas: Failed to abort "
-				       "previous AEN command\n");
-				return ret_val;
-			}
-		}
-	}
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd)
-		return -ENOMEM;
-
-	dcmd = &cmd->frame->dcmd;
-
-	memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail));
-
-	/*
-	 * Prepare DCMD for aen registration
-	 */
-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-	dcmd->cmd = MFI_CMD_DCMD;
-	dcmd->cmd_status = 0x0;
-	dcmd->sge_count = 1;
-	dcmd->flags = MFI_FRAME_DIR_READ;
-	dcmd->timeout = 0;
-	dcmd->pad_0 = 0;
-	instance->last_seq_num = seq_num;
-	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
-	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
-	dcmd->mbox.w[0] = seq_num;
-	dcmd->mbox.w[1] = curr_aen.word;
-	dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h;
-	dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail);
-
-	if (instance->aen_cmd != NULL) {
-		megasas_return_cmd(instance, cmd);
-		return 0;
-	}
-
-	/*
-	 * Store reference to the cmd used to register for AEN. When an
-	 * application wants us to register for AEN, we have to abort this
-	 * cmd and re-register with a new EVENT LOCALE supplied by that app
-	 */
-	instance->aen_cmd = cmd;
-
-	/*
-	 * Issue the aen registration frame
-	 */
-	instance->instancet->fire_cmd(instance,
-			cmd->frame_phys_addr, 0, instance->reg_set);
-
-	return 0;
-}
-
-/**
- * megasas_start_aen -	Subscribes to AEN during driver load time
- * @instance:		Adapter soft state
- */
-static int megasas_start_aen(struct megasas_instance *instance)
-{
-	struct megasas_evt_log_info eli;
-	union megasas_evt_class_locale class_locale;
-
-	/*
-	 * Get the latest sequence number from FW
-	 */
-	memset(&eli, 0, sizeof(eli));
-
-	if (megasas_get_seq_num(instance, &eli))
-		return -1;
-
-	/*
-	 * Register AEN with FW for latest sequence number plus 1
-	 */
-	class_locale.members.reserved = 0;
-	class_locale.members.locale = MR_EVT_LOCALE_ALL;
-	class_locale.members.class = MR_EVT_CLASS_DEBUG;
-
-	return megasas_register_aen(instance, eli.newest_seq_num + 1,
-				    class_locale.word);
-}
-
-/**
- * megasas_io_attach -	Attaches this driver to SCSI mid-layer
- * @instance:		Adapter soft state
- */
-static int megasas_io_attach(struct megasas_instance *instance)
-{
-	struct Scsi_Host *host = instance->host;
-
-	/*
-	 * Export parameters required by SCSI mid-layer
-	 */
-	host->irq = instance->pdev->irq;
-	host->unique_id = instance->unique_id;
-	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-		host->can_queue =
-			instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
-	} else
-		host->can_queue =
-			instance->max_fw_cmds - MEGASAS_INT_CMDS;
-	host->this_id = instance->init_id;
-	host->sg_tablesize = instance->max_num_sge;
-	/*
-	 * Check if the module parameter value for max_sectors can be used
-	 */
-	if (max_sectors && max_sectors < instance->max_sectors_per_req)
-		instance->max_sectors_per_req = max_sectors;
-	else {
-		if (max_sectors) {
-			if (((instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
-				(instance->pdev->device ==
-				PCI_DEVICE_ID_LSI_SAS0079GEN2)) &&
-				(max_sectors <= MEGASAS_MAX_SECTORS)) {
-				instance->max_sectors_per_req = max_sectors;
-			} else {
-			printk(KERN_INFO "megasas: max_sectors should be > 0"
-				"and <= %d (or < 1MB for GEN2 controller)\n",
-				instance->max_sectors_per_req);
-			}
-		}
-	}
-
-	host->max_sectors = instance->max_sectors_per_req;
-	host->cmd_per_lun = 128;
-	host->max_channel = MEGASAS_MAX_CHANNELS - 1;
-	host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
-	host->max_lun = MEGASAS_MAX_LUN;
-	host->max_cmd_len = 16;
-
-	/*
-	 * Notify the mid-layer about the new controller
-	 */
-	if (scsi_add_host(host, &instance->pdev->dev)) {
-		printk(KERN_DEBUG "megasas: scsi_add_host failed\n");
-		return -ENODEV;
-	}
-
-	/*
-	 * Trigger SCSI to scan our drives
-	 */
-	scsi_scan_host(host);
-	return 0;
-}
-
-static int
-megasas_set_dma_mask(struct pci_dev *pdev)
-{
-	/*
-	 * All our contollers are capable of performing 64-bit DMA
-	 */
-	if (IS_DMA64) {
-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
-
-			if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
-				goto fail_set_dma_mask;
-		}
-	} else {
-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
-			goto fail_set_dma_mask;
-	}
-	return 0;
-
-fail_set_dma_mask:
-	return 1;
-}
-
-/**
- * megasas_probe_one -	PCI hotplug entry point
- * @pdev:		PCI device structure
- * @id:			PCI ids of supported hotplugged adapter	
- */
-static int __devinit
-megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	int rval;
-	struct Scsi_Host *host;
-	struct megasas_instance *instance;
-
-	/*
-	 * Announce PCI information
-	 */
-	printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
-	       pdev->vendor, pdev->device, pdev->subsystem_vendor,
-	       pdev->subsystem_device);
-
-	printk("bus %d:slot %d:func %d\n",
-	       pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-
-	/*
-	 * PCI prepping: enable device set bus mastering and dma mask
-	 */
-	rval = pci_enable_device_mem(pdev);
-
-	if (rval) {
-		return rval;
-	}
-
-	pci_set_master(pdev);
-
-	if (megasas_set_dma_mask(pdev))
-		goto fail_set_dma_mask;
-
-	host = scsi_host_alloc(&megasas_template,
-			       sizeof(struct megasas_instance));
-
-	if (!host) {
-		printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n");
-		goto fail_alloc_instance;
-	}
-
-	instance = (struct megasas_instance *)host->hostdata;
-	memset(instance, 0, sizeof(*instance));
-	atomic_set( &instance->fw_reset_no_pci_access, 0 );
-
-	instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
-						  &instance->producer_h);
-	instance->consumer = pci_alloc_consistent(pdev, sizeof(u32),
-						  &instance->consumer_h);
-
-	if (!instance->producer || !instance->consumer) {
-		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
-		       "producer, consumer\n");
-		goto fail_alloc_dma_buf;
-	}
-
-	*instance->producer = 0;
-	*instance->consumer = 0;
-	megasas_poll_wait_aen = 0;
-	instance->flag_ieee = 0;
-	instance->ev = NULL;
-	instance->issuepend_done = 1;
-	instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
-	megasas_poll_wait_aen = 0;
-
-	instance->evt_detail = pci_alloc_consistent(pdev,
-						    sizeof(struct
-							   megasas_evt_detail),
-						    &instance->evt_detail_h);
-
-	if (!instance->evt_detail) {
-		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
-		       "event detail structure\n");
-		goto fail_alloc_dma_buf;
-	}
-
-	/*
-	 * Initialize locks and queues
-	 */
-	INIT_LIST_HEAD(&instance->cmd_pool);
-	INIT_LIST_HEAD(&instance->internal_reset_pending_q);
-
-	atomic_set(&instance->fw_outstanding,0);
-
-	init_waitqueue_head(&instance->int_cmd_wait_q);
-	init_waitqueue_head(&instance->abort_cmd_wait_q);
-
-	spin_lock_init(&instance->cmd_pool_lock);
-	spin_lock_init(&instance->hba_lock);
-	spin_lock_init(&instance->completion_lock);
-	spin_lock_init(&poll_aen_lock);
-
-	mutex_init(&instance->aen_mutex);
-
-	/*
-	 * Initialize PCI related and misc parameters
-	 */
-	instance->pdev = pdev;
-	instance->host = host;
-	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
-	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
-
-	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-		instance->flag_ieee = 1;
-		sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
-	} else
-		sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
-
-	megasas_dbg_lvl = 0;
-	instance->flag = 0;
-	instance->unload = 1;
-	instance->last_time = 0;
-	instance->disableOnlineCtrlReset = 1;
-
-	INIT_WORK(&instance->work_init, process_fw_state_change_wq);
-
-	/*
-	 * Initialize MFI Firmware
-	 */
-	if (megasas_init_mfi(instance))
-		goto fail_init_mfi;
-
-	/*
-	 * Register IRQ
-	 */
-	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) {
-		printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
-		goto fail_irq;
-	}
-
-	instance->instancet->enable_intr(instance->reg_set);
-
-	/*
-	 * Store instance in PCI softstate
-	 */
-	pci_set_drvdata(pdev, instance);
-
-	/*
-	 * Add this controller to megasas_mgmt_info structure so that it
-	 * can be exported to management applications
-	 */
-	megasas_mgmt_info.count++;
-	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance;
-	megasas_mgmt_info.max_index++;
-
-	/*
-	 * Initiate AEN (Asynchronous Event Notification)
-	 */
-	if (megasas_start_aen(instance)) {
-		printk(KERN_DEBUG "megasas: start aen failed\n");
-		goto fail_start_aen;
-	}
-
-	/*
-	 * Register with SCSI mid-layer
-	 */
-	if (megasas_io_attach(instance))
-		goto fail_io_attach;
-
-	instance->unload = 0;
-	return 0;
-
-      fail_start_aen:
-      fail_io_attach:
-	megasas_mgmt_info.count--;
-	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL;
-	megasas_mgmt_info.max_index--;
-
-	pci_set_drvdata(pdev, NULL);
-	instance->instancet->disable_intr(instance->reg_set);
-	free_irq(instance->pdev->irq, instance);
-
-	megasas_release_mfi(instance);
-
-      fail_irq:
-      fail_init_mfi:
-      fail_alloc_dma_buf:
-	if (instance->evt_detail)
-		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
-				    instance->evt_detail,
-				    instance->evt_detail_h);
-
-	if (instance->producer)
-		pci_free_consistent(pdev, sizeof(u32), instance->producer,
-				    instance->producer_h);
-	if (instance->consumer)
-		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
-				    instance->consumer_h);
-	scsi_host_put(host);
-
-      fail_alloc_instance:
-      fail_set_dma_mask:
-	pci_disable_device(pdev);
-
-	return -ENODEV;
-}
-
-/**
- * megasas_flush_cache -	Requests FW to flush all its caches
- * @instance:			Adapter soft state
- */
-static void megasas_flush_cache(struct megasas_instance *instance)
-{
-	struct megasas_cmd *cmd;
-	struct megasas_dcmd_frame *dcmd;
-
-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
-		return;
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd)
-		return;
-
-	dcmd = &cmd->frame->dcmd;
-
-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-	dcmd->cmd = MFI_CMD_DCMD;
-	dcmd->cmd_status = 0x0;
-	dcmd->sge_count = 0;
-	dcmd->flags = MFI_FRAME_DIR_NONE;
-	dcmd->timeout = 0;
-	dcmd->pad_0 = 0;
-	dcmd->data_xfer_len = 0;
-	dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
-	dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
-
-	megasas_issue_blocked_cmd(instance, cmd);
-
-	megasas_return_cmd(instance, cmd);
-
-	return;
-}
-
-/**
- * megasas_shutdown_controller -	Instructs FW to shutdown the controller
- * @instance:				Adapter soft state
- * @opcode:				Shutdown/Hibernate
- */
-static void megasas_shutdown_controller(struct megasas_instance *instance,
-					u32 opcode)
-{
-	struct megasas_cmd *cmd;
-	struct megasas_dcmd_frame *dcmd;
-
-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
-		return;
-
-	cmd = megasas_get_cmd(instance);
-
-	if (!cmd)
-		return;
-
-	if (instance->aen_cmd)
-		megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
-
-	dcmd = &cmd->frame->dcmd;
-
-	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
-	dcmd->cmd = MFI_CMD_DCMD;
-	dcmd->cmd_status = 0x0;
-	dcmd->sge_count = 0;
-	dcmd->flags = MFI_FRAME_DIR_NONE;
-	dcmd->timeout = 0;
-	dcmd->pad_0 = 0;
-	dcmd->data_xfer_len = 0;
-	dcmd->opcode = opcode;
-
-	megasas_issue_blocked_cmd(instance, cmd);
-
-	megasas_return_cmd(instance, cmd);
-
-	return;
-}
-
-#ifdef CONFIG_PM
-/**
- * megasas_suspend -	driver suspend entry point
- * @pdev:		PCI device structure
- * @state:		PCI power state to suspend routine
- */
-static int
-megasas_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct Scsi_Host *host;
-	struct megasas_instance *instance;
-
-	instance = pci_get_drvdata(pdev);
-	host = instance->host;
-	instance->unload = 1;
-
-	if (poll_mode_io)
-		del_timer_sync(&instance->io_completion_timer);
-
-	megasas_flush_cache(instance);
-	megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
-
-	/* cancel the delayed work if this work still in queue */
-	if (instance->ev != NULL) {
-		struct megasas_aen_event *ev = instance->ev;
-		cancel_delayed_work(
-			(struct delayed_work *)&ev->hotplug_work);
-		flush_scheduled_work();
-		instance->ev = NULL;
-	}
-
-	tasklet_kill(&instance->isr_tasklet);
-
-	pci_set_drvdata(instance->pdev, instance);
-	instance->instancet->disable_intr(instance->reg_set);
-	free_irq(instance->pdev->irq, instance);
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-/**
- * megasas_resume-      driver resume entry point
- * @pdev:               PCI device structure
- */
-static int
-megasas_resume(struct pci_dev *pdev)
-{
-	int rval;
-	struct Scsi_Host *host;
-	struct megasas_instance *instance;
-
-	instance = pci_get_drvdata(pdev);
-	host = instance->host;
-	pci_set_power_state(pdev, PCI_D0);
-	pci_enable_wake(pdev, PCI_D0, 0);
-	pci_restore_state(pdev);
-
-	/*
-	 * PCI prepping: enable device set bus mastering and dma mask
-	 */
-	rval = pci_enable_device_mem(pdev);
-
-	if (rval) {
-		printk(KERN_ERR "megasas: Enable device failed\n");
-		return rval;
-	}
-
-	pci_set_master(pdev);
-
-	if (megasas_set_dma_mask(pdev))
-		goto fail_set_dma_mask;
-
-	/*
-	 * Initialize MFI Firmware
-	 */
-
-	*instance->producer = 0;
-	*instance->consumer = 0;
-
-	atomic_set(&instance->fw_outstanding, 0);
-
-	/*
-	 * We expect the FW state to be READY
-	 */
-	if (megasas_transition_to_ready(instance))
-		goto fail_ready_state;
-
-	if (megasas_issue_init_mfi(instance))
-		goto fail_init_mfi;
-
-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
-			(unsigned long)instance);
-
-	/*
-	 * Register IRQ
-	 */
-	if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
-		"megasas", instance)) {
-		printk(KERN_ERR "megasas: Failed to register IRQ\n");
-		goto fail_irq;
-	}
-
-	instance->instancet->enable_intr(instance->reg_set);
-
-	/*
-	 * Initiate AEN (Asynchronous Event Notification)
-	 */
-	if (megasas_start_aen(instance))
-		printk(KERN_ERR "megasas: Start AEN failed\n");
-
-	/* Initialize the cmd completion timer */
-	if (poll_mode_io)
-		megasas_start_timer(instance, &instance->io_completion_timer,
-				megasas_io_completion_timer,
-				MEGASAS_COMPLETION_TIMER_INTERVAL);
-	instance->unload = 0;
-
-	return 0;
-
-fail_irq:
-fail_init_mfi:
-	if (instance->evt_detail)
-		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
-				instance->evt_detail,
-				instance->evt_detail_h);
-
-	if (instance->producer)
-		pci_free_consistent(pdev, sizeof(u32), instance->producer,
-				instance->producer_h);
-	if (instance->consumer)
-		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
-				instance->consumer_h);
-	scsi_host_put(host);
-
-fail_set_dma_mask:
-fail_ready_state:
-
-	pci_disable_device(pdev);
-
-	return -ENODEV;
-}
-#else
-#define megasas_suspend	NULL
-#define megasas_resume	NULL
-#endif
-
-/**
- * megasas_detach_one -	PCI hot"un"plug entry point
- * @pdev:		PCI device structure
- */
-static void __devexit megasas_detach_one(struct pci_dev *pdev)
-{
-	int i;
-	struct Scsi_Host *host;
-	struct megasas_instance *instance;
-
-	instance = pci_get_drvdata(pdev);
-	instance->unload = 1;
-	host = instance->host;
-
-	if (poll_mode_io)
-		del_timer_sync(&instance->io_completion_timer);
-
-	scsi_remove_host(instance->host);
-	megasas_flush_cache(instance);
-	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
-
-	/* cancel the delayed work if this work still in queue*/
-	if (instance->ev != NULL) {
-		struct megasas_aen_event *ev = instance->ev;
-		cancel_delayed_work(
-			(struct delayed_work *)&ev->hotplug_work);
-		flush_scheduled_work();
-		instance->ev = NULL;
-	}
-
-	tasklet_kill(&instance->isr_tasklet);
-
-	/*
-	 * Take the instance off the instance array. Note that we will not
-	 * decrement the max_index. We let this array be sparse array
-	 */
-	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-		if (megasas_mgmt_info.instance[i] == instance) {
-			megasas_mgmt_info.count--;
-			megasas_mgmt_info.instance[i] = NULL;
-
-			break;
-		}
-	}
-
-	pci_set_drvdata(instance->pdev, NULL);
-
-	instance->instancet->disable_intr(instance->reg_set);
-
-	free_irq(instance->pdev->irq, instance);
-
-	megasas_release_mfi(instance);
-
-	pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
-			    instance->evt_detail, instance->evt_detail_h);
-
-	pci_free_consistent(pdev, sizeof(u32), instance->producer,
-			    instance->producer_h);
-
-	pci_free_consistent(pdev, sizeof(u32), instance->consumer,
-			    instance->consumer_h);
-
-	scsi_host_put(host);
-
-	pci_set_drvdata(pdev, NULL);
-
-	pci_disable_device(pdev);
-
-	return;
-}
-
-/**
- * megasas_shutdown -	Shutdown entry point
- * @device:		Generic device structure
- */
-static void megasas_shutdown(struct pci_dev *pdev)
-{
-	struct megasas_instance *instance = pci_get_drvdata(pdev);
-	instance->unload = 1;
-	megasas_flush_cache(instance);
-	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
-}
-
-/**
- * megasas_mgmt_open -	char node "open" entry point
- */
-static int megasas_mgmt_open(struct inode *inode, struct file *filep)
-{
-	/*
-	 * Allow only those users with admin rights
-	 */
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	return 0;
-}
-
-/**
- * megasas_mgmt_fasync -	Async notifier registration from applications
- *
- * This function adds the calling process to a driver global queue. When an
- * event occurs, SIGIO will be sent to all processes in this queue.
- */
-static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
-{
-	int rc;
-
-	mutex_lock(&megasas_async_queue_mutex);
-
-	rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
-
-	mutex_unlock(&megasas_async_queue_mutex);
-
-	if (rc >= 0) {
-		/* For sanity check when we get ioctl */
-		filep->private_data = filep;
-		return 0;
-	}
-
-	printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc);
-
-	return rc;
-}
-
-/**
- * megasas_mgmt_poll -  char node "poll" entry point
- * */
-static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
-{
-	unsigned int mask;
-	unsigned long flags;
-	poll_wait(file, &megasas_poll_wait, wait);
-	spin_lock_irqsave(&poll_aen_lock, flags);
-	if (megasas_poll_wait_aen)
-		mask =   (POLLIN | POLLRDNORM);
-	else
-		mask = 0;
-	spin_unlock_irqrestore(&poll_aen_lock, flags);
-	return mask;
-}
-
-/**
- * megasas_mgmt_fw_ioctl -	Issues management ioctls to FW
- * @instance:			Adapter soft state
- * @argp:			User's ioctl packet
- */
-static int
-megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
-		      struct megasas_iocpacket __user * user_ioc,
-		      struct megasas_iocpacket *ioc)
-{
-	struct megasas_sge32 *kern_sge32;
-	struct megasas_cmd *cmd;
-	void *kbuff_arr[MAX_IOCTL_SGE];
-	dma_addr_t buf_handle = 0;
-	int error = 0, i;
-	void *sense = NULL;
-	dma_addr_t sense_handle;
-	unsigned long *sense_ptr;
-
-	memset(kbuff_arr, 0, sizeof(kbuff_arr));
-
-	if (ioc->sge_count > MAX_IOCTL_SGE) {
-		printk(KERN_DEBUG "megasas: SGE count [%d] >  max limit [%d]\n",
-		       ioc->sge_count, MAX_IOCTL_SGE);
-		return -EINVAL;
-	}
-
-	cmd = megasas_get_cmd(instance);
-	if (!cmd) {
-		printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * User's IOCTL packet has 2 frames (maximum). Copy those two
-	 * frames into our cmd's frames. cmd->frame's context will get
-	 * overwritten when we copy from user's frames. So set that value
-	 * alone separately
-	 */
-	memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
-	cmd->frame->hdr.context = cmd->index;
-	cmd->frame->hdr.pad_0 = 0;
-
-	/*
-	 * The management interface between applications and the fw uses
-	 * MFI frames. E.g, RAID configuration changes, LD property changes
-	 * etc are accomplishes through different kinds of MFI frames. The
-	 * driver needs to care only about substituting user buffers with
-	 * kernel buffers in SGLs. The location of SGL is embedded in the
-	 * struct iocpacket itself.
-	 */
-	kern_sge32 = (struct megasas_sge32 *)
-	    ((unsigned long)cmd->frame + ioc->sgl_off);
-
-	/*
-	 * For each user buffer, create a mirror buffer and copy in
-	 */
-	for (i = 0; i < ioc->sge_count; i++) {
-		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
-						    ioc->sgl[i].iov_len,
-						    &buf_handle, GFP_KERNEL);
-		if (!kbuff_arr[i]) {
-			printk(KERN_DEBUG "megasas: Failed to alloc "
-			       "kernel SGL buffer for IOCTL \n");
-			error = -ENOMEM;
-			goto out;
-		}
-
-		/*
-		 * We don't change the dma_coherent_mask, so
-		 * pci_alloc_consistent only returns 32bit addresses
-		 */
-		kern_sge32[i].phys_addr = (u32) buf_handle;
-		kern_sge32[i].length = ioc->sgl[i].iov_len;
-
-		/*
-		 * We created a kernel buffer corresponding to the
-		 * user buffer. Now copy in from the user buffer
-		 */
-		if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base,
-				   (u32) (ioc->sgl[i].iov_len))) {
-			error = -EFAULT;
-			goto out;
-		}
-	}
-
-	if (ioc->sense_len) {
-		sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
-					     &sense_handle, GFP_KERNEL);
-		if (!sense) {
-			error = -ENOMEM;
-			goto out;
-		}
-
-		sense_ptr =
-		(unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
-		*sense_ptr = sense_handle;
-	}
-
-	/*
-	 * Set the sync_cmd flag so that the ISR knows not to complete this
-	 * cmd to the SCSI mid-layer
-	 */
-	cmd->sync_cmd = 1;
-	megasas_issue_blocked_cmd(instance, cmd);
-	cmd->sync_cmd = 0;
-
-	/*
-	 * copy out the kernel buffers to user buffers
-	 */
-	for (i = 0; i < ioc->sge_count; i++) {
-		if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i],
-				 ioc->sgl[i].iov_len)) {
-			error = -EFAULT;
-			goto out;
-		}
-	}
-
-	/*
-	 * copy out the sense
-	 */
-	if (ioc->sense_len) {
-		/*
-		 * sense_ptr points to the location that has the user
-		 * sense buffer address
-		 */
-		sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
-				ioc->sense_off);
-
-		if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
-				 sense, ioc->sense_len)) {
-			printk(KERN_ERR "megasas: Failed to copy out to user "
-					"sense data\n");
-			error = -EFAULT;
-			goto out;
-		}
-	}
-
-	/*
-	 * copy the status codes returned by the fw
-	 */
-	if (copy_to_user(&user_ioc->frame.hdr.cmd_status,
-			 &cmd->frame->hdr.cmd_status, sizeof(u8))) {
-		printk(KERN_DEBUG "megasas: Error copying out cmd_status\n");
-		error = -EFAULT;
-	}
-
-      out:
-	if (sense) {
-		dma_free_coherent(&instance->pdev->dev, ioc->sense_len,
-				    sense, sense_handle);
-	}
-
-	for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
-		dma_free_coherent(&instance->pdev->dev,
-				    kern_sge32[i].length,
-				    kbuff_arr[i], kern_sge32[i].phys_addr);
-	}
-
-	megasas_return_cmd(instance, cmd);
-	return error;
-}
-
-static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
-{
-	struct megasas_iocpacket __user *user_ioc =
-	    (struct megasas_iocpacket __user *)arg;
-	struct megasas_iocpacket *ioc;
-	struct megasas_instance *instance;
-	int error;
-	int i;
-	unsigned long flags;
-	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
-
-	ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
-	if (!ioc)
-		return -ENOMEM;
-
-	if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) {
-		error = -EFAULT;
-		goto out_kfree_ioc;
-	}
-
-	instance = megasas_lookup_instance(ioc->host_no);
-	if (!instance) {
-		error = -ENODEV;
-		goto out_kfree_ioc;
-	}
-
-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
-		printk(KERN_ERR "Controller in crit error\n");
-		error = -ENODEV;
-		goto out_kfree_ioc;
-	}
-
-	if (instance->unload == 1) {
-		error = -ENODEV;
-		goto out_kfree_ioc;
-	}
-
-	/*
-	 * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
-	 */
-	if (down_interruptible(&instance->ioctl_sem)) {
-		error = -ERESTARTSYS;
-		goto out_kfree_ioc;
-	}
-
-	for (i = 0; i < wait_time; i++) {
-
-		spin_lock_irqsave(&instance->hba_lock, flags);
-		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
-			spin_unlock_irqrestore(&instance->hba_lock, flags);
-			break;
-		}
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
-			printk(KERN_NOTICE "megasas: waiting"
-				"for controller reset to finish\n");
-		}
-
-		msleep(1000);
-	}
-
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-		printk(KERN_ERR "megaraid_sas: timed out while"
-			"waiting for HBA to recover\n");
-		error = -ENODEV;
-		goto out_kfree_ioc;
-	}
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-	error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
-	up(&instance->ioctl_sem);
-
-      out_kfree_ioc:
-	kfree(ioc);
-	return error;
-}
-
-static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg)
-{
-	struct megasas_instance *instance;
-	struct megasas_aen aen;
-	int error;
-	int i;
-	unsigned long flags;
-	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
-
-	if (file->private_data != file) {
-		printk(KERN_DEBUG "megasas: fasync_helper was not "
-		       "called first\n");
-		return -EINVAL;
-	}
-
-	if (copy_from_user(&aen, (void __user *)arg, sizeof(aen)))
-		return -EFAULT;
-
-	instance = megasas_lookup_instance(aen.host_no);
-
-	if (!instance)
-		return -ENODEV;
-
-	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
-		return -ENODEV;
-	}
-
-	if (instance->unload == 1) {
-		return -ENODEV;
-	}
-
-	for (i = 0; i < wait_time; i++) {
-
-		spin_lock_irqsave(&instance->hba_lock, flags);
-		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
-			spin_unlock_irqrestore(&instance->hba_lock,
-						flags);
-			break;
-		}
-
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
-			printk(KERN_NOTICE "megasas: waiting for"
-				"controller reset to finish\n");
-		}
-
-		msleep(1000);
-	}
-
-	spin_lock_irqsave(&instance->hba_lock, flags);
-	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
-		spin_unlock_irqrestore(&instance->hba_lock, flags);
-		printk(KERN_ERR "megaraid_sas: timed out while waiting"
-				"for HBA to recover.\n");
-		return -ENODEV;
-	}
-	spin_unlock_irqrestore(&instance->hba_lock, flags);
-
-	mutex_lock(&instance->aen_mutex);
-	error = megasas_register_aen(instance, aen.seq_num,
-				     aen.class_locale_word);
-	mutex_unlock(&instance->aen_mutex);
-	return error;
-}
-
-/**
- * megasas_mgmt_ioctl -	char node ioctl entry point
- */
-static long
-megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case MEGASAS_IOC_FIRMWARE:
-		return megasas_mgmt_ioctl_fw(file, arg);
-
-	case MEGASAS_IOC_GET_AEN:
-		return megasas_mgmt_ioctl_aen(file, arg);
-	}
-
-	return -ENOTTY;
-}
-
-#ifdef CONFIG_COMPAT
-static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
-{
-	struct compat_megasas_iocpacket __user *cioc =
-	    (struct compat_megasas_iocpacket __user *)arg;
-	struct megasas_iocpacket __user *ioc =
-	    compat_alloc_user_space(sizeof(struct megasas_iocpacket));
-	int i;
-	int error = 0;
-	compat_uptr_t ptr;
-
-	if (clear_user(ioc, sizeof(*ioc)))
-		return -EFAULT;
-
-	if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) ||
-	    copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) ||
-	    copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) ||
-	    copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) ||
-	    copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) ||
-	    copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
-		return -EFAULT;
-
-	/*
-	 * The sense_ptr is used in megasas_mgmt_fw_ioctl only when
-	 * sense_len is not null, so prepare the 64bit value under
-	 * the same condition.
-	 */
-	if (ioc->sense_len) {
-		void __user **sense_ioc_ptr =
-			(void __user **)(ioc->frame.raw + ioc->sense_off);
-		compat_uptr_t *sense_cioc_ptr =
-			(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
-		if (get_user(ptr, sense_cioc_ptr) ||
-		    put_user(compat_ptr(ptr), sense_ioc_ptr))
-			return -EFAULT;
-	}
-
-	for (i = 0; i < MAX_IOCTL_SGE; i++) {
-		if (get_user(ptr, &cioc->sgl[i].iov_base) ||
-		    put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
-		    copy_in_user(&ioc->sgl[i].iov_len,
-				 &cioc->sgl[i].iov_len, sizeof(compat_size_t)))
-			return -EFAULT;
-	}
-
-	error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc);
-
-	if (copy_in_user(&cioc->frame.hdr.cmd_status,
-			 &ioc->frame.hdr.cmd_status, sizeof(u8))) {
-		printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n");
-		return -EFAULT;
-	}
-	return error;
-}
-
-static long
-megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
-			  unsigned long arg)
-{
-	switch (cmd) {
-	case MEGASAS_IOC_FIRMWARE32:
-		return megasas_mgmt_compat_ioctl_fw(file, arg);
-	case MEGASAS_IOC_GET_AEN:
-		return megasas_mgmt_ioctl_aen(file, arg);
-	}
-
-	return -ENOTTY;
-}
-#endif
-
-/*
- * File operations structure for management interface
- */
-static const struct file_operations megasas_mgmt_fops = {
-	.owner = THIS_MODULE,
-	.open = megasas_mgmt_open,
-	.fasync = megasas_mgmt_fasync,
-	.unlocked_ioctl = megasas_mgmt_ioctl,
-	.poll = megasas_mgmt_poll,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl = megasas_mgmt_compat_ioctl,
-#endif
-	.llseek = noop_llseek,
-};
-
-/*
- * PCI hotplug support registration structure
- */
-static struct pci_driver megasas_pci_driver = {
-
-	.name = "megaraid_sas",
-	.id_table = megasas_pci_table,
-	.probe = megasas_probe_one,
-	.remove = __devexit_p(megasas_detach_one),
-	.suspend = megasas_suspend,
-	.resume = megasas_resume,
-	.shutdown = megasas_shutdown,
-};
-
-/*
- * Sysfs driver attributes
- */
-static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
-{
-	return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n",
-			MEGASAS_VERSION);
-}
-
-static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
-
-static ssize_t
-megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
-{
-	return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
-			MEGASAS_RELDATE);
-}
-
-static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
-		   NULL);
-
-static ssize_t
-megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
-{
-	return sprintf(buf, "%u\n", support_poll_for_event);
-}
-
-static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
-			megasas_sysfs_show_support_poll_for_event, NULL);
-
- static ssize_t
-megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf)
-{
-	return sprintf(buf, "%u\n", support_device_change);
-}
-
-static DRIVER_ATTR(support_device_change, S_IRUGO,
-			megasas_sysfs_show_support_device_change, NULL);
-
-static ssize_t
-megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
-{
-	return sprintf(buf, "%u\n", megasas_dbg_lvl);
-}
-
-static ssize_t
-megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count)
-{
-	int retval = count;
-	if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){
-		printk(KERN_ERR "megasas: could not set dbg_lvl\n");
-		retval = -EINVAL;
-	}
-	return retval;
-}
-
-static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
-		megasas_sysfs_set_dbg_lvl);
-
-static ssize_t
-megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
-{
-	return sprintf(buf, "%u\n", poll_mode_io);
-}
-
-static ssize_t
-megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
-				const char *buf, size_t count)
-{
-	int retval = count;
-	int tmp = poll_mode_io;
-	int i;
-	struct megasas_instance *instance;
-
-	if (sscanf(buf, "%u", &poll_mode_io) < 1) {
-		printk(KERN_ERR "megasas: could not set poll_mode_io\n");
-		retval = -EINVAL;
-	}
-
-	/*
-	 * Check if poll_mode_io is already set or is same as previous value
-	 */
-	if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
-		goto out;
-
-	if (poll_mode_io) {
-		/*
-		 * Start timers for all adapters
-		 */
-		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-			instance = megasas_mgmt_info.instance[i];
-			if (instance) {
-				megasas_start_timer(instance,
-					&instance->io_completion_timer,
-					megasas_io_completion_timer,
-					MEGASAS_COMPLETION_TIMER_INTERVAL);
-			}
-		}
-	} else {
-		/*
-		 * Delete timers for all adapters
-		 */
-		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
-			instance = megasas_mgmt_info.instance[i];
-			if (instance)
-				del_timer_sync(&instance->io_completion_timer);
-		}
-	}
-
-out:
-	return retval;
-}
-
-static void
-megasas_aen_polling(struct work_struct *work)
-{
-	struct megasas_aen_event *ev =
-		container_of(work, struct megasas_aen_event, hotplug_work);
-	struct megasas_instance *instance = ev->instance;
-	union megasas_evt_class_locale class_locale;
-	struct  Scsi_Host *host;
-	struct  scsi_device *sdev1;
-	u16     pd_index = 0;
-	u16	ld_index = 0;
-	int     i, j, doscan = 0;
-	u32 seq_num;
-	int error;
-
-	if (!instance) {
-		printk(KERN_ERR "invalid instance!\n");
-		kfree(ev);
-		return;
-	}
-	instance->ev = NULL;
-	host = instance->host;
-	if (instance->evt_detail) {
-
-		switch (instance->evt_detail->code) {
-		case MR_EVT_PD_INSERTED:
-			if (megasas_get_pd_list(instance) == 0) {
-			for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
-				for (j = 0;
-				j < MEGASAS_MAX_DEV_PER_CHANNEL;
-				j++) {
-
-				pd_index =
-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-				sdev1 =
-				scsi_device_lookup(host, i, j, 0);
-
-				if (instance->pd_list[pd_index].driveState
-						== MR_PD_STATE_SYSTEM) {
-						if (!sdev1) {
-						scsi_add_device(host, i, j, 0);
-						}
-
-					if (sdev1)
-						scsi_device_put(sdev1);
-					}
-				}
-			}
-			}
-			doscan = 0;
-			break;
-
-		case MR_EVT_PD_REMOVED:
-			if (megasas_get_pd_list(instance) == 0) {
-			megasas_get_pd_list(instance);
-			for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
-				for (j = 0;
-				j < MEGASAS_MAX_DEV_PER_CHANNEL;
-				j++) {
-
-				pd_index =
-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-				sdev1 =
-				scsi_device_lookup(host, i, j, 0);
-
-				if (instance->pd_list[pd_index].driveState
-					== MR_PD_STATE_SYSTEM) {
-					if (sdev1) {
-						scsi_device_put(sdev1);
-					}
-				} else {
-					if (sdev1) {
-						scsi_remove_device(sdev1);
-						scsi_device_put(sdev1);
-					}
-				}
-				}
-			}
-			}
-			doscan = 0;
-			break;
-
-		case MR_EVT_LD_OFFLINE:
-		case MR_EVT_LD_DELETED:
-			megasas_get_ld_list(instance);
-			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
-				for (j = 0;
-				j < MEGASAS_MAX_DEV_PER_CHANNEL;
-				j++) {
-
-				ld_index =
-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-				sdev1 = scsi_device_lookup(host,
-					i + MEGASAS_MAX_LD_CHANNELS,
-					j,
-					0);
-
-				if (instance->ld_ids[ld_index] != 0xff) {
-					if (sdev1) {
-						scsi_device_put(sdev1);
-					}
-				} else {
-					if (sdev1) {
-						scsi_remove_device(sdev1);
-						scsi_device_put(sdev1);
-					}
-				}
-				}
-			}
-			doscan = 0;
-			break;
-		case MR_EVT_LD_CREATED:
-			megasas_get_ld_list(instance);
-			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
-				for (j = 0;
-					j < MEGASAS_MAX_DEV_PER_CHANNEL;
-					j++) {
-					ld_index =
-					(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-					sdev1 = scsi_device_lookup(host,
-						i+MEGASAS_MAX_LD_CHANNELS,
-						j, 0);
-
-					if (instance->ld_ids[ld_index] !=
-								0xff) {
-						if (!sdev1) {
-							scsi_add_device(host,
-								i + 2,
-								j, 0);
-						}
-					}
-					if (sdev1) {
-						scsi_device_put(sdev1);
-					}
-				}
-			}
-			doscan = 0;
-			break;
-		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
-		case MR_EVT_FOREIGN_CFG_IMPORTED:
-			doscan = 1;
-			break;
-		default:
-			doscan = 0;
-			break;
-		}
-	} else {
-		printk(KERN_ERR "invalid evt_detail!\n");
-		kfree(ev);
-		return;
-	}
-
-	if (doscan) {
-		printk(KERN_INFO "scanning ...\n");
-		megasas_get_pd_list(instance);
-		for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
-			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
-				pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
-				sdev1 = scsi_device_lookup(host, i, j, 0);
-				if (instance->pd_list[pd_index].driveState ==
-							MR_PD_STATE_SYSTEM) {
-					if (!sdev1) {
-						scsi_add_device(host, i, j, 0);
-					}
-					if (sdev1)
-						scsi_device_put(sdev1);
-				} else {
-					if (sdev1) {
-						scsi_remove_device(sdev1);
-						scsi_device_put(sdev1);
-					}
-				}
-			}
-		}
-
-		megasas_get_ld_list(instance);
-		for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
-			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
-				ld_index =
-				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
-
-				sdev1 = scsi_device_lookup(host,
-					i+MEGASAS_MAX_LD_CHANNELS, j, 0);
-				if (instance->ld_ids[ld_index] != 0xff) {
-					if (!sdev1) {
-						scsi_add_device(host,
-								i+2,
-								j, 0);
-					} else {
-						scsi_device_put(sdev1);
-					}
-				} else {
-					if (sdev1) {
-						scsi_remove_device(sdev1);
-						scsi_device_put(sdev1);
-					}
-				}
-			}
-		}
-	}
-
-	if ( instance->aen_cmd != NULL ) {
-		kfree(ev);
-		return ;
-	}
-
-	seq_num = instance->evt_detail->seq_num + 1;
-
-	/* Register AEN with FW for latest sequence number plus 1 */
-	class_locale.members.reserved = 0;
-	class_locale.members.locale = MR_EVT_LOCALE_ALL;
-	class_locale.members.class = MR_EVT_CLASS_DEBUG;
-	mutex_lock(&instance->aen_mutex);
-	error = megasas_register_aen(instance, seq_num,
-					class_locale.word);
-	mutex_unlock(&instance->aen_mutex);
-
-	if (error)
-		printk(KERN_ERR "register aen failed error %x\n", error);
-
-	kfree(ev);
-}
-
-
-static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
-		megasas_sysfs_show_poll_mode_io,
-		megasas_sysfs_set_poll_mode_io);
-
-/**
- * megasas_init - Driver load entry point
- */
-static int __init megasas_init(void)
-{
-	int rval;
-
-	/*
-	 * Announce driver version and other information
-	 */
-	printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
-	       MEGASAS_EXT_VERSION);
-
-	support_poll_for_event = 2;
-	support_device_change = 1;
-
-	memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
-
-	/*
-	 * Register character device node
-	 */
-	rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops);
-
-	if (rval < 0) {
-		printk(KERN_DEBUG "megasas: failed to open device node\n");
-		return rval;
-	}
-
-	megasas_mgmt_majorno = rval;
-
-	/*
-	 * Register ourselves as PCI hotplug module
-	 */
-	rval = pci_register_driver(&megasas_pci_driver);
-
-	if (rval) {
-		printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n");
-		goto err_pcidrv;
-	}
-
-	rval = driver_create_file(&megasas_pci_driver.driver,
-				  &driver_attr_version);
-	if (rval)
-		goto err_dcf_attr_ver;
-	rval = driver_create_file(&megasas_pci_driver.driver,
-				  &driver_attr_release_date);
-	if (rval)
-		goto err_dcf_rel_date;
-
-	rval = driver_create_file(&megasas_pci_driver.driver,
-				&driver_attr_support_poll_for_event);
-	if (rval)
-		goto err_dcf_support_poll_for_event;
-
-	rval = driver_create_file(&megasas_pci_driver.driver,
-				  &driver_attr_dbg_lvl);
-	if (rval)
-		goto err_dcf_dbg_lvl;
-	rval = driver_create_file(&megasas_pci_driver.driver,
-				  &driver_attr_poll_mode_io);
-	if (rval)
-		goto err_dcf_poll_mode_io;
-
-	rval = driver_create_file(&megasas_pci_driver.driver,
-				&driver_attr_support_device_change);
-	if (rval)
-		goto err_dcf_support_device_change;
-
-	return rval;
-
-err_dcf_support_device_change:
-	driver_remove_file(&megasas_pci_driver.driver,
-		  &driver_attr_poll_mode_io);
-
-err_dcf_poll_mode_io:
-	driver_remove_file(&megasas_pci_driver.driver,
-			   &driver_attr_dbg_lvl);
-err_dcf_dbg_lvl:
-	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_support_poll_for_event);
-
-err_dcf_support_poll_for_event:
-	driver_remove_file(&megasas_pci_driver.driver,
-			   &driver_attr_release_date);
-
-err_dcf_rel_date:
-	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
-err_dcf_attr_ver:
-	pci_unregister_driver(&megasas_pci_driver);
-err_pcidrv:
-	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
-  	return rval;
-}
-
-/**
- * megasas_exit - Driver unload entry point
- */
-static void __exit megasas_exit(void)
-{
-	driver_remove_file(&megasas_pci_driver.driver,
-			   &driver_attr_poll_mode_io);
-	driver_remove_file(&megasas_pci_driver.driver,
-			   &driver_attr_dbg_lvl);
-	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_support_poll_for_event);
-	driver_remove_file(&megasas_pci_driver.driver,
-			&driver_attr_support_device_change);
-	driver_remove_file(&megasas_pci_driver.driver,
-			   &driver_attr_release_date);
-	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
-
-	pci_unregister_driver(&megasas_pci_driver);
-	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
-}
-
-module_init(megasas_init);
-module_exit(megasas_exit);
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index ad16f5e..1b5e375 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1,15 +1,30 @@
 /*
+ *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *		Linux MegaRAID driver for SAS based RAID controllers
+ *  Copyright (c) 2009-2011  LSI Corporation.
  *
- * Copyright (c) 2003-2005  LSI 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 free software; you can redistribute it and/or
- *		modify it under the terms of the GNU 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.
  *
- * FILE		: megaraid_sas.h
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *  FILE: megaraid_sas.h
+ *
+ *  Authors: LSI Corporation
+ *
+ *  Send feedback to: <megaraidlinux@lsi.com>
+ *
+ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ *     ATTN: Linuxraid
  */
 
 #ifndef LSI_MEGARAID_SAS_H
@@ -18,9 +33,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION			"00.00.04.31-rc1"
-#define MEGASAS_RELDATE			"May 3, 2010"
-#define MEGASAS_EXT_VERSION		"Mon. May 3, 11:41:51 PST 2010"
+#define MEGASAS_VERSION				"00.00.05.29-rc1"
+#define MEGASAS_RELDATE				"Dec. 7, 2010"
+#define MEGASAS_EXT_VERSION			"Tue. Dec. 7 17:00:00 PDT 2010"
 
 /*
  * Device IDs
@@ -32,6 +47,7 @@
 #define	PCI_DEVICE_ID_LSI_SAS0079GEN2		0x0079
 #define	PCI_DEVICE_ID_LSI_SAS0073SKINNY		0x0073
 #define	PCI_DEVICE_ID_LSI_SAS0071SKINNY		0x0071
+#define	PCI_DEVICE_ID_LSI_FUSION		0x005b
 
 /*
  * =====================================
@@ -421,7 +437,6 @@
 	* Add properties that can be controlled by
 	* a bit in the following structure.
 	*/
-
 	struct {
 		u32     copyBackDisabled            : 1;
 		u32     SMARTerEnabled              : 1;
@@ -701,6 +716,7 @@
 #define MEGASAS_DEFAULT_INIT_ID			-1
 #define MEGASAS_MAX_LUN				8
 #define MEGASAS_MAX_LD				64
+#define MEGASAS_DEFAULT_CMD_PER_LUN		128
 #define MEGASAS_MAX_PD                          (MEGASAS_MAX_PD_CHANNELS * \
 						MEGASAS_MAX_DEV_PER_CHANNEL)
 #define MEGASAS_MAX_LD_IDS			(MEGASAS_MAX_LD_CHANNELS * \
@@ -769,7 +785,10 @@
 */
  
 struct megasas_register_set {
-	u32 	reserved_0[4];			/*0000h*/
+	u32	doorbell;                       /*0000h*/
+	u32	fusion_seq_offset;		/*0004h*/
+	u32	fusion_host_diag;		/*0008h*/
+	u32	reserved_01;			/*000Ch*/
 
 	u32 	inbound_msg_0;			/*0010h*/
 	u32 	inbound_msg_1;			/*0014h*/
@@ -789,15 +808,18 @@
 	u32 	inbound_queue_port;		/*0040h*/
 	u32 	outbound_queue_port;		/*0044h*/
 
-	u32 	reserved_2[22];			/*0048h*/
+	u32	reserved_2[9];			/*0048h*/
+	u32	reply_post_host_index;		/*006Ch*/
+	u32	reserved_2_2[12];		/*0070h*/
 
 	u32 	outbound_doorbell_clear;	/*00A0h*/
 
 	u32 	reserved_3[3];			/*00A4h*/
 
 	u32 	outbound_scratch_pad ;		/*00B0h*/
+	u32	outbound_scratch_pad_2;         /*00B4h*/
 
-	u32 	reserved_4[3];			/*00B4h*/
+	u32	reserved_4[2];			/*00B8h*/
 
 	u32 	inbound_low_queue_port ;	/*00C0h*/
 
@@ -1272,6 +1294,9 @@
 
 	u16 max_num_sge;
 	u16 max_fw_cmds;
+	/* For Fusion its num IOCTL cmds, for others MFI based its
+	   max_fw_cmds */
+	u16 max_mfi_cmds;
 	u32 max_sectors_per_req;
 	struct megasas_aen_event *ev;
 
@@ -1320,6 +1345,16 @@
 
 	struct timer_list io_completion_timer;
 	struct list_head internal_reset_pending_q;
+
+	/* Ptr to hba specfic information */
+	void *ctrl_context;
+	u8	msi_flag;
+	struct msix_entry msixentry;
+	u64 map_id;
+	struct megasas_cmd *map_update_cmd;
+	unsigned long bar;
+	long reset_flags;
+	struct mutex reset_mutex;
 };
 
 enum {
@@ -1345,6 +1380,13 @@
 		struct megasas_register_set __iomem *);
 	int (*check_reset)(struct megasas_instance *, \
 		struct megasas_register_set __iomem *);
+	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);
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
@@ -1371,7 +1413,13 @@
 	struct list_head list;
 	struct scsi_cmnd *scmd;
 	struct megasas_instance *instance;
-	u32 frame_count;
+	union {
+		struct {
+			u16 smid;
+			u16 resvd;
+		} context;
+		u32 frame_count;
+	};
 };
 
 #define MAX_MGMT_ADAPTERS		1024
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
new file mode 100644
index 0000000..5d6d07b
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -0,0 +1,5444 @@
+/*
+ *  Linux MegaRAID driver for SAS based RAID controllers
+ *
+ *  Copyright (c) 2009-2011  LSI 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
+ *
+ *  FILE: megaraid_sas_base.c
+ *  Version : v00.00.05.29-rc1
+ *
+ *  Authors: LSI Corporation
+ *           Sreenivas Bagalkote
+ *           Sumant Patro
+ *           Bo Yang
+ *
+ *  Send feedback to: <megaraidlinux@lsi.com>
+ *
+ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ *     ATTN: Linuxraid
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/uio.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <linux/blkdev.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include "megaraid_sas_fusion.h"
+#include "megaraid_sas.h"
+
+/*
+ * poll_mode_io:1- schedule complete completion from q cmd
+ */
+static unsigned int poll_mode_io;
+module_param_named(poll_mode_io, poll_mode_io, int, 0);
+MODULE_PARM_DESC(poll_mode_io,
+	"Complete cmds from IO path, (default=0)");
+
+/*
+ * Number of sectors per IO command
+ * Will be set in megasas_init_mfi if user does not provide
+ */
+static unsigned int max_sectors;
+module_param_named(max_sectors, max_sectors, int, 0);
+MODULE_PARM_DESC(max_sectors,
+	"Maximum number of sectors per IO command");
+
+static int msix_disable;
+module_param(msix_disable, int, S_IRUGO);
+MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0");
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MEGASAS_VERSION);
+MODULE_AUTHOR("megaraidlinux@lsi.com");
+MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
+
+int megasas_transition_to_ready(struct megasas_instance *instance);
+static int megasas_get_pd_list(struct megasas_instance *instance);
+static int megasas_issue_init_mfi(struct megasas_instance *instance);
+static int megasas_register_aen(struct megasas_instance *instance,
+				u32 seq_num, u32 class_locale_word);
+/*
+ * PCI ID table for all supported controllers
+ */
+static struct pci_device_id megasas_pci_table[] = {
+
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)},
+	/* xscale IOP */
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
+	/* ppc IOP */
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
+	/* ppc IOP */
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
+	/* gen2*/
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
+	/* gen2*/
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)},
+	/* skinny*/
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)},
+	/* skinny*/
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
+	/* xscale IOP, vega */
+	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
+	/* xscale IOP */
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)},
+	/* Fusion */
+	{}
+};
+
+MODULE_DEVICE_TABLE(pci, megasas_pci_table);
+
+static int megasas_mgmt_majorno;
+static struct megasas_mgmt_info megasas_mgmt_info;
+static struct fasync_struct *megasas_async_queue;
+static DEFINE_MUTEX(megasas_async_queue_mutex);
+
+static int megasas_poll_wait_aen;
+static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
+static u32 support_poll_for_event;
+u32 megasas_dbg_lvl;
+static u32 support_device_change;
+
+/* define lock for aen poll */
+spinlock_t poll_aen_lock;
+
+void
+megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+		     u8 alt_status);
+
+static irqreturn_t megasas_isr(int irq, void *devp);
+static u32
+megasas_init_adapter_mfi(struct megasas_instance *instance);
+u32
+megasas_build_and_issue_cmd(struct megasas_instance *instance,
+			    struct scsi_cmnd *scmd);
+static void megasas_complete_cmd_dpc(unsigned long instance_addr);
+void
+megasas_release_fusion(struct megasas_instance *instance);
+int
+megasas_ioc_init_fusion(struct megasas_instance *instance);
+void
+megasas_free_cmds_fusion(struct megasas_instance *instance);
+u8
+megasas_get_map_info(struct megasas_instance *instance);
+int
+megasas_sync_map_info(struct megasas_instance *instance);
+int
+wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
+void megasas_reset_reply_desc(struct megasas_instance *instance);
+u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
+		      struct LD_LOAD_BALANCE_INFO *lbInfo);
+int megasas_reset_fusion(struct Scsi_Host *shost);
+void megasas_fusion_ocr_wq(struct work_struct *work);
+
+void
+megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+	instance->instancet->fire_cmd(instance,
+		cmd->frame_phys_addr, 0, instance->reg_set);
+}
+
+/**
+ * megasas_get_cmd -	Get a command from the free pool
+ * @instance:		Adapter soft state
+ *
+ * Returns a free command from the pool
+ */
+struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+						  *instance)
+{
+	unsigned long flags;
+	struct megasas_cmd *cmd = NULL;
+
+	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+
+	if (!list_empty(&instance->cmd_pool)) {
+		cmd = list_entry((&instance->cmd_pool)->next,
+				 struct megasas_cmd, list);
+		list_del_init(&cmd->list);
+	} else {
+		printk(KERN_ERR "megasas: Command pool empty!\n");
+	}
+
+	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+	return cmd;
+}
+
+/**
+ * megasas_return_cmd -	Return a cmd to free command pool
+ * @instance:		Adapter soft state
+ * @cmd:		Command packet to be returned to free command pool
+ */
+inline void
+megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+
+	cmd->scmd = NULL;
+	cmd->frame_count = 0;
+	list_add_tail(&cmd->list, &instance->cmd_pool);
+
+	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+}
+
+
+/**
+*	The following functions are defined for xscale
+*	(deviceid : 1064R, PERC5) controllers
+*/
+
+/**
+ * megasas_enable_intr_xscale -	Enables interrupts
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
+{
+	writel(0, &(regs)->outbound_intr_mask);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_xscale -Disables interrupt
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs)
+{
+	u32 mask = 0x1f;
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_xscale - returns the current FW status value
+ * @regs:			MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs)
+{
+	return readl(&(regs)->outbound_msg_0);
+}
+/**
+ * megasas_clear_interrupt_xscale -	Check & clear interrupt
+ * @regs:				MFI register set
+ */
+static int
+megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
+{
+	u32 status;
+	u32 mfiStatus = 0;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (status & MFI_OB_INTR_STATUS_MASK)
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+	if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT)
+		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+
+	/*
+	 * Clear the interrupt by writing back the same value
+	 */
+	if (mfiStatus)
+		writel(status, &regs->outbound_intr_status);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_status);
+
+	return mfiStatus;
+}
+
+/**
+ * megasas_fire_cmd_xscale -	Sends command to the FW
+ * @frame_phys_addr :		Physical address of cmd
+ * @frame_count :		Number of frames for the command
+ * @regs :			MFI register set
+ */
+static inline void
+megasas_fire_cmd_xscale(struct megasas_instance *instance,
+		dma_addr_t frame_phys_addr,
+		u32 frame_count,
+		struct megasas_register_set __iomem *regs)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	writel((frame_phys_addr >> 3)|(frame_count),
+	       &(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_xscale -  For controller reset
+ * @regs:                              MFI register set
+ */
+static int
+megasas_adp_reset_xscale(struct megasas_instance *instance,
+	struct megasas_register_set __iomem *regs)
+{
+	u32 i;
+	u32 pcidata;
+	writel(MFI_ADP_RESET, &regs->inbound_doorbell);
+
+	for (i = 0; i < 3; i++)
+		msleep(1000); /* sleep for 3 secs */
+	pcidata  = 0;
+	pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata);
+	printk(KERN_NOTICE "pcidata = %x\n", pcidata);
+	if (pcidata & 0x2) {
+		printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata);
+		pcidata &= ~0x2;
+		pci_write_config_dword(instance->pdev,
+				MFI_1068_PCSR_OFFSET, pcidata);
+
+		for (i = 0; i < 2; i++)
+			msleep(1000); /* need to wait 2 secs again */
+
+		pcidata  = 0;
+		pci_read_config_dword(instance->pdev,
+				MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata);
+		printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
+		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
+			printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata);
+			pcidata = 0;
+			pci_write_config_dword(instance->pdev,
+				MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
+		}
+	}
+	return 0;
+}
+
+/**
+ * megasas_check_reset_xscale -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_xscale(struct megasas_instance *instance,
+		struct megasas_register_set __iomem *regs)
+{
+	u32 consumer;
+	consumer = *instance->consumer;
+
+	if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) &&
+		(*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
+		return 1;
+	}
+	return 0;
+}
+
+static struct megasas_instance_template megasas_instance_template_xscale = {
+
+	.fire_cmd = megasas_fire_cmd_xscale,
+	.enable_intr = megasas_enable_intr_xscale,
+	.disable_intr = megasas_disable_intr_xscale,
+	.clear_intr = megasas_clear_intr_xscale,
+	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+	.adp_reset = megasas_adp_reset_xscale,
+	.check_reset = megasas_check_reset_xscale,
+	.service_isr = megasas_isr,
+	.tasklet = megasas_complete_cmd_dpc,
+	.init_adapter = megasas_init_adapter_mfi,
+	.build_and_issue_cmd = megasas_build_and_issue_cmd,
+	.issue_dcmd = megasas_issue_dcmd,
+};
+
+/**
+*	This is the end of set of functions & definitions specific
+*	to xscale (deviceid : 1064R, PERC5) controllers
+*/
+
+/**
+*	The following functions are defined for ppc (deviceid : 0x60)
+* 	controllers
+*/
+
+/**
+ * megasas_enable_intr_ppc -	Enables interrupts
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+
+	writel(~0x80000000, &(regs)->outbound_intr_mask);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_ppc -	Disable interrupt
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+	u32 mask = 0xFFFFFFFF;
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_ppc - returns the current FW status value
+ * @regs:			MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
+{
+	return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_ppc -	Check & clear interrupt
+ * @regs:				MFI register set
+ */
+static int
+megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+	u32 status;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
+		return 0;
+	}
+
+	/*
+	 * Clear the interrupt by writing back the same value
+	 */
+	writel(status, &regs->outbound_doorbell_clear);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_doorbell_clear);
+
+	return 1;
+}
+/**
+ * megasas_fire_cmd_ppc -	Sends command to the FW
+ * @frame_phys_addr :		Physical address of cmd
+ * @frame_count :		Number of frames for the command
+ * @regs :			MFI register set
+ */
+static inline void
+megasas_fire_cmd_ppc(struct megasas_instance *instance,
+		dma_addr_t frame_phys_addr,
+		u32 frame_count,
+		struct megasas_register_set __iomem *regs)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	writel((frame_phys_addr | (frame_count<<1))|1,
+			&(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_ppc -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_ppc(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_ppc -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_ppc(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+static struct megasas_instance_template megasas_instance_template_ppc = {
+
+	.fire_cmd = megasas_fire_cmd_ppc,
+	.enable_intr = megasas_enable_intr_ppc,
+	.disable_intr = megasas_disable_intr_ppc,
+	.clear_intr = megasas_clear_intr_ppc,
+	.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+	.adp_reset = megasas_adp_reset_ppc,
+	.check_reset = megasas_check_reset_ppc,
+	.service_isr = megasas_isr,
+	.tasklet = megasas_complete_cmd_dpc,
+	.init_adapter = megasas_init_adapter_mfi,
+	.build_and_issue_cmd = megasas_build_and_issue_cmd,
+	.issue_dcmd = megasas_issue_dcmd,
+};
+
+/**
+ * megasas_enable_intr_skinny -	Enables interrupts
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
+{
+	writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
+
+	writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_skinny -	Disables interrupt
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
+{
+	u32 mask = 0xFFFFFFFF;
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_skinny - returns the current FW status value
+ * @regs:			MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs)
+{
+	return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_skinny -	Check & clear interrupt
+ * @regs:				MFI register set
+ */
+static int
+megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
+{
+	u32 status;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
+		return 0;
+	}
+
+	/*
+	 * Clear the interrupt by writing back the same value
+	 */
+	writel(status, &regs->outbound_intr_status);
+
+	/*
+	* dummy read to flush PCI
+	*/
+	readl(&regs->outbound_intr_status);
+
+	return 1;
+}
+
+/**
+ * megasas_fire_cmd_skinny -	Sends command to the FW
+ * @frame_phys_addr :		Physical address of cmd
+ * @frame_count :		Number of frames for the command
+ * @regs :			MFI register set
+ */
+static inline void
+megasas_fire_cmd_skinny(struct megasas_instance *instance,
+			dma_addr_t frame_phys_addr,
+			u32 frame_count,
+			struct megasas_register_set __iomem *regs)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	writel(0, &(regs)->inbound_high_queue_port);
+	writel((frame_phys_addr | (frame_count<<1))|1,
+		&(regs)->inbound_low_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_skinny -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_skinny(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_skinny -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_skinny(struct megasas_instance *instance,
+				struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+static struct megasas_instance_template megasas_instance_template_skinny = {
+
+	.fire_cmd = megasas_fire_cmd_skinny,
+	.enable_intr = megasas_enable_intr_skinny,
+	.disable_intr = megasas_disable_intr_skinny,
+	.clear_intr = megasas_clear_intr_skinny,
+	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
+	.adp_reset = megasas_adp_reset_skinny,
+	.check_reset = megasas_check_reset_skinny,
+	.service_isr = megasas_isr,
+	.tasklet = megasas_complete_cmd_dpc,
+	.init_adapter = megasas_init_adapter_mfi,
+	.build_and_issue_cmd = megasas_build_and_issue_cmd,
+	.issue_dcmd = megasas_issue_dcmd,
+};
+
+
+/**
+*	The following functions are defined for gen2 (deviceid : 0x78 0x79)
+*	controllers
+*/
+
+/**
+ * megasas_enable_intr_gen2 -  Enables interrupts
+ * @regs:                      MFI register set
+ */
+static inline void
+megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+
+	/* write ~0x00000005 (4 & 1) to the intr mask*/
+	writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_gen2 - Disables interrupt
+ * @regs:                      MFI register set
+ */
+static inline void
+megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+	u32 mask = 0xFFFFFFFF;
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_gen2 - returns the current FW status value
+ * @regs:                      MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
+{
+	return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_gen2 -      Check & clear interrupt
+ * @regs:                              MFI register set
+ */
+static int
+megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
+{
+	u32 status;
+	u32 mfiStatus = 0;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) {
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+	}
+	if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) {
+		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+	}
+
+	/*
+	 * Clear the interrupt by writing back the same value
+	 */
+	if (mfiStatus)
+		writel(status, &regs->outbound_doorbell_clear);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_status);
+
+	return mfiStatus;
+}
+/**
+ * megasas_fire_cmd_gen2 -     Sends command to the FW
+ * @frame_phys_addr :          Physical address of cmd
+ * @frame_count :              Number of frames for the command
+ * @regs :                     MFI register set
+ */
+static inline void
+megasas_fire_cmd_gen2(struct megasas_instance *instance,
+			dma_addr_t frame_phys_addr,
+			u32 frame_count,
+			struct megasas_register_set __iomem *regs)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	writel((frame_phys_addr | (frame_count<<1))|1,
+			&(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_gen2 -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_gen2(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *reg_set)
+{
+	u32			retry = 0 ;
+	u32			HostDiag;
+
+	writel(0, &reg_set->seq_offset);
+	writel(4, &reg_set->seq_offset);
+	writel(0xb, &reg_set->seq_offset);
+	writel(2, &reg_set->seq_offset);
+	writel(7, &reg_set->seq_offset);
+	writel(0xd, &reg_set->seq_offset);
+	msleep(1000);
+
+	HostDiag = (u32)readl(&reg_set->host_diag);
+
+	while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
+		msleep(100);
+		HostDiag = (u32)readl(&reg_set->host_diag);
+		printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
+					retry, HostDiag);
+
+		if (retry++ >= 100)
+			return 1;
+
+	}
+
+	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
+
+	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+
+	ssleep(10);
+
+	HostDiag = (u32)readl(&reg_set->host_diag);
+	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
+		msleep(100);
+		HostDiag = (u32)readl(&reg_set->host_diag);
+		printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
+				retry, HostDiag);
+
+		if (retry++ >= 1000)
+			return 1;
+
+	}
+	return 0;
+}
+
+/**
+ * megasas_check_reset_gen2 -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_gen2(struct megasas_instance *instance,
+		struct megasas_register_set __iomem *regs)
+{
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		return 1;
+	}
+
+	return 0;
+}
+
+static struct megasas_instance_template megasas_instance_template_gen2 = {
+
+	.fire_cmd = megasas_fire_cmd_gen2,
+	.enable_intr = megasas_enable_intr_gen2,
+	.disable_intr = megasas_disable_intr_gen2,
+	.clear_intr = megasas_clear_intr_gen2,
+	.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+	.adp_reset = megasas_adp_reset_gen2,
+	.check_reset = megasas_check_reset_gen2,
+	.service_isr = megasas_isr,
+	.tasklet = megasas_complete_cmd_dpc,
+	.init_adapter = megasas_init_adapter_mfi,
+	.build_and_issue_cmd = megasas_build_and_issue_cmd,
+	.issue_dcmd = megasas_issue_dcmd,
+};
+
+/**
+*	This is the end of set of functions & definitions
+*       specific to gen2 (deviceid : 0x78, 0x79) controllers
+*/
+
+/*
+ * Template added for TB (Fusion)
+ */
+extern struct megasas_instance_template megasas_instance_template_fusion;
+
+/**
+ * megasas_issue_polled -	Issues a polling command
+ * @instance:			Adapter soft state
+ * @cmd:			Command packet to be issued
+ *
+ * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
+ */
+int
+megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+
+	struct megasas_header *frame_hdr = &cmd->frame->hdr;
+
+	frame_hdr->cmd_status = 0xFF;
+	frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+	/*
+	 * Issue the frame using inbound queue port
+	 */
+	instance->instancet->issue_dcmd(instance, cmd);
+
+	/*
+	 * Wait for cmd_status to change
+	 */
+	return wait_and_poll(instance, cmd);
+}
+
+/**
+ * megasas_issue_blocked_cmd -	Synchronous wrapper around regular FW cmds
+ * @instance:			Adapter soft state
+ * @cmd:			Command to be issued
+ *
+ * This function waits on an event for the command to be returned from ISR.
+ * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
+ * Used to issue ioctl commands.
+ */
+static int
+megasas_issue_blocked_cmd(struct megasas_instance *instance,
+			  struct megasas_cmd *cmd)
+{
+	cmd->cmd_status = ENODATA;
+
+	instance->instancet->issue_dcmd(instance, cmd);
+
+	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
+
+	return 0;
+}
+
+/**
+ * megasas_issue_blocked_abort_cmd -	Aborts previously issued cmd
+ * @instance:				Adapter soft state
+ * @cmd_to_abort:			Previously issued cmd to be aborted
+ *
+ * MFI firmware can abort previously issued AEN comamnd (automatic event
+ * notification). The megasas_issue_blocked_abort_cmd() issues such abort
+ * cmd and waits for return status.
+ * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
+ */
+static int
+megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
+				struct megasas_cmd *cmd_to_abort)
+{
+	struct megasas_cmd *cmd;
+	struct megasas_abort_frame *abort_fr;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd)
+		return -1;
+
+	abort_fr = &cmd->frame->abort;
+
+	/*
+	 * Prepare and issue the abort frame
+	 */
+	abort_fr->cmd = MFI_CMD_ABORT;
+	abort_fr->cmd_status = 0xFF;
+	abort_fr->flags = 0;
+	abort_fr->abort_context = cmd_to_abort->index;
+	abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
+	abort_fr->abort_mfi_phys_addr_hi = 0;
+
+	cmd->sync_cmd = 1;
+	cmd->cmd_status = 0xFF;
+
+	instance->instancet->issue_dcmd(instance, cmd);
+
+	/*
+	 * Wait for this cmd to complete
+	 */
+	wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
+	cmd->sync_cmd = 0;
+
+	megasas_return_cmd(instance, cmd);
+	return 0;
+}
+
+/**
+ * megasas_make_sgl32 -	Prepares 32-bit SGL
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command from the mid-layer
+ * @mfi_sgl:		SGL to be filled in
+ *
+ * If successful, this function returns the number of SG elements. Otherwise,
+ * it returnes -1.
+ */
+static int
+megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
+		   union megasas_sgl *mfi_sgl)
+{
+	int i;
+	int sge_count;
+	struct scatterlist *os_sgl;
+
+	sge_count = scsi_dma_map(scp);
+	BUG_ON(sge_count < 0);
+
+	if (sge_count) {
+		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+			mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
+			mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
+		}
+	}
+	return sge_count;
+}
+
+/**
+ * megasas_make_sgl64 -	Prepares 64-bit SGL
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command from the mid-layer
+ * @mfi_sgl:		SGL to be filled in
+ *
+ * If successful, this function returns the number of SG elements. Otherwise,
+ * it returnes -1.
+ */
+static int
+megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
+		   union megasas_sgl *mfi_sgl)
+{
+	int i;
+	int sge_count;
+	struct scatterlist *os_sgl;
+
+	sge_count = scsi_dma_map(scp);
+	BUG_ON(sge_count < 0);
+
+	if (sge_count) {
+		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+			mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
+			mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
+		}
+	}
+	return sge_count;
+}
+
+/**
+ * megasas_make_sgl_skinny - Prepares IEEE SGL
+ * @instance:           Adapter soft state
+ * @scp:                SCSI command from the mid-layer
+ * @mfi_sgl:            SGL to be filled in
+ *
+ * If successful, this function returns the number of SG elements. Otherwise,
+ * it returnes -1.
+ */
+static int
+megasas_make_sgl_skinny(struct megasas_instance *instance,
+		struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
+{
+	int i;
+	int sge_count;
+	struct scatterlist *os_sgl;
+
+	sge_count = scsi_dma_map(scp);
+
+	if (sge_count) {
+		scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+			mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
+			mfi_sgl->sge_skinny[i].phys_addr =
+						sg_dma_address(os_sgl);
+			mfi_sgl->sge_skinny[i].flag = 0;
+		}
+	}
+	return sge_count;
+}
+
+ /**
+ * megasas_get_frame_count - Computes the number of frames
+ * @frame_type		: type of frame- io or pthru frame
+ * @sge_count		: number of sg elements
+ *
+ * Returns the number of frames required for numnber of sge's (sge_count)
+ */
+
+static u32 megasas_get_frame_count(struct megasas_instance *instance,
+			u8 sge_count, u8 frame_type)
+{
+	int num_cnt;
+	int sge_bytes;
+	u32 sge_sz;
+	u32 frame_count=0;
+
+	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+	    sizeof(struct megasas_sge32);
+
+	if (instance->flag_ieee) {
+		sge_sz = sizeof(struct megasas_sge_skinny);
+	}
+
+	/*
+	 * Main frame can contain 2 SGEs for 64-bit SGLs and
+	 * 3 SGEs for 32-bit SGLs for ldio &
+	 * 1 SGEs for 64-bit SGLs and
+	 * 2 SGEs for 32-bit SGLs for pthru frame
+	 */
+	if (unlikely(frame_type == PTHRU_FRAME)) {
+		if (instance->flag_ieee == 1) {
+			num_cnt = sge_count - 1;
+		} else if (IS_DMA64)
+			num_cnt = sge_count - 1;
+		else
+			num_cnt = sge_count - 2;
+	} else {
+		if (instance->flag_ieee == 1) {
+			num_cnt = sge_count - 1;
+		} else if (IS_DMA64)
+			num_cnt = sge_count - 2;
+		else
+			num_cnt = sge_count - 3;
+	}
+
+	if(num_cnt>0){
+		sge_bytes = sge_sz * num_cnt;
+
+		frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) +
+		    ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ;
+	}
+	/* Main frame */
+	frame_count +=1;
+
+	if (frame_count > 7)
+		frame_count = 8;
+	return frame_count;
+}
+
+/**
+ * megasas_build_dcdb -	Prepares a direct cdb (DCDB) command
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command
+ * @cmd:		Command to be prepared in
+ *
+ * This function prepares CDB commands. These are typcially pass-through
+ * commands to the devices.
+ */
+static int
+megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+		   struct megasas_cmd *cmd)
+{
+	u32 is_logical;
+	u32 device_id;
+	u16 flags = 0;
+	struct megasas_pthru_frame *pthru;
+
+	is_logical = MEGASAS_IS_LOGICAL(scp);
+	device_id = MEGASAS_DEV_INDEX(instance, scp);
+	pthru = (struct megasas_pthru_frame *)cmd->frame;
+
+	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+		flags = MFI_FRAME_DIR_WRITE;
+	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+		flags = MFI_FRAME_DIR_READ;
+	else if (scp->sc_data_direction == PCI_DMA_NONE)
+		flags = MFI_FRAME_DIR_NONE;
+
+	if (instance->flag_ieee == 1) {
+		flags |= MFI_FRAME_IEEE;
+	}
+
+	/*
+	 * Prepare the DCDB frame
+	 */
+	pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO;
+	pthru->cmd_status = 0x0;
+	pthru->scsi_status = 0x0;
+	pthru->target_id = device_id;
+	pthru->lun = scp->device->lun;
+	pthru->cdb_len = scp->cmd_len;
+	pthru->timeout = 0;
+	pthru->pad_0 = 0;
+	pthru->flags = flags;
+	pthru->data_xfer_len = scsi_bufflen(scp);
+
+	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+
+	/*
+	* If the command is for the tape device, set the
+	* pthru timeout to the os layer timeout value.
+	*/
+	if (scp->device->type == TYPE_TAPE) {
+		if ((scp->request->timeout / HZ) > 0xFFFF)
+			pthru->timeout = 0xFFFF;
+		else
+			pthru->timeout = scp->request->timeout / HZ;
+	}
+
+	/*
+	 * Construct SGL
+	 */
+	if (instance->flag_ieee == 1) {
+		pthru->flags |= MFI_FRAME_SGL64;
+		pthru->sge_count = megasas_make_sgl_skinny(instance, scp,
+						      &pthru->sgl);
+	} else if (IS_DMA64) {
+		pthru->flags |= MFI_FRAME_SGL64;
+		pthru->sge_count = megasas_make_sgl64(instance, scp,
+						      &pthru->sgl);
+	} else
+		pthru->sge_count = megasas_make_sgl32(instance, scp,
+						      &pthru->sgl);
+
+	if (pthru->sge_count > instance->max_num_sge) {
+		printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n",
+			pthru->sge_count);
+		return 0;
+	}
+
+	/*
+	 * Sense info specific
+	 */
+	pthru->sense_len = SCSI_SENSE_BUFFERSIZE;
+	pthru->sense_buf_phys_addr_hi = 0;
+	pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
+
+	/*
+	 * Compute the total number of frames this command consumes. FW uses
+	 * this number to pull sufficient number of frames from host memory.
+	 */
+	cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count,
+							PTHRU_FRAME);
+
+	return cmd->frame_count;
+}
+
+/**
+ * megasas_build_ldio -	Prepares IOs to logical devices
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command
+ * @cmd:		Command to be prepared
+ *
+ * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
+ */
+static int
+megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+		   struct megasas_cmd *cmd)
+{
+	u32 device_id;
+	u8 sc = scp->cmnd[0];
+	u16 flags = 0;
+	struct megasas_io_frame *ldio;
+
+	device_id = MEGASAS_DEV_INDEX(instance, scp);
+	ldio = (struct megasas_io_frame *)cmd->frame;
+
+	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+		flags = MFI_FRAME_DIR_WRITE;
+	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+		flags = MFI_FRAME_DIR_READ;
+
+	if (instance->flag_ieee == 1) {
+		flags |= MFI_FRAME_IEEE;
+	}
+
+	/*
+	 * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
+	 */
+	ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ;
+	ldio->cmd_status = 0x0;
+	ldio->scsi_status = 0x0;
+	ldio->target_id = device_id;
+	ldio->timeout = 0;
+	ldio->reserved_0 = 0;
+	ldio->pad_0 = 0;
+	ldio->flags = flags;
+	ldio->start_lba_hi = 0;
+	ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0;
+
+	/*
+	 * 6-byte READ(0x08) or WRITE(0x0A) cdb
+	 */
+	if (scp->cmd_len == 6) {
+		ldio->lba_count = (u32) scp->cmnd[4];
+		ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) |
+		    ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
+
+		ldio->start_lba_lo &= 0x1FFFFF;
+	}
+
+	/*
+	 * 10-byte READ(0x28) or WRITE(0x2A) cdb
+	 */
+	else if (scp->cmd_len == 10) {
+		ldio->lba_count = (u32) scp->cmnd[8] |
+		    ((u32) scp->cmnd[7] << 8);
+		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+		    ((u32) scp->cmnd[3] << 16) |
+		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+	}
+
+	/*
+	 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
+	 */
+	else if (scp->cmd_len == 12) {
+		ldio->lba_count = ((u32) scp->cmnd[6] << 24) |
+		    ((u32) scp->cmnd[7] << 16) |
+		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+
+		ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+		    ((u32) scp->cmnd[3] << 16) |
+		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+	}
+
+	/*
+	 * 16-byte READ(0x88) or WRITE(0x8A) cdb
+	 */
+	else if (scp->cmd_len == 16) {
+		ldio->lba_count = ((u32) scp->cmnd[10] << 24) |
+		    ((u32) scp->cmnd[11] << 16) |
+		    ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
+
+		ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) |
+		    ((u32) scp->cmnd[7] << 16) |
+		    ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+
+		ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) |
+		    ((u32) scp->cmnd[3] << 16) |
+		    ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+
+	}
+
+	/*
+	 * Construct SGL
+	 */
+	if (instance->flag_ieee) {
+		ldio->flags |= MFI_FRAME_SGL64;
+		ldio->sge_count = megasas_make_sgl_skinny(instance, scp,
+					      &ldio->sgl);
+	} else if (IS_DMA64) {
+		ldio->flags |= MFI_FRAME_SGL64;
+		ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
+	} else
+		ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
+
+	if (ldio->sge_count > instance->max_num_sge) {
+		printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n",
+			ldio->sge_count);
+		return 0;
+	}
+
+	/*
+	 * Sense info specific
+	 */
+	ldio->sense_len = SCSI_SENSE_BUFFERSIZE;
+	ldio->sense_buf_phys_addr_hi = 0;
+	ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr;
+
+	/*
+	 * Compute the total number of frames this command consumes. FW uses
+	 * this number to pull sufficient number of frames from host memory.
+	 */
+	cmd->frame_count = megasas_get_frame_count(instance,
+			ldio->sge_count, IO_FRAME);
+
+	return cmd->frame_count;
+}
+
+/**
+ * megasas_is_ldio -		Checks if the cmd is for logical drive
+ * @scmd:			SCSI command
+ *
+ * Called by megasas_queue_command to find out if the command to be queued
+ * is a logical drive command
+ */
+inline int megasas_is_ldio(struct scsi_cmnd *cmd)
+{
+	if (!MEGASAS_IS_LOGICAL(cmd))
+		return 0;
+	switch (cmd->cmnd[0]) {
+	case READ_10:
+	case WRITE_10:
+	case READ_12:
+	case WRITE_12:
+	case READ_6:
+	case WRITE_6:
+	case READ_16:
+	case WRITE_16:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+ /**
+ * megasas_dump_pending_frames -	Dumps the frame address of all pending cmds
+ *                              	in FW
+ * @instance:				Adapter soft state
+ */
+static inline void
+megasas_dump_pending_frames(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	int i,n;
+	union megasas_sgl *mfi_sgl;
+	struct megasas_io_frame *ldio;
+	struct megasas_pthru_frame *pthru;
+	u32 sgcount;
+	u32 max_cmd = instance->max_fw_cmds;
+
+	printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no);
+	printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding));
+	if (IS_DMA64)
+		printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no);
+	else
+		printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no);
+
+	printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no);
+	for (i = 0; i < max_cmd; i++) {
+		cmd = instance->cmd_list[i];
+		if(!cmd->scmd)
+			continue;
+		printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr);
+		if (megasas_is_ldio(cmd->scmd)){
+			ldio = (struct megasas_io_frame *)cmd->frame;
+			mfi_sgl = &ldio->sgl;
+			sgcount = ldio->sge_count;
+			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount);
+		}
+		else {
+			pthru = (struct megasas_pthru_frame *) cmd->frame;
+			mfi_sgl = &pthru->sgl;
+			sgcount = pthru->sge_count;
+			printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount);
+		}
+	if(megasas_dbg_lvl & MEGASAS_DBG_LVL){
+		for (n = 0; n < sgcount; n++){
+			if (IS_DMA64)
+				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ;
+			else
+				printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ;
+			}
+		}
+		printk(KERN_ERR "\n");
+	} /*for max_cmd*/
+	printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no);
+	for (i = 0; i < max_cmd; i++) {
+
+		cmd = instance->cmd_list[i];
+
+		if(cmd->sync_cmd == 1){
+			printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr);
+		}
+	}
+	printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
+}
+
+u32
+megasas_build_and_issue_cmd(struct megasas_instance *instance,
+			    struct scsi_cmnd *scmd)
+{
+	struct megasas_cmd *cmd;
+	u32 frame_count;
+
+	cmd = megasas_get_cmd(instance);
+	if (!cmd)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	/*
+	 * Logical drive command
+	 */
+	if (megasas_is_ldio(scmd))
+		frame_count = megasas_build_ldio(instance, scmd, cmd);
+	else
+		frame_count = megasas_build_dcdb(instance, scmd, cmd);
+
+	if (!frame_count)
+		goto out_return_cmd;
+
+	cmd->scmd = scmd;
+	scmd->SCp.ptr = (char *)cmd;
+
+	/*
+	 * Issue the command to the FW
+	 */
+	atomic_inc(&instance->fw_outstanding);
+
+	instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
+				cmd->frame_count-1, instance->reg_set);
+	/*
+	 * Check if we have pend cmds to be completed
+	 */
+	if (poll_mode_io && atomic_read(&instance->fw_outstanding))
+		tasklet_schedule(&instance->isr_tasklet);
+
+	return 0;
+out_return_cmd:
+	megasas_return_cmd(instance, cmd);
+	return 1;
+}
+
+
+/**
+ * megasas_queue_command -	Queue entry point
+ * @scmd:			SCSI command to be queued
+ * @done:			Callback entry point
+ */
+static int
+megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
+{
+	struct megasas_instance *instance;
+	unsigned long flags;
+
+	instance = (struct megasas_instance *)
+	    scmd->device->host->hostdata;
+
+	if (instance->issuepend_done == 0)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	scmd->scsi_done = done;
+	scmd->result = 0;
+
+	if (MEGASAS_IS_LOGICAL(scmd) &&
+	    (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
+		scmd->result = DID_BAD_TARGET << 16;
+		goto out_done;
+	}
+
+	switch (scmd->cmnd[0]) {
+	case SYNCHRONIZE_CACHE:
+		/*
+		 * FW takes care of flush cache on its own
+		 * No need to send it down
+		 */
+		scmd->result = DID_OK << 16;
+		goto out_done;
+	default:
+		break;
+	}
+
+	if (instance->instancet->build_and_issue_cmd(instance, scmd)) {
+		printk(KERN_ERR "megasas: Err returned from build_and_issue_cmd\n");
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	return 0;
+
+ out_done:
+	done(scmd);
+	return 0;
+}
+
+static DEF_SCSI_QCMD(megasas_queue_command)
+
+static struct megasas_instance *megasas_lookup_instance(u16 host_no)
+{
+	int i;
+
+	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+
+		if ((megasas_mgmt_info.instance[i]) &&
+		    (megasas_mgmt_info.instance[i]->host->host_no == host_no))
+			return megasas_mgmt_info.instance[i];
+	}
+
+	return NULL;
+}
+
+static int megasas_slave_configure(struct scsi_device *sdev)
+{
+	u16             pd_index = 0;
+	struct  megasas_instance *instance ;
+
+	instance = megasas_lookup_instance(sdev->host->host_no);
+
+	/*
+	* Don't export physical disk devices to the disk driver.
+	*
+	* FIXME: Currently we don't export them to the midlayer at all.
+	*        That will be fixed once LSI engineers have audited the
+	*        firmware for possible issues.
+	*/
+	if (sdev->channel < MEGASAS_MAX_PD_CHANNELS &&
+				sdev->type == TYPE_DISK) {
+		pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
+								sdev->id;
+		if (instance->pd_list[pd_index].driveState ==
+						MR_PD_STATE_SYSTEM) {
+			blk_queue_rq_timeout(sdev->request_queue,
+				MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
+			return 0;
+		}
+		return -ENXIO;
+	}
+
+	/*
+	* The RAID firmware may require extended timeouts.
+	*/
+	blk_queue_rq_timeout(sdev->request_queue,
+		MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
+	return 0;
+}
+
+static int megasas_slave_alloc(struct scsi_device *sdev)
+{
+	u16             pd_index = 0;
+	struct megasas_instance *instance ;
+	instance = megasas_lookup_instance(sdev->host->host_no);
+	if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) &&
+				(sdev->type == TYPE_DISK)) {
+		/*
+		 * Open the OS scan to the SYSTEM PD
+		 */
+		pd_index =
+			(sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
+			sdev->id;
+		if ((instance->pd_list[pd_index].driveState ==
+					MR_PD_STATE_SYSTEM) &&
+			(instance->pd_list[pd_index].driveType ==
+						TYPE_DISK)) {
+			return 0;
+		}
+		return -ENXIO;
+	}
+	return 0;
+}
+
+void megaraid_sas_kill_hba(struct megasas_instance *instance)
+{
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+	    (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+	    (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)) {
+		writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
+	} else {
+		writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell);
+	}
+}
+
+ /**
+  * megasas_check_and_restore_queue_depth - Check if queue depth needs to be
+  *					restored to max value
+  * @instance:			Adapter soft state
+  *
+  */
+void
+megasas_check_and_restore_queue_depth(struct megasas_instance *instance)
+{
+	unsigned long flags;
+	if (instance->flag & MEGASAS_FW_BUSY
+		&& time_after(jiffies, instance->last_time + 5 * HZ)
+		&& atomic_read(&instance->fw_outstanding) < 17) {
+
+		spin_lock_irqsave(instance->host->host_lock, flags);
+		instance->flag &= ~MEGASAS_FW_BUSY;
+		if ((instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+			(instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+			instance->host->can_queue =
+				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+		} else
+			instance->host->can_queue =
+				instance->max_fw_cmds - MEGASAS_INT_CMDS;
+
+		spin_unlock_irqrestore(instance->host->host_lock, flags);
+	}
+}
+
+/**
+ * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
+ * @instance_addr:			Address of adapter soft state
+ *
+ * Tasklet to complete cmds
+ */
+static void megasas_complete_cmd_dpc(unsigned long instance_addr)
+{
+	u32 producer;
+	u32 consumer;
+	u32 context;
+	struct megasas_cmd *cmd;
+	struct megasas_instance *instance =
+				(struct megasas_instance *)instance_addr;
+	unsigned long flags;
+
+	/* If we have already declared adapter dead, donot complete cmds */
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
+		return;
+
+	spin_lock_irqsave(&instance->completion_lock, flags);
+
+	producer = *instance->producer;
+	consumer = *instance->consumer;
+
+	while (consumer != producer) {
+		context = instance->reply_queue[consumer];
+		if (context >= instance->max_fw_cmds) {
+			printk(KERN_ERR "Unexpected context value %x\n",
+				context);
+			BUG();
+		}
+
+		cmd = instance->cmd_list[context];
+
+		megasas_complete_cmd(instance, cmd, DID_OK);
+
+		consumer++;
+		if (consumer == (instance->max_fw_cmds + 1)) {
+			consumer = 0;
+		}
+	}
+
+	*instance->consumer = producer;
+
+	spin_unlock_irqrestore(&instance->completion_lock, flags);
+
+	/*
+	 * Check if we can restore can_queue
+	 */
+	megasas_check_and_restore_queue_depth(instance);
+}
+
+static void
+megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
+
+static void
+process_fw_state_change_wq(struct work_struct *work);
+
+void megasas_do_ocr(struct megasas_instance *instance)
+{
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
+	(instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
+	(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
+		*instance->consumer     = MEGASAS_ADPRESET_INPROG_SIGN;
+	}
+	instance->instancet->disable_intr(instance->reg_set);
+	instance->adprecovery   = MEGASAS_ADPRESET_SM_INFAULT;
+	instance->issuepend_done = 0;
+
+	atomic_set(&instance->fw_outstanding, 0);
+	megasas_internal_reset_defer_cmds(instance);
+	process_fw_state_change_wq(&instance->work_init);
+}
+
+/**
+ * megasas_wait_for_outstanding -	Wait for all outstanding cmds
+ * @instance:				Adapter soft state
+ *
+ * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
+ * complete all its outstanding commands. Returns error if one or more IOs
+ * are pending after this time period. It also marks the controller dead.
+ */
+static int megasas_wait_for_outstanding(struct megasas_instance *instance)
+{
+	int i;
+	u32 reset_index;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+	u8 adprecovery;
+	unsigned long flags;
+	struct list_head clist_local;
+	struct megasas_cmd *reset_cmd;
+	u32 fw_state;
+	u8 kill_adapter_flag;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	adprecovery = instance->adprecovery;
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+
+		INIT_LIST_HEAD(&clist_local);
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		list_splice_init(&instance->internal_reset_pending_q,
+				&clist_local);
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		printk(KERN_NOTICE "megasas: HBA reset wait ...\n");
+		for (i = 0; i < wait_time; i++) {
+			msleep(1000);
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			adprecovery = instance->adprecovery;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
+				break;
+		}
+
+		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+			printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			return FAILED;
+		}
+
+		reset_index	= 0;
+		while (!list_empty(&clist_local)) {
+			reset_cmd	= list_entry((&clist_local)->next,
+						struct megasas_cmd, list);
+			list_del_init(&reset_cmd->list);
+			if (reset_cmd->scmd) {
+				reset_cmd->scmd->result = DID_RESET << 16;
+				printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n",
+					reset_index, reset_cmd,
+					reset_cmd->scmd->cmnd[0],
+					reset_cmd->scmd->serial_number);
+
+				reset_cmd->scmd->scsi_done(reset_cmd->scmd);
+				megasas_return_cmd(instance, reset_cmd);
+			} else if (reset_cmd->sync_cmd) {
+				printk(KERN_NOTICE "megasas:%p synch cmds"
+						"reset queue\n",
+						reset_cmd);
+
+				reset_cmd->cmd_status = ENODATA;
+				instance->instancet->fire_cmd(instance,
+						reset_cmd->frame_phys_addr,
+						0, instance->reg_set);
+			} else {
+				printk(KERN_NOTICE "megasas: %p unexpected"
+					"cmds lst\n",
+					reset_cmd);
+			}
+			reset_index++;
+		}
+
+		return SUCCESS;
+	}
+
+	for (i = 0; i < wait_time; i++) {
+
+		int outstanding = atomic_read(&instance->fw_outstanding);
+
+		if (!outstanding)
+			break;
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
+			       "commands to complete\n",i,outstanding);
+			/*
+			 * Call cmd completion routine. Cmd to be
+			 * be completed directly without depending on isr.
+			 */
+			megasas_complete_cmd_dpc((unsigned long)instance);
+		}
+
+		msleep(1000);
+	}
+
+	i = 0;
+	kill_adapter_flag = 0;
+	do {
+		fw_state = instance->instancet->read_fw_status_reg(
+					instance->reg_set) & MFI_STATE_MASK;
+		if ((fw_state == MFI_STATE_FAULT) &&
+			(instance->disableOnlineCtrlReset == 0)) {
+			if (i == 3) {
+				kill_adapter_flag = 2;
+				break;
+			}
+			megasas_do_ocr(instance);
+			kill_adapter_flag = 1;
+
+			/* wait for 1 secs to let FW finish the pending cmds */
+			msleep(1000);
+		}
+		i++;
+	} while (i <= 3);
+
+	if (atomic_read(&instance->fw_outstanding) &&
+					!kill_adapter_flag) {
+		if (instance->disableOnlineCtrlReset == 0) {
+
+			megasas_do_ocr(instance);
+
+			/* wait for 5 secs to let FW finish the pending cmds */
+			for (i = 0; i < wait_time; i++) {
+				int outstanding =
+					atomic_read(&instance->fw_outstanding);
+				if (!outstanding)
+					return SUCCESS;
+				msleep(1000);
+			}
+		}
+	}
+
+	if (atomic_read(&instance->fw_outstanding) ||
+					(kill_adapter_flag == 2)) {
+		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
+		/*
+		* Send signal to FW to stop processing any pending cmds.
+		* The controller will be taken offline by the OS now.
+		*/
+		if ((instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+			(instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+			writel(MFI_STOP_ADP,
+				&instance->reg_set->doorbell);
+		} else {
+			writel(MFI_STOP_ADP,
+				&instance->reg_set->inbound_doorbell);
+		}
+		megasas_dump_pending_frames(instance);
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		return FAILED;
+	}
+
+	printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
+
+	return SUCCESS;
+}
+
+/**
+ * megasas_generic_reset -	Generic reset routine
+ * @scmd:			Mid-layer SCSI command
+ *
+ * This routine implements a generic reset handler for device, bus and host
+ * reset requests. Device, bus and host specific reset handlers can use this
+ * function after they do their specific tasks.
+ */
+static int megasas_generic_reset(struct scsi_cmnd *scmd)
+{
+	int ret_val;
+	struct megasas_instance *instance;
+
+	instance = (struct megasas_instance *)scmd->device->host->hostdata;
+
+	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
+		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		printk(KERN_ERR "megasas: cannot recover from previous reset "
+		       "failures\n");
+		return FAILED;
+	}
+
+	ret_val = megasas_wait_for_outstanding(instance);
+	if (ret_val == SUCCESS)
+		printk(KERN_NOTICE "megasas: reset successful \n");
+	else
+		printk(KERN_ERR "megasas: failed to do reset\n");
+
+	return ret_val;
+}
+
+/**
+ * megasas_reset_timer - quiesce the adapter if required
+ * @scmd:		scsi cmnd
+ *
+ * Sets the FW busy flag and reduces the host->can_queue if the
+ * cmd has not been completed within the timeout period.
+ */
+static enum
+blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+{
+	struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
+	struct megasas_instance *instance;
+	unsigned long flags;
+
+	if (time_after(jiffies, scmd->jiffies_at_alloc +
+				(MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
+		return BLK_EH_NOT_HANDLED;
+	}
+
+	instance = cmd->instance;
+	if (!(instance->flag & MEGASAS_FW_BUSY)) {
+		/* FW is busy, throttle IO */
+		spin_lock_irqsave(instance->host->host_lock, flags);
+
+		instance->host->can_queue = 16;
+		instance->last_time = jiffies;
+		instance->flag |= MEGASAS_FW_BUSY;
+
+		spin_unlock_irqrestore(instance->host->host_lock, flags);
+	}
+	return BLK_EH_RESET_TIMER;
+}
+
+/**
+ * megasas_reset_device -	Device reset handler entry point
+ */
+static int megasas_reset_device(struct scsi_cmnd *scmd)
+{
+	int ret;
+
+	/*
+	 * First wait for all commands to complete
+	 */
+	ret = megasas_generic_reset(scmd);
+
+	return ret;
+}
+
+/**
+ * megasas_reset_bus_host -	Bus & host reset handler entry point
+ */
+static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
+{
+	int ret;
+	struct megasas_instance *instance;
+	instance = (struct megasas_instance *)scmd->device->host->hostdata;
+
+	/*
+	 * First wait for all commands to complete
+	 */
+	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+		ret = megasas_reset_fusion(scmd->device->host);
+	else
+		ret = megasas_generic_reset(scmd);
+
+	return ret;
+}
+
+/**
+ * megasas_bios_param - Returns disk geometry for a disk
+ * @sdev: 		device handle
+ * @bdev:		block device
+ * @capacity:		drive capacity
+ * @geom:		geometry parameters
+ */
+static int
+megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+		 sector_t capacity, int geom[])
+{
+	int heads;
+	int sectors;
+	sector_t cylinders;
+	unsigned long tmp;
+	/* Default heads (64) & sectors (32) */
+	heads = 64;
+	sectors = 32;
+
+	tmp = heads * sectors;
+	cylinders = capacity;
+
+	sector_div(cylinders, tmp);
+
+	/*
+	 * Handle extended translation size for logical drives > 1Gb
+	 */
+
+	if (capacity >= 0x200000) {
+		heads = 255;
+		sectors = 63;
+		tmp = heads*sectors;
+		cylinders = capacity;
+		sector_div(cylinders, tmp);
+	}
+
+	geom[0] = heads;
+	geom[1] = sectors;
+	geom[2] = cylinders;
+
+	return 0;
+}
+
+static void megasas_aen_polling(struct work_struct *work);
+
+/**
+ * megasas_service_aen -	Processes an event notification
+ * @instance:			Adapter soft state
+ * @cmd:			AEN command completed by the ISR
+ *
+ * For AEN, driver sends a command down to FW that is held by the FW till an
+ * event occurs. When an event of interest occurs, FW completes the command
+ * that it was previously holding.
+ *
+ * This routines sends SIGIO signal to processes that have registered with the
+ * driver for AEN.
+ */
+static void
+megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+	unsigned long flags;
+	/*
+	 * Don't signal app if it is just an aborted previously registered aen
+	 */
+	if ((!cmd->abort_aen) && (instance->unload == 0)) {
+		spin_lock_irqsave(&poll_aen_lock, flags);
+		megasas_poll_wait_aen = 1;
+		spin_unlock_irqrestore(&poll_aen_lock, flags);
+		wake_up(&megasas_poll_wait);
+		kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
+	}
+	else
+		cmd->abort_aen = 0;
+
+	instance->aen_cmd = NULL;
+	megasas_return_cmd(instance, cmd);
+
+	if ((instance->unload == 0) &&
+		((instance->issuepend_done == 1))) {
+		struct megasas_aen_event *ev;
+		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+		if (!ev) {
+			printk(KERN_ERR "megasas_service_aen: out of memory\n");
+		} else {
+			ev->instance = instance;
+			instance->ev = ev;
+			INIT_WORK(&ev->hotplug_work, megasas_aen_polling);
+			schedule_delayed_work(
+				(struct delayed_work *)&ev->hotplug_work, 0);
+		}
+	}
+}
+
+/*
+ * Scsi host template for megaraid_sas driver
+ */
+static struct scsi_host_template megasas_template = {
+
+	.module = THIS_MODULE,
+	.name = "LSI SAS based MegaRAID driver",
+	.proc_name = "megaraid_sas",
+	.slave_configure = megasas_slave_configure,
+	.slave_alloc = megasas_slave_alloc,
+	.queuecommand = megasas_queue_command,
+	.eh_device_reset_handler = megasas_reset_device,
+	.eh_bus_reset_handler = megasas_reset_bus_host,
+	.eh_host_reset_handler = megasas_reset_bus_host,
+	.eh_timed_out = megasas_reset_timer,
+	.bios_param = megasas_bios_param,
+	.use_clustering = ENABLE_CLUSTERING,
+};
+
+/**
+ * megasas_complete_int_cmd -	Completes an internal command
+ * @instance:			Adapter soft state
+ * @cmd:			Command to be completed
+ *
+ * The megasas_issue_blocked_cmd() function waits for a command to complete
+ * after it issues a command. This function wakes up that waiting routine by
+ * calling wake_up() on the wait queue.
+ */
+static void
+megasas_complete_int_cmd(struct megasas_instance *instance,
+			 struct megasas_cmd *cmd)
+{
+	cmd->cmd_status = cmd->frame->io.cmd_status;
+
+	if (cmd->cmd_status == ENODATA) {
+		cmd->cmd_status = 0;
+	}
+	wake_up(&instance->int_cmd_wait_q);
+}
+
+/**
+ * megasas_complete_abort -	Completes aborting a command
+ * @instance:			Adapter soft state
+ * @cmd:			Cmd that was issued to abort another cmd
+ *
+ * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q
+ * after it issues an abort on a previously issued command. This function
+ * wakes up all functions waiting on the same wait queue.
+ */
+static void
+megasas_complete_abort(struct megasas_instance *instance,
+		       struct megasas_cmd *cmd)
+{
+	if (cmd->sync_cmd) {
+		cmd->sync_cmd = 0;
+		cmd->cmd_status = 0;
+		wake_up(&instance->abort_cmd_wait_q);
+	}
+
+	return;
+}
+
+/**
+ * megasas_complete_cmd -	Completes a command
+ * @instance:			Adapter soft state
+ * @cmd:			Command to be completed
+ * @alt_status:			If non-zero, use this value as status to
+ * 				SCSI mid-layer instead of the value returned
+ * 				by the FW. This should be used if caller wants
+ * 				an alternate status (as in the case of aborted
+ * 				commands)
+ */
+void
+megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
+		     u8 alt_status)
+{
+	int exception = 0;
+	struct megasas_header *hdr = &cmd->frame->hdr;
+	unsigned long flags;
+	struct fusion_context *fusion = instance->ctrl_context;
+
+	/* flag for the retry reset */
+	cmd->retry_for_fw_reset = 0;
+
+	if (cmd->scmd)
+		cmd->scmd->SCp.ptr = NULL;
+
+	switch (hdr->cmd) {
+
+	case MFI_CMD_PD_SCSI_IO:
+	case MFI_CMD_LD_SCSI_IO:
+
+		/*
+		 * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been
+		 * issued either through an IO path or an IOCTL path. If it
+		 * was via IOCTL, we will send it to internal completion.
+		 */
+		if (cmd->sync_cmd) {
+			cmd->sync_cmd = 0;
+			megasas_complete_int_cmd(instance, cmd);
+			break;
+		}
+
+	case MFI_CMD_LD_READ:
+	case MFI_CMD_LD_WRITE:
+
+		if (alt_status) {
+			cmd->scmd->result = alt_status << 16;
+			exception = 1;
+		}
+
+		if (exception) {
+
+			atomic_dec(&instance->fw_outstanding);
+
+			scsi_dma_unmap(cmd->scmd);
+			cmd->scmd->scsi_done(cmd->scmd);
+			megasas_return_cmd(instance, cmd);
+
+			break;
+		}
+
+		switch (hdr->cmd_status) {
+
+		case MFI_STAT_OK:
+			cmd->scmd->result = DID_OK << 16;
+			break;
+
+		case MFI_STAT_SCSI_IO_FAILED:
+		case MFI_STAT_LD_INIT_IN_PROGRESS:
+			cmd->scmd->result =
+			    (DID_ERROR << 16) | hdr->scsi_status;
+			break;
+
+		case MFI_STAT_SCSI_DONE_WITH_ERROR:
+
+			cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status;
+
+			if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) {
+				memset(cmd->scmd->sense_buffer, 0,
+				       SCSI_SENSE_BUFFERSIZE);
+				memcpy(cmd->scmd->sense_buffer, cmd->sense,
+				       hdr->sense_len);
+
+				cmd->scmd->result |= DRIVER_SENSE << 24;
+			}
+
+			break;
+
+		case MFI_STAT_LD_OFFLINE:
+		case MFI_STAT_DEVICE_NOT_FOUND:
+			cmd->scmd->result = DID_BAD_TARGET << 16;
+			break;
+
+		default:
+			printk(KERN_DEBUG "megasas: MFI FW status %#x\n",
+			       hdr->cmd_status);
+			cmd->scmd->result = DID_ERROR << 16;
+			break;
+		}
+
+		atomic_dec(&instance->fw_outstanding);
+
+		scsi_dma_unmap(cmd->scmd);
+		cmd->scmd->scsi_done(cmd->scmd);
+		megasas_return_cmd(instance, cmd);
+
+		break;
+
+	case MFI_CMD_SMP:
+	case MFI_CMD_STP:
+	case MFI_CMD_DCMD:
+		/* Check for LD map update */
+		if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) &&
+		    (cmd->frame->dcmd.mbox.b[1] == 1)) {
+			spin_lock_irqsave(instance->host->host_lock, flags);
+			if (cmd->frame->hdr.cmd_status != 0) {
+				if (cmd->frame->hdr.cmd_status !=
+				    MFI_STAT_NOT_FOUND)
+					printk(KERN_WARNING "megasas: map sync"
+					       "failed, status = 0x%x.\n",
+					       cmd->frame->hdr.cmd_status);
+				else {
+					megasas_return_cmd(instance, cmd);
+					spin_unlock_irqrestore(
+						instance->host->host_lock,
+						flags);
+					break;
+				}
+			} else
+				instance->map_id++;
+			megasas_return_cmd(instance, cmd);
+			if (MR_ValidateMapInfo(
+				    fusion->ld_map[(instance->map_id & 1)],
+				    fusion->load_balance_info))
+				fusion->fast_path_io = 1;
+			else
+				fusion->fast_path_io = 0;
+			megasas_sync_map_info(instance);
+			spin_unlock_irqrestore(instance->host->host_lock,
+					       flags);
+			break;
+		}
+		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
+			cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
+			spin_lock_irqsave(&poll_aen_lock, flags);
+			megasas_poll_wait_aen = 0;
+			spin_unlock_irqrestore(&poll_aen_lock, flags);
+		}
+
+		/*
+		 * See if got an event notification
+		 */
+		if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT)
+			megasas_service_aen(instance, cmd);
+		else
+			megasas_complete_int_cmd(instance, cmd);
+
+		break;
+
+	case MFI_CMD_ABORT:
+		/*
+		 * Cmd issued to abort another cmd returned
+		 */
+		megasas_complete_abort(instance, cmd);
+		break;
+
+	default:
+		printk("megasas: Unknown command completed! [0x%X]\n",
+		       hdr->cmd);
+		break;
+	}
+}
+
+/**
+ * megasas_issue_pending_cmds_again -	issue all pending cmds
+ *                              	in FW again because of the fw reset
+ * @instance:				Adapter soft state
+ */
+static inline void
+megasas_issue_pending_cmds_again(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	struct list_head clist_local;
+	union megasas_evt_class_locale class_locale;
+	unsigned long flags;
+	u32 seq_num;
+
+	INIT_LIST_HEAD(&clist_local);
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	list_splice_init(&instance->internal_reset_pending_q, &clist_local);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	while (!list_empty(&clist_local)) {
+		cmd	= list_entry((&clist_local)->next,
+					struct megasas_cmd, list);
+		list_del_init(&cmd->list);
+
+		if (cmd->sync_cmd || cmd->scmd) {
+			printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d"
+				"detected to be pending while HBA reset.\n",
+					cmd, cmd->scmd, cmd->sync_cmd);
+
+			cmd->retry_for_fw_reset++;
+
+			if (cmd->retry_for_fw_reset == 3) {
+				printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
+					"was tried multiple times during reset."
+					"Shutting down the HBA\n",
+					cmd, cmd->scmd, cmd->sync_cmd);
+				megaraid_sas_kill_hba(instance);
+
+				instance->adprecovery =
+						MEGASAS_HW_CRITICAL_ERROR;
+				return;
+			}
+		}
+
+		if (cmd->sync_cmd == 1) {
+			if (cmd->scmd) {
+				printk(KERN_NOTICE "megaraid_sas: unexpected"
+					"cmd attached to internal command!\n");
+			}
+			printk(KERN_NOTICE "megasas: %p synchronous cmd"
+						"on the internal reset queue,"
+						"issue it again.\n", cmd);
+			cmd->cmd_status = ENODATA;
+			instance->instancet->fire_cmd(instance,
+							cmd->frame_phys_addr ,
+							0, instance->reg_set);
+		} else if (cmd->scmd) {
+			printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
+			"detected on the internal queue, issue again.\n",
+			cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
+
+			atomic_inc(&instance->fw_outstanding);
+			instance->instancet->fire_cmd(instance,
+					cmd->frame_phys_addr,
+					cmd->frame_count-1, instance->reg_set);
+		} else {
+			printk(KERN_NOTICE "megasas: %p unexpected cmd on the"
+				"internal reset defer list while re-issue!!\n",
+				cmd);
+		}
+	}
+
+	if (instance->aen_cmd) {
+		printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n");
+		megasas_return_cmd(instance, instance->aen_cmd);
+
+		instance->aen_cmd	= NULL;
+	}
+
+	/*
+	* Initiate AEN (Asynchronous Event Notification)
+	*/
+	seq_num = instance->last_seq_num;
+	class_locale.members.reserved = 0;
+	class_locale.members.locale = MR_EVT_LOCALE_ALL;
+	class_locale.members.class = MR_EVT_CLASS_DEBUG;
+
+	megasas_register_aen(instance, seq_num, class_locale.word);
+}
+
+/**
+ * Move the internal reset pending commands to a deferred queue.
+ *
+ * We move the commands pending at internal reset time to a
+ * pending queue. This queue would be flushed after successful
+ * completion of the internal reset sequence. if the internal reset
+ * did not complete in time, the kernel reset handler would flush
+ * these commands.
+ **/
+static void
+megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	int i;
+	u32 max_cmd = instance->max_fw_cmds;
+	u32 defer_index;
+	unsigned long flags;
+
+	defer_index     = 0;
+	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+	for (i = 0; i < max_cmd; i++) {
+		cmd = instance->cmd_list[i];
+		if (cmd->sync_cmd == 1 || cmd->scmd) {
+			printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
+					"on the defer queue as internal\n",
+				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
+
+			if (!list_empty(&cmd->list)) {
+				printk(KERN_NOTICE "megaraid_sas: ERROR while"
+					" moving this cmd:%p, %d %p, it was"
+					"discovered on some list?\n",
+					cmd, cmd->sync_cmd, cmd->scmd);
+
+				list_del_init(&cmd->list);
+			}
+			defer_index++;
+			list_add_tail(&cmd->list,
+				&instance->internal_reset_pending_q);
+		}
+	}
+	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+}
+
+
+static void
+process_fw_state_change_wq(struct work_struct *work)
+{
+	struct megasas_instance *instance =
+		container_of(work, struct megasas_instance, work_init);
+	u32 wait;
+	unsigned long flags;
+
+	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
+		printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
+				instance->adprecovery);
+		return ;
+	}
+
+	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
+		printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
+					"state, restarting it...\n");
+
+		instance->instancet->disable_intr(instance->reg_set);
+		atomic_set(&instance->fw_outstanding, 0);
+
+		atomic_set(&instance->fw_reset_no_pci_access, 1);
+		instance->instancet->adp_reset(instance, instance->reg_set);
+		atomic_set(&instance->fw_reset_no_pci_access, 0 );
+
+		printk(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
+					"initiating next stage...\n");
+
+		printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine,"
+					"state 2 starting...\n");
+
+		/*waitting for about 20 second before start the second init*/
+		for (wait = 0; wait < 30; wait++) {
+			msleep(1000);
+		}
+
+		if (megasas_transition_to_ready(instance)) {
+			printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
+
+			megaraid_sas_kill_hba(instance);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+			return ;
+		}
+
+		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
+			(instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
+			(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)
+			) {
+			*instance->consumer = *instance->producer;
+		} else {
+			*instance->consumer = 0;
+			*instance->producer = 0;
+		}
+
+		megasas_issue_init_mfi(instance);
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HBA_OPERATIONAL;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		instance->instancet->enable_intr(instance->reg_set);
+
+		megasas_issue_pending_cmds_again(instance);
+		instance->issuepend_done = 1;
+	}
+	return ;
+}
+
+/**
+ * megasas_deplete_reply_queue -	Processes all completed commands
+ * @instance:				Adapter soft state
+ * @alt_status:				Alternate status to be returned to
+ * 					SCSI mid-layer instead of the status
+ * 					returned by the FW
+ * Note: this must be called with hba lock held
+ */
+static int
+megasas_deplete_reply_queue(struct megasas_instance *instance,
+					u8 alt_status)
+{
+	u32 mfiStatus;
+	u32 fw_state;
+
+	if ((mfiStatus = instance->instancet->check_reset(instance,
+					instance->reg_set)) == 1) {
+		return IRQ_HANDLED;
+	}
+
+	if ((mfiStatus = instance->instancet->clear_intr(
+						instance->reg_set)
+						) == 0) {
+		return IRQ_NONE;
+	}
+
+	instance->mfiStatus = mfiStatus;
+
+	if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
+		fw_state = instance->instancet->read_fw_status_reg(
+				instance->reg_set) & MFI_STATE_MASK;
+
+		if (fw_state != MFI_STATE_FAULT) {
+			printk(KERN_NOTICE "megaraid_sas: fw state:%x\n",
+						fw_state);
+		}
+
+		if ((fw_state == MFI_STATE_FAULT) &&
+				(instance->disableOnlineCtrlReset == 0)) {
+			printk(KERN_NOTICE "megaraid_sas: wait adp restart\n");
+
+			if ((instance->pdev->device ==
+					PCI_DEVICE_ID_LSI_SAS1064R) ||
+				(instance->pdev->device ==
+					PCI_DEVICE_ID_DELL_PERC5) ||
+				(instance->pdev->device ==
+					PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
+
+				*instance->consumer =
+					MEGASAS_ADPRESET_INPROG_SIGN;
+			}
+
+
+			instance->instancet->disable_intr(instance->reg_set);
+			instance->adprecovery	= MEGASAS_ADPRESET_SM_INFAULT;
+			instance->issuepend_done = 0;
+
+			atomic_set(&instance->fw_outstanding, 0);
+			megasas_internal_reset_defer_cmds(instance);
+
+			printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
+					fw_state, instance->adprecovery);
+
+			schedule_work(&instance->work_init);
+			return IRQ_HANDLED;
+
+		} else {
+			printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
+				fw_state, instance->disableOnlineCtrlReset);
+		}
+	}
+
+	tasklet_schedule(&instance->isr_tasklet);
+	return IRQ_HANDLED;
+}
+/**
+ * megasas_isr - isr entry point
+ */
+static irqreturn_t megasas_isr(int irq, void *devp)
+{
+	struct megasas_instance *instance;
+	unsigned long flags;
+	irqreturn_t	rc;
+
+	if (atomic_read(
+		&(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
+		return IRQ_HANDLED;
+
+	instance = (struct megasas_instance *)devp;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	rc =  megasas_deplete_reply_queue(instance, DID_OK);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	return rc;
+}
+
+/**
+ * megasas_transition_to_ready -	Move the FW to READY state
+ * @instance:				Adapter soft state
+ *
+ * During the initialization, FW passes can potentially be in any one of
+ * several possible states. If the FW in operational, waiting-for-handshake
+ * states, driver must take steps to bring it to ready state. Otherwise, it
+ * has to wait for the ready state.
+ */
+int
+megasas_transition_to_ready(struct megasas_instance* instance)
+{
+	int i;
+	u8 max_wait;
+	u32 fw_state;
+	u32 cur_state;
+	u32 abs_state, curr_abs_state;
+
+	fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+
+	if (fw_state != MFI_STATE_READY)
+		printk(KERN_INFO "megasas: Waiting for FW to come to ready"
+		       " state\n");
+
+	while (fw_state != MFI_STATE_READY) {
+
+		abs_state =
+		instance->instancet->read_fw_status_reg(instance->reg_set);
+
+		switch (fw_state) {
+
+		case MFI_STATE_FAULT:
+
+			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
+			return -ENODEV;
+
+		case MFI_STATE_WAIT_HANDSHAKE:
+			/*
+			 * Set the CLR bit in inbound doorbell
+			 */
+			if ((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+				(instance->pdev->device ==
+				 PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+				(instance->pdev->device ==
+				 PCI_DEVICE_ID_LSI_FUSION)) {
+				writel(
+				  MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+				  &instance->reg_set->doorbell);
+			} else {
+				writel(
+				    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+					&instance->reg_set->inbound_doorbell);
+			}
+
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_WAIT_HANDSHAKE;
+			break;
+
+		case MFI_STATE_BOOT_MESSAGE_PENDING:
+			if ((instance->pdev->device ==
+			     PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+				(instance->pdev->device ==
+				 PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+			    (instance->pdev->device ==
+			     PCI_DEVICE_ID_LSI_FUSION)) {
+				writel(MFI_INIT_HOTPLUG,
+				       &instance->reg_set->doorbell);
+			} else
+				writel(MFI_INIT_HOTPLUG,
+					&instance->reg_set->inbound_doorbell);
+
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
+			break;
+
+		case MFI_STATE_OPERATIONAL:
+			/*
+			 * Bring it to READY state; assuming max wait 10 secs
+			 */
+			instance->instancet->disable_intr(instance->reg_set);
+			if ((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+				(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0071SKINNY)  ||
+				(instance->pdev->device
+					== PCI_DEVICE_ID_LSI_FUSION)) {
+				writel(MFI_RESET_FLAGS,
+					&instance->reg_set->doorbell);
+				if (instance->pdev->device ==
+				    PCI_DEVICE_ID_LSI_FUSION) {
+					for (i = 0; i < (10 * 1000); i += 20) {
+						if (readl(
+							    &instance->
+							    reg_set->
+							    doorbell) & 1)
+							msleep(20);
+						else
+							break;
+					}
+				}
+			} else
+				writel(MFI_RESET_FLAGS,
+					&instance->reg_set->inbound_doorbell);
+
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_OPERATIONAL;
+			break;
+
+		case MFI_STATE_UNDEFINED:
+			/*
+			 * This state should not last for more than 2 seconds
+			 */
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_UNDEFINED;
+			break;
+
+		case MFI_STATE_BB_INIT:
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_BB_INIT;
+			break;
+
+		case MFI_STATE_FW_INIT:
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_FW_INIT;
+			break;
+
+		case MFI_STATE_FW_INIT_2:
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_FW_INIT_2;
+			break;
+
+		case MFI_STATE_DEVICE_SCAN:
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_DEVICE_SCAN;
+			break;
+
+		case MFI_STATE_FLUSH_CACHE:
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_FLUSH_CACHE;
+			break;
+
+		default:
+			printk(KERN_DEBUG "megasas: Unknown state 0x%x\n",
+			       fw_state);
+			return -ENODEV;
+		}
+
+		/*
+		 * The cur_state should not last for more than max_wait secs
+		 */
+		for (i = 0; i < (max_wait * 1000); i++) {
+			fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &
+					MFI_STATE_MASK ;
+		curr_abs_state =
+		instance->instancet->read_fw_status_reg(instance->reg_set);
+
+			if (abs_state == curr_abs_state) {
+				msleep(1);
+			} else
+				break;
+		}
+
+		/*
+		 * Return error if fw_state hasn't changed after max_wait
+		 */
+		if (curr_abs_state == abs_state) {
+			printk(KERN_DEBUG "FW state [%d] hasn't changed "
+			       "in %d secs\n", fw_state, max_wait);
+			return -ENODEV;
+		}
+	}
+	printk(KERN_INFO "megasas: FW now in Ready state\n");
+
+	return 0;
+}
+
+/**
+ * megasas_teardown_frame_pool -	Destroy the cmd frame DMA pool
+ * @instance:				Adapter soft state
+ */
+static void megasas_teardown_frame_pool(struct megasas_instance *instance)
+{
+	int i;
+	u32 max_cmd = instance->max_mfi_cmds;
+	struct megasas_cmd *cmd;
+
+	if (!instance->frame_dma_pool)
+		return;
+
+	/*
+	 * Return all frames to pool
+	 */
+	for (i = 0; i < max_cmd; i++) {
+
+		cmd = instance->cmd_list[i];
+
+		if (cmd->frame)
+			pci_pool_free(instance->frame_dma_pool, cmd->frame,
+				      cmd->frame_phys_addr);
+
+		if (cmd->sense)
+			pci_pool_free(instance->sense_dma_pool, cmd->sense,
+				      cmd->sense_phys_addr);
+	}
+
+	/*
+	 * Now destroy the pool itself
+	 */
+	pci_pool_destroy(instance->frame_dma_pool);
+	pci_pool_destroy(instance->sense_dma_pool);
+
+	instance->frame_dma_pool = NULL;
+	instance->sense_dma_pool = NULL;
+}
+
+/**
+ * megasas_create_frame_pool -	Creates DMA pool for cmd frames
+ * @instance:			Adapter soft state
+ *
+ * Each command packet has an embedded DMA memory buffer that is used for
+ * filling MFI frame and the SG list that immediately follows the frame. This
+ * function creates those DMA memory buffers for each command packet by using
+ * PCI pool facility.
+ */
+static int megasas_create_frame_pool(struct megasas_instance *instance)
+{
+	int i;
+	u32 max_cmd;
+	u32 sge_sz;
+	u32 sgl_sz;
+	u32 total_sz;
+	u32 frame_count;
+	struct megasas_cmd *cmd;
+
+	max_cmd = instance->max_mfi_cmds;
+
+	/*
+	 * Size of our frame is 64 bytes for MFI frame, followed by max SG
+	 * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer
+	 */
+	sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
+	    sizeof(struct megasas_sge32);
+
+	if (instance->flag_ieee) {
+		sge_sz = sizeof(struct megasas_sge_skinny);
+	}
+
+	/*
+	 * Calculated the number of 64byte frames required for SGL
+	 */
+	sgl_sz = sge_sz * instance->max_num_sge;
+	frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
+	frame_count = 15;
+
+	/*
+	 * We need one extra frame for the MFI command
+	 */
+	frame_count++;
+
+	total_sz = MEGAMFI_FRAME_SIZE * frame_count;
+	/*
+	 * Use DMA pool facility provided by PCI layer
+	 */
+	instance->frame_dma_pool = pci_pool_create("megasas frame pool",
+						   instance->pdev, total_sz, 64,
+						   0);
+
+	if (!instance->frame_dma_pool) {
+		printk(KERN_DEBUG "megasas: failed to setup frame pool\n");
+		return -ENOMEM;
+	}
+
+	instance->sense_dma_pool = pci_pool_create("megasas sense pool",
+						   instance->pdev, 128, 4, 0);
+
+	if (!instance->sense_dma_pool) {
+		printk(KERN_DEBUG "megasas: failed to setup sense pool\n");
+
+		pci_pool_destroy(instance->frame_dma_pool);
+		instance->frame_dma_pool = NULL;
+
+		return -ENOMEM;
+	}
+
+	/*
+	 * Allocate and attach a frame to each of the commands in cmd_list.
+	 * By making cmd->index as the context instead of the &cmd, we can
+	 * always use 32bit context regardless of the architecture
+	 */
+	for (i = 0; i < max_cmd; i++) {
+
+		cmd = instance->cmd_list[i];
+
+		cmd->frame = pci_pool_alloc(instance->frame_dma_pool,
+					    GFP_KERNEL, &cmd->frame_phys_addr);
+
+		cmd->sense = pci_pool_alloc(instance->sense_dma_pool,
+					    GFP_KERNEL, &cmd->sense_phys_addr);
+
+		/*
+		 * megasas_teardown_frame_pool() takes care of freeing
+		 * whatever has been allocated
+		 */
+		if (!cmd->frame || !cmd->sense) {
+			printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n");
+			megasas_teardown_frame_pool(instance);
+			return -ENOMEM;
+		}
+
+		memset(cmd->frame, 0, total_sz);
+		cmd->frame->io.context = cmd->index;
+		cmd->frame->io.pad_0 = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * megasas_free_cmds -	Free all the cmds in the free cmd pool
+ * @instance:		Adapter soft state
+ */
+void megasas_free_cmds(struct megasas_instance *instance)
+{
+	int i;
+	/* First free the MFI frame pool */
+	megasas_teardown_frame_pool(instance);
+
+	/* Free all the commands in the cmd_list */
+	for (i = 0; i < instance->max_mfi_cmds; i++)
+
+		kfree(instance->cmd_list[i]);
+
+	/* Free the cmd_list buffer itself */
+	kfree(instance->cmd_list);
+	instance->cmd_list = NULL;
+
+	INIT_LIST_HEAD(&instance->cmd_pool);
+}
+
+/**
+ * megasas_alloc_cmds -	Allocates the command packets
+ * @instance:		Adapter soft state
+ *
+ * Each command that is issued to the FW, whether IO commands from the OS or
+ * internal commands like IOCTLs, are wrapped in local data structure called
+ * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to
+ * the FW.
+ *
+ * Each frame has a 32-bit field called context (tag). This context is used
+ * to get back the megasas_cmd from the frame when a frame gets completed in
+ * the ISR. Typically the address of the megasas_cmd itself would be used as
+ * the context. But we wanted to keep the differences between 32 and 64 bit
+ * systems to the mininum. We always use 32 bit integers for the context. In
+ * this driver, the 32 bit values are the indices into an array cmd_list.
+ * This array is used only to look up the megasas_cmd given the context. The
+ * free commands themselves are maintained in a linked list called cmd_pool.
+ */
+int megasas_alloc_cmds(struct megasas_instance *instance)
+{
+	int i;
+	int j;
+	u32 max_cmd;
+	struct megasas_cmd *cmd;
+
+	max_cmd = instance->max_mfi_cmds;
+
+	/*
+	 * instance->cmd_list is an array of struct megasas_cmd pointers.
+	 * Allocate the dynamic array first and then allocate individual
+	 * commands.
+	 */
+	instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL);
+
+	if (!instance->cmd_list) {
+		printk(KERN_DEBUG "megasas: out of memory\n");
+		return -ENOMEM;
+	}
+
+	memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) *max_cmd);
+
+	for (i = 0; i < max_cmd; i++) {
+		instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd),
+						GFP_KERNEL);
+
+		if (!instance->cmd_list[i]) {
+
+			for (j = 0; j < i; j++)
+				kfree(instance->cmd_list[j]);
+
+			kfree(instance->cmd_list);
+			instance->cmd_list = NULL;
+
+			return -ENOMEM;
+		}
+	}
+
+	/*
+	 * Add all the commands to command pool (instance->cmd_pool)
+	 */
+	for (i = 0; i < max_cmd; i++) {
+		cmd = instance->cmd_list[i];
+		memset(cmd, 0, sizeof(struct megasas_cmd));
+		cmd->index = i;
+		cmd->scmd = NULL;
+		cmd->instance = instance;
+
+		list_add_tail(&cmd->list, &instance->cmd_pool);
+	}
+
+	/*
+	 * Create a frame pool and assign one frame to each cmd
+	 */
+	if (megasas_create_frame_pool(instance)) {
+		printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
+		megasas_free_cmds(instance);
+	}
+
+	return 0;
+}
+
+/*
+ * megasas_get_pd_list_info -	Returns FW's pd_list structure
+ * @instance:				Adapter soft state
+ * @pd_list:				pd_list structure
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD
+ * list structure.  This information is mainly used to find out SYSTEM
+ * supported by the FW.
+ */
+static int
+megasas_get_pd_list(struct megasas_instance *instance)
+{
+	int ret = 0, pd_index = 0;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct MR_PD_LIST *ci;
+	struct MR_PD_ADDRESS *pd_addr;
+	dma_addr_t ci_h = 0;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
+		return -ENOMEM;
+	}
+
+	dcmd = &cmd->frame->dcmd;
+
+	ci = pci_alloc_consistent(instance->pdev,
+		  MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
+
+	if (!ci) {
+		printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(ci, 0, sizeof(*ci));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
+	dcmd->mbox.b[1] = 0;
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
+	dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
+	dcmd->sgl.sge32[0].phys_addr = ci_h;
+	dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
+
+	if (!megasas_issue_polled(instance, cmd)) {
+		ret = 0;
+	} else {
+		ret = -1;
+	}
+
+	/*
+	* the following function will get the instance PD LIST.
+	*/
+
+	pd_addr = ci->addr;
+
+	if ( ret == 0 &&
+		(ci->count <
+		  (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
+
+		memset(instance->pd_list, 0,
+			MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
+
+		for (pd_index = 0; pd_index < ci->count; pd_index++) {
+
+			instance->pd_list[pd_addr->deviceId].tid	=
+							pd_addr->deviceId;
+			instance->pd_list[pd_addr->deviceId].driveType	=
+							pd_addr->scsiDevType;
+			instance->pd_list[pd_addr->deviceId].driveState	=
+							MR_PD_STATE_SYSTEM;
+			pd_addr++;
+		}
+	}
+
+	pci_free_consistent(instance->pdev,
+				MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
+				ci, ci_h);
+	megasas_return_cmd(instance, cmd);
+
+	return ret;
+}
+
+/*
+ * megasas_get_ld_list_info -	Returns FW's ld_list structure
+ * @instance:				Adapter soft state
+ * @ld_list:				ld_list structure
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD
+ * list structure.  This information is mainly used to find out SYSTEM
+ * supported by the FW.
+ */
+static int
+megasas_get_ld_list(struct megasas_instance *instance)
+{
+	int ret = 0, ld_index = 0, ids = 0;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct MR_LD_LIST *ci;
+	dma_addr_t ci_h = 0;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n");
+		return -ENOMEM;
+	}
+
+	dcmd = &cmd->frame->dcmd;
+
+	ci = pci_alloc_consistent(instance->pdev,
+				sizeof(struct MR_LD_LIST),
+				&ci_h);
+
+	if (!ci) {
+		printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n");
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(ci, 0, sizeof(*ci));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->data_xfer_len = sizeof(struct MR_LD_LIST);
+	dcmd->opcode = MR_DCMD_LD_GET_LIST;
+	dcmd->sgl.sge32[0].phys_addr = ci_h;
+	dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
+	dcmd->pad_0  = 0;
+
+	if (!megasas_issue_polled(instance, cmd)) {
+		ret = 0;
+	} else {
+		ret = -1;
+	}
+
+	/* the following function will get the instance PD LIST */
+
+	if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) {
+		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
+
+		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
+			if (ci->ldList[ld_index].state != 0) {
+				ids = ci->ldList[ld_index].ref.targetId;
+				instance->ld_ids[ids] =
+					ci->ldList[ld_index].ref.targetId;
+			}
+		}
+	}
+
+	pci_free_consistent(instance->pdev,
+				sizeof(struct MR_LD_LIST),
+				ci,
+				ci_h);
+
+	megasas_return_cmd(instance, cmd);
+	return ret;
+}
+
+/**
+ * megasas_get_controller_info -	Returns FW's controller structure
+ * @instance:				Adapter soft state
+ * @ctrl_info:				Controller information structure
+ *
+ * Issues an internal command (DCMD) to get the FW's controller structure.
+ * This information is mainly used to find out the maximum IO transfer per
+ * command supported by the FW.
+ */
+static int
+megasas_get_ctrl_info(struct megasas_instance *instance,
+		      struct megasas_ctrl_info *ctrl_info)
+{
+	int ret = 0;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct megasas_ctrl_info *ci;
+	dma_addr_t ci_h = 0;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas: Failed to get a free cmd\n");
+		return -ENOMEM;
+	}
+
+	dcmd = &cmd->frame->dcmd;
+
+	ci = pci_alloc_consistent(instance->pdev,
+				  sizeof(struct megasas_ctrl_info), &ci_h);
+
+	if (!ci) {
+		printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n");
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(ci, 0, sizeof(*ci));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);
+	dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
+	dcmd->sgl.sge32[0].phys_addr = ci_h;
+	dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info);
+
+	if (!megasas_issue_polled(instance, cmd)) {
+		ret = 0;
+		memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
+	} else {
+		ret = -1;
+	}
+
+	pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
+			    ci, ci_h);
+
+	megasas_return_cmd(instance, cmd);
+	return ret;
+}
+
+/**
+ * megasas_issue_init_mfi -	Initializes the FW
+ * @instance:		Adapter soft state
+ *
+ * Issues the INIT MFI cmd
+ */
+static int
+megasas_issue_init_mfi(struct megasas_instance *instance)
+{
+	u32 context;
+
+	struct megasas_cmd *cmd;
+
+	struct megasas_init_frame *init_frame;
+	struct megasas_init_queue_info *initq_info;
+	dma_addr_t init_frame_h;
+	dma_addr_t initq_info_h;
+
+	/*
+	 * Prepare a init frame. Note the init frame points to queue info
+	 * structure. Each frame has SGL allocated after first 64 bytes. For
+	 * this frame - since we don't need any SGL - we use SGL's space as
+	 * queue info structure
+	 *
+	 * We will not get a NULL command below. We just created the pool.
+	 */
+	cmd = megasas_get_cmd(instance);
+
+	init_frame = (struct megasas_init_frame *)cmd->frame;
+	initq_info = (struct megasas_init_queue_info *)
+		((unsigned long)init_frame + 64);
+
+	init_frame_h = cmd->frame_phys_addr;
+	initq_info_h = init_frame_h + 64;
+
+	context = init_frame->context;
+	memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
+	memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
+	init_frame->context = context;
+
+	initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
+	initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
+
+	initq_info->producer_index_phys_addr_lo = instance->producer_h;
+	initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
+
+	init_frame->cmd = MFI_CMD_INIT;
+	init_frame->cmd_status = 0xFF;
+	init_frame->queue_info_new_phys_addr_lo = initq_info_h;
+
+	init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
+
+	/*
+	 * disable the intr before firing the init frame to FW
+	 */
+	instance->instancet->disable_intr(instance->reg_set);
+
+	/*
+	 * Issue the init frame in polled mode
+	 */
+
+	if (megasas_issue_polled(instance, cmd)) {
+		printk(KERN_ERR "megasas: Failed to init firmware\n");
+		megasas_return_cmd(instance, cmd);
+		goto fail_fw_init;
+	}
+
+	megasas_return_cmd(instance, cmd);
+
+	return 0;
+
+fail_fw_init:
+	return -EINVAL;
+}
+
+/**
+ * megasas_start_timer - Initializes a timer object
+ * @instance:		Adapter soft state
+ * @timer:		timer object to be initialized
+ * @fn:			timer function
+ * @interval:		time interval between timer function call
+ */
+static inline void
+megasas_start_timer(struct megasas_instance *instance,
+			struct timer_list *timer,
+			void *fn, unsigned long interval)
+{
+	init_timer(timer);
+	timer->expires = jiffies + interval;
+	timer->data = (unsigned long)instance;
+	timer->function = fn;
+	add_timer(timer);
+}
+
+/**
+ * megasas_io_completion_timer - Timer fn
+ * @instance_addr:	Address of adapter soft state
+ *
+ * Schedules tasklet for cmd completion
+ * if poll_mode_io is set
+ */
+static void
+megasas_io_completion_timer(unsigned long instance_addr)
+{
+	struct megasas_instance *instance =
+			(struct megasas_instance *)instance_addr;
+
+	if (atomic_read(&instance->fw_outstanding))
+		tasklet_schedule(&instance->isr_tasklet);
+
+	/* Restart timer */
+	if (poll_mode_io)
+		mod_timer(&instance->io_completion_timer,
+			jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
+}
+
+static u32
+megasas_init_adapter_mfi(struct megasas_instance *instance)
+{
+	struct megasas_register_set __iomem *reg_set;
+	u32 context_sz;
+	u32 reply_q_sz;
+
+	reg_set = instance->reg_set;
+
+	/*
+	 * Get various operational parameters from status register
+	 */
+	instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
+	/*
+	 * Reduce the max supported cmds by 1. This is to ensure that the
+	 * reply_q_sz (1 more than the max cmd that driver may send)
+	 * does not exceed max cmds that the FW can support
+	 */
+	instance->max_fw_cmds = instance->max_fw_cmds-1;
+	instance->max_mfi_cmds = instance->max_fw_cmds;
+	instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >>
+					0x10;
+	/*
+	 * Create a pool of commands
+	 */
+	if (megasas_alloc_cmds(instance))
+		goto fail_alloc_cmds;
+
+	/*
+	 * Allocate memory for reply queue. Length of reply queue should
+	 * be _one_ more than the maximum commands handled by the firmware.
+	 *
+	 * Note: When FW completes commands, it places corresponding contex
+	 * values in this circular reply queue. This circular queue is a fairly
+	 * typical producer-consumer queue. FW is the producer (of completed
+	 * commands) and the driver is the consumer.
+	 */
+	context_sz = sizeof(u32);
+	reply_q_sz = context_sz * (instance->max_fw_cmds + 1);
+
+	instance->reply_queue = pci_alloc_consistent(instance->pdev,
+						     reply_q_sz,
+						     &instance->reply_queue_h);
+
+	if (!instance->reply_queue) {
+		printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n");
+		goto fail_reply_queue;
+	}
+
+	if (megasas_issue_init_mfi(instance))
+		goto fail_fw_init;
+
+	instance->fw_support_ieee = 0;
+	instance->fw_support_ieee =
+		(instance->instancet->read_fw_status_reg(reg_set) &
+		0x04000000);
+
+	printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d",
+			instance->fw_support_ieee);
+
+	if (instance->fw_support_ieee)
+		instance->flag_ieee = 1;
+
+	return 0;
+
+fail_fw_init:
+
+	pci_free_consistent(instance->pdev, reply_q_sz,
+			    instance->reply_queue, instance->reply_queue_h);
+fail_reply_queue:
+	megasas_free_cmds(instance);
+
+fail_alloc_cmds:
+	iounmap(instance->reg_set);
+	return 1;
+}
+
+/**
+ * megasas_init_fw -	Initializes the FW
+ * @instance:		Adapter soft state
+ *
+ * This is the main function for initializing firmware
+ */
+
+static int megasas_init_fw(struct megasas_instance *instance)
+{
+	u32 max_sectors_1;
+	u32 max_sectors_2;
+	u32 tmp_sectors;
+	struct megasas_register_set __iomem *reg_set;
+	struct megasas_ctrl_info *ctrl_info;
+	unsigned long bar_list;
+
+	/* Find first memory bar */
+	bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
+	instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
+	instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
+	if (pci_request_selected_regions(instance->pdev, instance->bar,
+					 "megasas: LSI")) {
+		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+		return -EBUSY;
+	}
+
+	instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
+
+	if (!instance->reg_set) {
+		printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
+		goto fail_ioremap;
+	}
+
+	reg_set = instance->reg_set;
+
+	switch (instance->pdev->device) {
+	case PCI_DEVICE_ID_LSI_FUSION:
+		instance->instancet = &megasas_instance_template_fusion;
+		break;
+	case PCI_DEVICE_ID_LSI_SAS1078R:
+	case PCI_DEVICE_ID_LSI_SAS1078DE:
+		instance->instancet = &megasas_instance_template_ppc;
+		break;
+	case PCI_DEVICE_ID_LSI_SAS1078GEN2:
+	case PCI_DEVICE_ID_LSI_SAS0079GEN2:
+		instance->instancet = &megasas_instance_template_gen2;
+		break;
+	case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
+	case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
+		instance->instancet = &megasas_instance_template_skinny;
+		break;
+	case PCI_DEVICE_ID_LSI_SAS1064R:
+	case PCI_DEVICE_ID_DELL_PERC5:
+	default:
+		instance->instancet = &megasas_instance_template_xscale;
+		break;
+	}
+
+	/*
+	 * We expect the FW state to be READY
+	 */
+	if (megasas_transition_to_ready(instance))
+		goto fail_ready_state;
+
+	/* Get operational params, sge flags, send init cmd to controller */
+	if (instance->instancet->init_adapter(instance))
+		return -ENODEV;
+
+	printk(KERN_ERR "megasas: INIT adapter done\n");
+
+	/** for passthrough
+	* the following function will get the PD LIST.
+	*/
+
+	memset(instance->pd_list, 0 ,
+		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
+	megasas_get_pd_list(instance);
+
+	memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
+	megasas_get_ld_list(instance);
+
+	ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
+
+	/*
+	 * Compute the max allowed sectors per IO: The controller info has two
+	 * limits on max sectors. Driver should use the minimum of these two.
+	 *
+	 * 1 << stripe_sz_ops.min = max sectors per strip
+	 *
+	 * Note that older firmwares ( < FW ver 30) didn't report information
+	 * to calculate max_sectors_1. So the number ended up as zero always.
+	 */
+	tmp_sectors = 0;
+	if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
+
+		max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
+		    ctrl_info->max_strips_per_io;
+		max_sectors_2 = ctrl_info->max_request_size;
+
+		tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
+		instance->disableOnlineCtrlReset =
+		ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
+	}
+
+	instance->max_sectors_per_req = instance->max_num_sge *
+						PAGE_SIZE / 512;
+	if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
+		instance->max_sectors_per_req = tmp_sectors;
+
+	kfree(ctrl_info);
+
+        /*
+	* Setup tasklet for cmd completion
+	*/
+
+	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+		(unsigned long)instance);
+
+	/* Initialize the cmd completion timer */
+	if (poll_mode_io)
+		megasas_start_timer(instance, &instance->io_completion_timer,
+				megasas_io_completion_timer,
+				MEGASAS_COMPLETION_TIMER_INTERVAL);
+	return 0;
+
+fail_ready_state:
+	iounmap(instance->reg_set);
+
+      fail_ioremap:
+	pci_release_selected_regions(instance->pdev, instance->bar);
+
+	return -EINVAL;
+}
+
+/**
+ * megasas_release_mfi -	Reverses the FW initialization
+ * @intance:			Adapter soft state
+ */
+static void megasas_release_mfi(struct megasas_instance *instance)
+{
+	u32 reply_q_sz = sizeof(u32) *(instance->max_mfi_cmds + 1);
+
+	if (instance->reply_queue)
+		pci_free_consistent(instance->pdev, reply_q_sz,
+			    instance->reply_queue, instance->reply_queue_h);
+
+	megasas_free_cmds(instance);
+
+	iounmap(instance->reg_set);
+
+	pci_release_selected_regions(instance->pdev, instance->bar);
+}
+
+/**
+ * megasas_get_seq_num -	Gets latest event sequence numbers
+ * @instance:			Adapter soft state
+ * @eli:			FW event log sequence numbers information
+ *
+ * FW maintains a log of all events in a non-volatile area. Upper layers would
+ * usually find out the latest sequence number of the events, the seq number at
+ * the boot etc. They would "read" all the events below the latest seq number
+ * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq
+ * number), they would subsribe to AEN (asynchronous event notification) and
+ * wait for the events to happen.
+ */
+static int
+megasas_get_seq_num(struct megasas_instance *instance,
+		    struct megasas_evt_log_info *eli)
+{
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct megasas_evt_log_info *el_info;
+	dma_addr_t el_info_h = 0;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		return -ENOMEM;
+	}
+
+	dcmd = &cmd->frame->dcmd;
+	el_info = pci_alloc_consistent(instance->pdev,
+				       sizeof(struct megasas_evt_log_info),
+				       &el_info_h);
+
+	if (!el_info) {
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(el_info, 0, sizeof(*el_info));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0x0;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
+	dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
+	dcmd->sgl.sge32[0].phys_addr = el_info_h;
+	dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info);
+
+	megasas_issue_blocked_cmd(instance, cmd);
+
+	/*
+	 * Copy the data back into callers buffer
+	 */
+	memcpy(eli, el_info, sizeof(struct megasas_evt_log_info));
+
+	pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info),
+			    el_info, el_info_h);
+
+	megasas_return_cmd(instance, cmd);
+
+	return 0;
+}
+
+/**
+ * megasas_register_aen -	Registers for asynchronous event notification
+ * @instance:			Adapter soft state
+ * @seq_num:			The starting sequence number
+ * @class_locale:		Class of the event
+ *
+ * This function subscribes for AEN for events beyond the @seq_num. It requests
+ * to be notified if and only if the event is of type @class_locale
+ */
+static int
+megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
+		     u32 class_locale_word)
+{
+	int ret_val;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	union megasas_evt_class_locale curr_aen;
+	union megasas_evt_class_locale prev_aen;
+
+	/*
+	 * If there an AEN pending already (aen_cmd), check if the
+	 * class_locale of that pending AEN is inclusive of the new
+	 * AEN request we currently have. If it is, then we don't have
+	 * to do anything. In other words, whichever events the current
+	 * AEN request is subscribing to, have already been subscribed
+	 * to.
+	 *
+	 * If the old_cmd is _not_ inclusive, then we have to abort
+	 * that command, form a class_locale that is superset of both
+	 * old and current and re-issue to the FW
+	 */
+
+	curr_aen.word = class_locale_word;
+
+	if (instance->aen_cmd) {
+
+		prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1];
+
+		/*
+		 * A class whose enum value is smaller is inclusive of all
+		 * higher values. If a PROGRESS (= -1) was previously
+		 * registered, then a new registration requests for higher
+		 * classes need not be sent to FW. They are automatically
+		 * included.
+		 *
+		 * Locale numbers don't have such hierarchy. They are bitmap
+		 * values
+		 */
+		if ((prev_aen.members.class <= curr_aen.members.class) &&
+		    !((prev_aen.members.locale & curr_aen.members.locale) ^
+		      curr_aen.members.locale)) {
+			/*
+			 * Previously issued event registration includes
+			 * current request. Nothing to do.
+			 */
+			return 0;
+		} else {
+			curr_aen.members.locale |= prev_aen.members.locale;
+
+			if (prev_aen.members.class < curr_aen.members.class)
+				curr_aen.members.class = prev_aen.members.class;
+
+			instance->aen_cmd->abort_aen = 1;
+			ret_val = megasas_issue_blocked_abort_cmd(instance,
+								  instance->
+								  aen_cmd);
+
+			if (ret_val) {
+				printk(KERN_DEBUG "megasas: Failed to abort "
+				       "previous AEN command\n");
+				return ret_val;
+			}
+		}
+	}
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd)
+		return -ENOMEM;
+
+	dcmd = &cmd->frame->dcmd;
+
+	memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail));
+
+	/*
+	 * Prepare DCMD for aen registration
+	 */
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0x0;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	instance->last_seq_num = seq_num;
+	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
+	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
+	dcmd->mbox.w[0] = seq_num;
+	dcmd->mbox.w[1] = curr_aen.word;
+	dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h;
+	dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail);
+
+	if (instance->aen_cmd != NULL) {
+		megasas_return_cmd(instance, cmd);
+		return 0;
+	}
+
+	/*
+	 * Store reference to the cmd used to register for AEN. When an
+	 * application wants us to register for AEN, we have to abort this
+	 * cmd and re-register with a new EVENT LOCALE supplied by that app
+	 */
+	instance->aen_cmd = cmd;
+
+	/*
+	 * Issue the aen registration frame
+	 */
+	instance->instancet->issue_dcmd(instance, cmd);
+
+	return 0;
+}
+
+/**
+ * megasas_start_aen -	Subscribes to AEN during driver load time
+ * @instance:		Adapter soft state
+ */
+static int megasas_start_aen(struct megasas_instance *instance)
+{
+	struct megasas_evt_log_info eli;
+	union megasas_evt_class_locale class_locale;
+
+	/*
+	 * Get the latest sequence number from FW
+	 */
+	memset(&eli, 0, sizeof(eli));
+
+	if (megasas_get_seq_num(instance, &eli))
+		return -1;
+
+	/*
+	 * Register AEN with FW for latest sequence number plus 1
+	 */
+	class_locale.members.reserved = 0;
+	class_locale.members.locale = MR_EVT_LOCALE_ALL;
+	class_locale.members.class = MR_EVT_CLASS_DEBUG;
+
+	return megasas_register_aen(instance, eli.newest_seq_num + 1,
+				    class_locale.word);
+}
+
+/**
+ * megasas_io_attach -	Attaches this driver to SCSI mid-layer
+ * @instance:		Adapter soft state
+ */
+static int megasas_io_attach(struct megasas_instance *instance)
+{
+	struct Scsi_Host *host = instance->host;
+
+	/*
+	 * Export parameters required by SCSI mid-layer
+	 */
+	host->irq = instance->pdev->irq;
+	host->unique_id = instance->unique_id;
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		host->can_queue =
+			instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+	} else
+		host->can_queue =
+			instance->max_fw_cmds - MEGASAS_INT_CMDS;
+	host->this_id = instance->init_id;
+	host->sg_tablesize = instance->max_num_sge;
+	/*
+	 * Check if the module parameter value for max_sectors can be used
+	 */
+	if (max_sectors && max_sectors < instance->max_sectors_per_req)
+		instance->max_sectors_per_req = max_sectors;
+	else {
+		if (max_sectors) {
+			if (((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
+				(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0079GEN2)) &&
+				(max_sectors <= MEGASAS_MAX_SECTORS)) {
+				instance->max_sectors_per_req = max_sectors;
+			} else {
+			printk(KERN_INFO "megasas: max_sectors should be > 0"
+				"and <= %d (or < 1MB for GEN2 controller)\n",
+				instance->max_sectors_per_req);
+			}
+		}
+	}
+
+	host->max_sectors = instance->max_sectors_per_req;
+	host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
+	host->max_channel = MEGASAS_MAX_CHANNELS - 1;
+	host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
+	host->max_lun = MEGASAS_MAX_LUN;
+	host->max_cmd_len = 16;
+
+	/* Fusion only supports host reset */
+	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
+		host->hostt->eh_device_reset_handler = NULL;
+		host->hostt->eh_bus_reset_handler = NULL;
+	}
+
+	/*
+	 * Notify the mid-layer about the new controller
+	 */
+	if (scsi_add_host(host, &instance->pdev->dev)) {
+		printk(KERN_DEBUG "megasas: scsi_add_host failed\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Trigger SCSI to scan our drives
+	 */
+	scsi_scan_host(host);
+	return 0;
+}
+
+static int
+megasas_set_dma_mask(struct pci_dev *pdev)
+{
+	/*
+	 * All our contollers are capable of performing 64-bit DMA
+	 */
+	if (IS_DMA64) {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
+
+			if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+				goto fail_set_dma_mask;
+		}
+	} else {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+			goto fail_set_dma_mask;
+	}
+	return 0;
+
+fail_set_dma_mask:
+	return 1;
+}
+
+/**
+ * megasas_probe_one -	PCI hotplug entry point
+ * @pdev:		PCI device structure
+ * @id:			PCI ids of supported hotplugged adapter
+ */
+static int __devinit
+megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int rval;
+	struct Scsi_Host *host;
+	struct megasas_instance *instance;
+
+	/*
+	 * Announce PCI information
+	 */
+	printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
+	       pdev->vendor, pdev->device, pdev->subsystem_vendor,
+	       pdev->subsystem_device);
+
+	printk("bus %d:slot %d:func %d\n",
+	       pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+	/*
+	 * PCI prepping: enable device set bus mastering and dma mask
+	 */
+	rval = pci_enable_device_mem(pdev);
+
+	if (rval) {
+		return rval;
+	}
+
+	pci_set_master(pdev);
+
+	if (megasas_set_dma_mask(pdev))
+		goto fail_set_dma_mask;
+
+	host = scsi_host_alloc(&megasas_template,
+			       sizeof(struct megasas_instance));
+
+	if (!host) {
+		printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n");
+		goto fail_alloc_instance;
+	}
+
+	instance = (struct megasas_instance *)host->hostdata;
+	memset(instance, 0, sizeof(*instance));
+	atomic_set( &instance->fw_reset_no_pci_access, 0 );
+	instance->pdev = pdev;
+
+	switch (instance->pdev->device) {
+	case PCI_DEVICE_ID_LSI_FUSION:
+	{
+		struct fusion_context *fusion;
+
+		instance->ctrl_context =
+			kzalloc(sizeof(struct fusion_context), GFP_KERNEL);
+		if (!instance->ctrl_context) {
+			printk(KERN_DEBUG "megasas: Failed to allocate "
+			       "memory for Fusion context info\n");
+			goto fail_alloc_dma_buf;
+		}
+		fusion = instance->ctrl_context;
+		INIT_LIST_HEAD(&fusion->cmd_pool);
+		spin_lock_init(&fusion->cmd_pool_lock);
+	}
+	break;
+	default: /* For all other supported controllers */
+
+		instance->producer =
+			pci_alloc_consistent(pdev, sizeof(u32),
+					     &instance->producer_h);
+		instance->consumer =
+			pci_alloc_consistent(pdev, sizeof(u32),
+					     &instance->consumer_h);
+
+		if (!instance->producer || !instance->consumer) {
+			printk(KERN_DEBUG "megasas: Failed to allocate"
+			       "memory for producer, consumer\n");
+			goto fail_alloc_dma_buf;
+		}
+
+		*instance->producer = 0;
+		*instance->consumer = 0;
+		break;
+	}
+
+	megasas_poll_wait_aen = 0;
+	instance->flag_ieee = 0;
+	instance->ev = NULL;
+	instance->issuepend_done = 1;
+	instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+	megasas_poll_wait_aen = 0;
+
+	instance->evt_detail = pci_alloc_consistent(pdev,
+						    sizeof(struct
+							   megasas_evt_detail),
+						    &instance->evt_detail_h);
+
+	if (!instance->evt_detail) {
+		printk(KERN_DEBUG "megasas: Failed to allocate memory for "
+		       "event detail structure\n");
+		goto fail_alloc_dma_buf;
+	}
+
+	/*
+	 * Initialize locks and queues
+	 */
+	INIT_LIST_HEAD(&instance->cmd_pool);
+	INIT_LIST_HEAD(&instance->internal_reset_pending_q);
+
+	atomic_set(&instance->fw_outstanding,0);
+
+	init_waitqueue_head(&instance->int_cmd_wait_q);
+	init_waitqueue_head(&instance->abort_cmd_wait_q);
+
+	spin_lock_init(&instance->cmd_pool_lock);
+	spin_lock_init(&instance->hba_lock);
+	spin_lock_init(&instance->completion_lock);
+	spin_lock_init(&poll_aen_lock);
+
+	mutex_init(&instance->aen_mutex);
+	mutex_init(&instance->reset_mutex);
+
+	/*
+	 * Initialize PCI related and misc parameters
+	 */
+	instance->host = host;
+	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
+	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
+
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		instance->flag_ieee = 1;
+		sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
+	} else
+		sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
+
+	megasas_dbg_lvl = 0;
+	instance->flag = 0;
+	instance->unload = 1;
+	instance->last_time = 0;
+	instance->disableOnlineCtrlReset = 1;
+
+	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+		INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
+	else
+		INIT_WORK(&instance->work_init, process_fw_state_change_wq);
+
+	/*
+	 * Initialize MFI Firmware
+	 */
+	if (megasas_init_fw(instance))
+		goto fail_init_mfi;
+
+	/* Try to enable MSI-X */
+	if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) &&
+	    (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) &&
+	    (instance->pdev->device != PCI_DEVICE_ID_LSI_VERDE_ZCR) &&
+	    !msix_disable && !pci_enable_msix(instance->pdev,
+					      &instance->msixentry, 1))
+		instance->msi_flag = 1;
+
+	/*
+	 * Register IRQ
+	 */
+	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
+			pdev->irq, instance->instancet->service_isr,
+			IRQF_SHARED, "megasas", instance)) {
+		printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
+		goto fail_irq;
+	}
+
+	instance->instancet->enable_intr(instance->reg_set);
+
+	/*
+	 * Store instance in PCI softstate
+	 */
+	pci_set_drvdata(pdev, instance);
+
+	/*
+	 * Add this controller to megasas_mgmt_info structure so that it
+	 * can be exported to management applications
+	 */
+	megasas_mgmt_info.count++;
+	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance;
+	megasas_mgmt_info.max_index++;
+
+	/*
+	 * Initiate AEN (Asynchronous Event Notification)
+	 */
+	if (megasas_start_aen(instance)) {
+		printk(KERN_DEBUG "megasas: start aen failed\n");
+		goto fail_start_aen;
+	}
+
+	/*
+	 * Register with SCSI mid-layer
+	 */
+	if (megasas_io_attach(instance))
+		goto fail_io_attach;
+
+	instance->unload = 0;
+	return 0;
+
+      fail_start_aen:
+      fail_io_attach:
+	megasas_mgmt_info.count--;
+	megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL;
+	megasas_mgmt_info.max_index--;
+
+	pci_set_drvdata(pdev, NULL);
+	instance->instancet->disable_intr(instance->reg_set);
+	free_irq(instance->msi_flag ? instance->msixentry.vector :
+		 instance->pdev->irq, instance);
+	if (instance->msi_flag)
+		pci_disable_msix(instance->pdev);
+
+      fail_irq:
+      fail_init_mfi:
+      fail_alloc_dma_buf:
+	if (instance->evt_detail)
+		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+				    instance->evt_detail,
+				    instance->evt_detail_h);
+
+	if (instance->producer) {
+		pci_free_consistent(pdev, sizeof(u32), instance->producer,
+				    instance->producer_h);
+		megasas_release_mfi(instance);
+	} else {
+		megasas_release_fusion(instance);
+	}
+	if (instance->consumer)
+		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+				    instance->consumer_h);
+	scsi_host_put(host);
+
+      fail_alloc_instance:
+      fail_set_dma_mask:
+	pci_disable_device(pdev);
+
+	return -ENODEV;
+}
+
+/**
+ * megasas_flush_cache -	Requests FW to flush all its caches
+ * @instance:			Adapter soft state
+ */
+static void megasas_flush_cache(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd)
+		return;
+
+	dcmd = &cmd->frame->dcmd;
+
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0x0;
+	dcmd->sge_count = 0;
+	dcmd->flags = MFI_FRAME_DIR_NONE;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = 0;
+	dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
+	dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
+
+	megasas_issue_blocked_cmd(instance, cmd);
+
+	megasas_return_cmd(instance, cmd);
+
+	return;
+}
+
+/**
+ * megasas_shutdown_controller -	Instructs FW to shutdown the controller
+ * @instance:				Adapter soft state
+ * @opcode:				Shutdown/Hibernate
+ */
+static void megasas_shutdown_controller(struct megasas_instance *instance,
+					u32 opcode)
+{
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd)
+		return;
+
+	if (instance->aen_cmd)
+		megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
+	if (instance->map_update_cmd)
+		megasas_issue_blocked_abort_cmd(instance,
+						instance->map_update_cmd);
+	dcmd = &cmd->frame->dcmd;
+
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0x0;
+	dcmd->sge_count = 0;
+	dcmd->flags = MFI_FRAME_DIR_NONE;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = 0;
+	dcmd->opcode = opcode;
+
+	megasas_issue_blocked_cmd(instance, cmd);
+
+	megasas_return_cmd(instance, cmd);
+
+	return;
+}
+
+#ifdef CONFIG_PM
+/**
+ * megasas_suspend -	driver suspend entry point
+ * @pdev:		PCI device structure
+ * @state:		PCI power state to suspend routine
+ */
+static int
+megasas_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct Scsi_Host *host;
+	struct megasas_instance *instance;
+
+	instance = pci_get_drvdata(pdev);
+	host = instance->host;
+	instance->unload = 1;
+
+	if (poll_mode_io)
+		del_timer_sync(&instance->io_completion_timer);
+
+	megasas_flush_cache(instance);
+	megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
+
+	/* cancel the delayed work if this work still in queue */
+	if (instance->ev != NULL) {
+		struct megasas_aen_event *ev = instance->ev;
+		cancel_delayed_work(
+			(struct delayed_work *)&ev->hotplug_work);
+		flush_scheduled_work();
+		instance->ev = NULL;
+	}
+
+	tasklet_kill(&instance->isr_tasklet);
+
+	pci_set_drvdata(instance->pdev, instance);
+	instance->instancet->disable_intr(instance->reg_set);
+	free_irq(instance->msi_flag ? instance->msixentry.vector :
+		 instance->pdev->irq, instance);
+	if (instance->msi_flag)
+		pci_disable_msix(instance->pdev);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+/**
+ * megasas_resume-      driver resume entry point
+ * @pdev:               PCI device structure
+ */
+static int
+megasas_resume(struct pci_dev *pdev)
+{
+	int rval;
+	struct Scsi_Host *host;
+	struct megasas_instance *instance;
+
+	instance = pci_get_drvdata(pdev);
+	host = instance->host;
+	pci_set_power_state(pdev, PCI_D0);
+	pci_enable_wake(pdev, PCI_D0, 0);
+	pci_restore_state(pdev);
+
+	/*
+	 * PCI prepping: enable device set bus mastering and dma mask
+	 */
+	rval = pci_enable_device_mem(pdev);
+
+	if (rval) {
+		printk(KERN_ERR "megasas: Enable device failed\n");
+		return rval;
+	}
+
+	pci_set_master(pdev);
+
+	if (megasas_set_dma_mask(pdev))
+		goto fail_set_dma_mask;
+
+	/*
+	 * Initialize MFI Firmware
+	 */
+
+	atomic_set(&instance->fw_outstanding, 0);
+
+	/*
+	 * We expect the FW state to be READY
+	 */
+	if (megasas_transition_to_ready(instance))
+		goto fail_ready_state;
+
+	switch (instance->pdev->device) {
+	case PCI_DEVICE_ID_LSI_FUSION:
+	{
+		megasas_reset_reply_desc(instance);
+		if (megasas_ioc_init_fusion(instance)) {
+			megasas_free_cmds(instance);
+			megasas_free_cmds_fusion(instance);
+			goto fail_init_mfi;
+		}
+		if (!megasas_get_map_info(instance))
+			megasas_sync_map_info(instance);
+	}
+	break;
+	default:
+		*instance->producer = 0;
+		*instance->consumer = 0;
+		if (megasas_issue_init_mfi(instance))
+			goto fail_init_mfi;
+		break;
+	}
+
+	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+		     (unsigned long)instance);
+
+	/* Now re-enable MSI-X */
+	if (instance->msi_flag)
+		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
+
+	/*
+	 * Register IRQ
+	 */
+	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
+			pdev->irq, instance->instancet->service_isr,
+			IRQF_SHARED, "megasas", instance)) {
+		printk(KERN_ERR "megasas: Failed to register IRQ\n");
+		goto fail_irq;
+	}
+
+	instance->instancet->enable_intr(instance->reg_set);
+
+	/*
+	 * Initiate AEN (Asynchronous Event Notification)
+	 */
+	if (megasas_start_aen(instance))
+		printk(KERN_ERR "megasas: Start AEN failed\n");
+
+	/* Initialize the cmd completion timer */
+	if (poll_mode_io)
+		megasas_start_timer(instance, &instance->io_completion_timer,
+				megasas_io_completion_timer,
+				MEGASAS_COMPLETION_TIMER_INTERVAL);
+	instance->unload = 0;
+
+	return 0;
+
+fail_irq:
+fail_init_mfi:
+	if (instance->evt_detail)
+		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
+				instance->evt_detail,
+				instance->evt_detail_h);
+
+	if (instance->producer)
+		pci_free_consistent(pdev, sizeof(u32), instance->producer,
+				instance->producer_h);
+	if (instance->consumer)
+		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
+				instance->consumer_h);
+	scsi_host_put(host);
+
+fail_set_dma_mask:
+fail_ready_state:
+
+	pci_disable_device(pdev);
+
+	return -ENODEV;
+}
+#else
+#define megasas_suspend	NULL
+#define megasas_resume	NULL
+#endif
+
+/**
+ * megasas_detach_one -	PCI hot"un"plug entry point
+ * @pdev:		PCI device structure
+ */
+static void __devexit megasas_detach_one(struct pci_dev *pdev)
+{
+	int i;
+	struct Scsi_Host *host;
+	struct megasas_instance *instance;
+	struct fusion_context *fusion;
+
+	instance = pci_get_drvdata(pdev);
+	instance->unload = 1;
+	host = instance->host;
+	fusion = instance->ctrl_context;
+
+	if (poll_mode_io)
+		del_timer_sync(&instance->io_completion_timer);
+
+	scsi_remove_host(instance->host);
+	megasas_flush_cache(instance);
+	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
+
+	/* cancel the delayed work if this work still in queue*/
+	if (instance->ev != NULL) {
+		struct megasas_aen_event *ev = instance->ev;
+		cancel_delayed_work(
+			(struct delayed_work *)&ev->hotplug_work);
+		flush_scheduled_work();
+		instance->ev = NULL;
+	}
+
+	tasklet_kill(&instance->isr_tasklet);
+
+	/*
+	 * Take the instance off the instance array. Note that we will not
+	 * decrement the max_index. We let this array be sparse array
+	 */
+	for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+		if (megasas_mgmt_info.instance[i] == instance) {
+			megasas_mgmt_info.count--;
+			megasas_mgmt_info.instance[i] = NULL;
+
+			break;
+		}
+	}
+
+	pci_set_drvdata(instance->pdev, NULL);
+
+	instance->instancet->disable_intr(instance->reg_set);
+
+	free_irq(instance->msi_flag ? instance->msixentry.vector :
+		 instance->pdev->irq, instance);
+	if (instance->msi_flag)
+		pci_disable_msix(instance->pdev);
+
+	switch (instance->pdev->device) {
+	case PCI_DEVICE_ID_LSI_FUSION:
+		megasas_release_fusion(instance);
+		for (i = 0; i < 2 ; i++)
+			if (fusion->ld_map[i])
+				dma_free_coherent(&instance->pdev->dev,
+						  fusion->map_sz,
+						  fusion->ld_map[i],
+						  fusion->
+						  ld_map_phys[i]);
+		kfree(instance->ctrl_context);
+		break;
+	default:
+		megasas_release_mfi(instance);
+		pci_free_consistent(pdev,
+				    sizeof(struct megasas_evt_detail),
+				    instance->evt_detail,
+				    instance->evt_detail_h);
+		pci_free_consistent(pdev, sizeof(u32),
+				    instance->producer,
+				    instance->producer_h);
+		pci_free_consistent(pdev, sizeof(u32),
+				    instance->consumer,
+				    instance->consumer_h);
+		break;
+	}
+
+	scsi_host_put(host);
+
+	pci_set_drvdata(pdev, NULL);
+
+	pci_disable_device(pdev);
+
+	return;
+}
+
+/**
+ * megasas_shutdown -	Shutdown entry point
+ * @device:		Generic device structure
+ */
+static void megasas_shutdown(struct pci_dev *pdev)
+{
+	struct megasas_instance *instance = pci_get_drvdata(pdev);
+	instance->unload = 1;
+	megasas_flush_cache(instance);
+	megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
+}
+
+/**
+ * megasas_mgmt_open -	char node "open" entry point
+ */
+static int megasas_mgmt_open(struct inode *inode, struct file *filep)
+{
+	/*
+	 * Allow only those users with admin rights
+	 */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	return 0;
+}
+
+/**
+ * megasas_mgmt_fasync -	Async notifier registration from applications
+ *
+ * This function adds the calling process to a driver global queue. When an
+ * event occurs, SIGIO will be sent to all processes in this queue.
+ */
+static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
+{
+	int rc;
+
+	mutex_lock(&megasas_async_queue_mutex);
+
+	rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
+
+	mutex_unlock(&megasas_async_queue_mutex);
+
+	if (rc >= 0) {
+		/* For sanity check when we get ioctl */
+		filep->private_data = filep;
+		return 0;
+	}
+
+	printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc);
+
+	return rc;
+}
+
+/**
+ * megasas_mgmt_poll -  char node "poll" entry point
+ * */
+static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
+{
+	unsigned int mask;
+	unsigned long flags;
+	poll_wait(file, &megasas_poll_wait, wait);
+	spin_lock_irqsave(&poll_aen_lock, flags);
+	if (megasas_poll_wait_aen)
+		mask =   (POLLIN | POLLRDNORM);
+	else
+		mask = 0;
+	spin_unlock_irqrestore(&poll_aen_lock, flags);
+	return mask;
+}
+
+/**
+ * megasas_mgmt_fw_ioctl -	Issues management ioctls to FW
+ * @instance:			Adapter soft state
+ * @argp:			User's ioctl packet
+ */
+static int
+megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+		      struct megasas_iocpacket __user * user_ioc,
+		      struct megasas_iocpacket *ioc)
+{
+	struct megasas_sge32 *kern_sge32;
+	struct megasas_cmd *cmd;
+	void *kbuff_arr[MAX_IOCTL_SGE];
+	dma_addr_t buf_handle = 0;
+	int error = 0, i;
+	void *sense = NULL;
+	dma_addr_t sense_handle;
+	unsigned long *sense_ptr;
+
+	memset(kbuff_arr, 0, sizeof(kbuff_arr));
+
+	if (ioc->sge_count > MAX_IOCTL_SGE) {
+		printk(KERN_DEBUG "megasas: SGE count [%d] >  max limit [%d]\n",
+		       ioc->sge_count, MAX_IOCTL_SGE);
+		return -EINVAL;
+	}
+
+	cmd = megasas_get_cmd(instance);
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * User's IOCTL packet has 2 frames (maximum). Copy those two
+	 * frames into our cmd's frames. cmd->frame's context will get
+	 * overwritten when we copy from user's frames. So set that value
+	 * alone separately
+	 */
+	memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
+	cmd->frame->hdr.context = cmd->index;
+	cmd->frame->hdr.pad_0 = 0;
+
+	/*
+	 * The management interface between applications and the fw uses
+	 * MFI frames. E.g, RAID configuration changes, LD property changes
+	 * etc are accomplishes through different kinds of MFI frames. The
+	 * driver needs to care only about substituting user buffers with
+	 * kernel buffers in SGLs. The location of SGL is embedded in the
+	 * struct iocpacket itself.
+	 */
+	kern_sge32 = (struct megasas_sge32 *)
+	    ((unsigned long)cmd->frame + ioc->sgl_off);
+
+	/*
+	 * For each user buffer, create a mirror buffer and copy in
+	 */
+	for (i = 0; i < ioc->sge_count; i++) {
+		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
+						    ioc->sgl[i].iov_len,
+						    &buf_handle, GFP_KERNEL);
+		if (!kbuff_arr[i]) {
+			printk(KERN_DEBUG "megasas: Failed to alloc "
+			       "kernel SGL buffer for IOCTL \n");
+			error = -ENOMEM;
+			goto out;
+		}
+
+		/*
+		 * We don't change the dma_coherent_mask, so
+		 * pci_alloc_consistent only returns 32bit addresses
+		 */
+		kern_sge32[i].phys_addr = (u32) buf_handle;
+		kern_sge32[i].length = ioc->sgl[i].iov_len;
+
+		/*
+		 * We created a kernel buffer corresponding to the
+		 * user buffer. Now copy in from the user buffer
+		 */
+		if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base,
+				   (u32) (ioc->sgl[i].iov_len))) {
+			error = -EFAULT;
+			goto out;
+		}
+	}
+
+	if (ioc->sense_len) {
+		sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len,
+					     &sense_handle, GFP_KERNEL);
+		if (!sense) {
+			error = -ENOMEM;
+			goto out;
+		}
+
+		sense_ptr =
+		(unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
+		*sense_ptr = sense_handle;
+	}
+
+	/*
+	 * Set the sync_cmd flag so that the ISR knows not to complete this
+	 * cmd to the SCSI mid-layer
+	 */
+	cmd->sync_cmd = 1;
+	megasas_issue_blocked_cmd(instance, cmd);
+	cmd->sync_cmd = 0;
+
+	/*
+	 * copy out the kernel buffers to user buffers
+	 */
+	for (i = 0; i < ioc->sge_count; i++) {
+		if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i],
+				 ioc->sgl[i].iov_len)) {
+			error = -EFAULT;
+			goto out;
+		}
+	}
+
+	/*
+	 * copy out the sense
+	 */
+	if (ioc->sense_len) {
+		/*
+		 * sense_ptr points to the location that has the user
+		 * sense buffer address
+		 */
+		sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
+				ioc->sense_off);
+
+		if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
+				 sense, ioc->sense_len)) {
+			printk(KERN_ERR "megasas: Failed to copy out to user "
+					"sense data\n");
+			error = -EFAULT;
+			goto out;
+		}
+	}
+
+	/*
+	 * copy the status codes returned by the fw
+	 */
+	if (copy_to_user(&user_ioc->frame.hdr.cmd_status,
+			 &cmd->frame->hdr.cmd_status, sizeof(u8))) {
+		printk(KERN_DEBUG "megasas: Error copying out cmd_status\n");
+		error = -EFAULT;
+	}
+
+      out:
+	if (sense) {
+		dma_free_coherent(&instance->pdev->dev, ioc->sense_len,
+				    sense, sense_handle);
+	}
+
+	for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) {
+		dma_free_coherent(&instance->pdev->dev,
+				    kern_sge32[i].length,
+				    kbuff_arr[i], kern_sge32[i].phys_addr);
+	}
+
+	megasas_return_cmd(instance, cmd);
+	return error;
+}
+
+static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
+{
+	struct megasas_iocpacket __user *user_ioc =
+	    (struct megasas_iocpacket __user *)arg;
+	struct megasas_iocpacket *ioc;
+	struct megasas_instance *instance;
+	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+
+	ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
+	if (!ioc)
+		return -ENOMEM;
+
+	if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) {
+		error = -EFAULT;
+		goto out_kfree_ioc;
+	}
+
+	instance = megasas_lookup_instance(ioc->host_no);
+	if (!instance) {
+		error = -ENODEV;
+		goto out_kfree_ioc;
+	}
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		printk(KERN_ERR "Controller in crit error\n");
+		error = -ENODEV;
+		goto out_kfree_ioc;
+	}
+
+	if (instance->unload == 1) {
+		error = -ENODEV;
+		goto out_kfree_ioc;
+	}
+
+	/*
+	 * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
+	 */
+	if (down_interruptible(&instance->ioctl_sem)) {
+		error = -ERESTARTSYS;
+		goto out_kfree_ioc;
+	}
+
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting"
+				"for controller reset to finish\n");
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		printk(KERN_ERR "megaraid_sas: timed out while"
+			"waiting for HBA to recover\n");
+		error = -ENODEV;
+		goto out_kfree_ioc;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
+	up(&instance->ioctl_sem);
+
+      out_kfree_ioc:
+	kfree(ioc);
+	return error;
+}
+
+static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg)
+{
+	struct megasas_instance *instance;
+	struct megasas_aen aen;
+	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+
+	if (file->private_data != file) {
+		printk(KERN_DEBUG "megasas: fasync_helper was not "
+		       "called first\n");
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&aen, (void __user *)arg, sizeof(aen)))
+		return -EFAULT;
+
+	instance = megasas_lookup_instance(aen.host_no);
+
+	if (!instance)
+		return -ENODEV;
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		return -ENODEV;
+	}
+
+	if (instance->unload == 1) {
+		return -ENODEV;
+	}
+
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock,
+						flags);
+			break;
+		}
+
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting for"
+				"controller reset to finish\n");
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		printk(KERN_ERR "megaraid_sas: timed out while waiting"
+				"for HBA to recover.\n");
+		return -ENODEV;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	mutex_lock(&instance->aen_mutex);
+	error = megasas_register_aen(instance, aen.seq_num,
+				     aen.class_locale_word);
+	mutex_unlock(&instance->aen_mutex);
+	return error;
+}
+
+/**
+ * megasas_mgmt_ioctl -	char node ioctl entry point
+ */
+static long
+megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case MEGASAS_IOC_FIRMWARE:
+		return megasas_mgmt_ioctl_fw(file, arg);
+
+	case MEGASAS_IOC_GET_AEN:
+		return megasas_mgmt_ioctl_aen(file, arg);
+	}
+
+	return -ENOTTY;
+}
+
+#ifdef CONFIG_COMPAT
+static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
+{
+	struct compat_megasas_iocpacket __user *cioc =
+	    (struct compat_megasas_iocpacket __user *)arg;
+	struct megasas_iocpacket __user *ioc =
+	    compat_alloc_user_space(sizeof(struct megasas_iocpacket));
+	int i;
+	int error = 0;
+	compat_uptr_t ptr;
+
+	if (clear_user(ioc, sizeof(*ioc)))
+		return -EFAULT;
+
+	if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) ||
+	    copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) ||
+	    copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) ||
+	    copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) ||
+	    copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) ||
+	    copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
+		return -EFAULT;
+
+	/*
+	 * The sense_ptr is used in megasas_mgmt_fw_ioctl only when
+	 * sense_len is not null, so prepare the 64bit value under
+	 * the same condition.
+	 */
+	if (ioc->sense_len) {
+		void __user **sense_ioc_ptr =
+			(void __user **)(ioc->frame.raw + ioc->sense_off);
+		compat_uptr_t *sense_cioc_ptr =
+			(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
+		if (get_user(ptr, sense_cioc_ptr) ||
+		    put_user(compat_ptr(ptr), sense_ioc_ptr))
+			return -EFAULT;
+	}
+
+	for (i = 0; i < MAX_IOCTL_SGE; i++) {
+		if (get_user(ptr, &cioc->sgl[i].iov_base) ||
+		    put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
+		    copy_in_user(&ioc->sgl[i].iov_len,
+				 &cioc->sgl[i].iov_len, sizeof(compat_size_t)))
+			return -EFAULT;
+	}
+
+	error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc);
+
+	if (copy_in_user(&cioc->frame.hdr.cmd_status,
+			 &ioc->frame.hdr.cmd_status, sizeof(u8))) {
+		printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n");
+		return -EFAULT;
+	}
+	return error;
+}
+
+static long
+megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd,
+			  unsigned long arg)
+{
+	switch (cmd) {
+	case MEGASAS_IOC_FIRMWARE32:
+		return megasas_mgmt_compat_ioctl_fw(file, arg);
+	case MEGASAS_IOC_GET_AEN:
+		return megasas_mgmt_ioctl_aen(file, arg);
+	}
+
+	return -ENOTTY;
+}
+#endif
+
+/*
+ * File operations structure for management interface
+ */
+static const struct file_operations megasas_mgmt_fops = {
+	.owner = THIS_MODULE,
+	.open = megasas_mgmt_open,
+	.fasync = megasas_mgmt_fasync,
+	.unlocked_ioctl = megasas_mgmt_ioctl,
+	.poll = megasas_mgmt_poll,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = megasas_mgmt_compat_ioctl,
+#endif
+	.llseek = noop_llseek,
+};
+
+/*
+ * PCI hotplug support registration structure
+ */
+static struct pci_driver megasas_pci_driver = {
+
+	.name = "megaraid_sas",
+	.id_table = megasas_pci_table,
+	.probe = megasas_probe_one,
+	.remove = __devexit_p(megasas_detach_one),
+	.suspend = megasas_suspend,
+	.resume = megasas_resume,
+	.shutdown = megasas_shutdown,
+};
+
+/*
+ * Sysfs driver attributes
+ */
+static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
+{
+	return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n",
+			MEGASAS_VERSION);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
+
+static ssize_t
+megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
+{
+	return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
+			MEGASAS_RELDATE);
+}
+
+static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
+		   NULL);
+
+static ssize_t
+megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
+{
+	return sprintf(buf, "%u\n", support_poll_for_event);
+}
+
+static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
+			megasas_sysfs_show_support_poll_for_event, NULL);
+
+ static ssize_t
+megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf)
+{
+	return sprintf(buf, "%u\n", support_device_change);
+}
+
+static DRIVER_ATTR(support_device_change, S_IRUGO,
+			megasas_sysfs_show_support_device_change, NULL);
+
+static ssize_t
+megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
+{
+	return sprintf(buf, "%u\n", megasas_dbg_lvl);
+}
+
+static ssize_t
+megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count)
+{
+	int retval = count;
+	if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){
+		printk(KERN_ERR "megasas: could not set dbg_lvl\n");
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
+		megasas_sysfs_set_dbg_lvl);
+
+static ssize_t
+megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
+{
+	return sprintf(buf, "%u\n", poll_mode_io);
+}
+
+static ssize_t
+megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
+				const char *buf, size_t count)
+{
+	int retval = count;
+	int tmp = poll_mode_io;
+	int i;
+	struct megasas_instance *instance;
+
+	if (sscanf(buf, "%u", &poll_mode_io) < 1) {
+		printk(KERN_ERR "megasas: could not set poll_mode_io\n");
+		retval = -EINVAL;
+	}
+
+	/*
+	 * Check if poll_mode_io is already set or is same as previous value
+	 */
+	if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
+		goto out;
+
+	if (poll_mode_io) {
+		/*
+		 * Start timers for all adapters
+		 */
+		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+			instance = megasas_mgmt_info.instance[i];
+			if (instance) {
+				megasas_start_timer(instance,
+					&instance->io_completion_timer,
+					megasas_io_completion_timer,
+					MEGASAS_COMPLETION_TIMER_INTERVAL);
+			}
+		}
+	} else {
+		/*
+		 * Delete timers for all adapters
+		 */
+		for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+			instance = megasas_mgmt_info.instance[i];
+			if (instance)
+				del_timer_sync(&instance->io_completion_timer);
+		}
+	}
+
+out:
+	return retval;
+}
+
+static void
+megasas_aen_polling(struct work_struct *work)
+{
+	struct megasas_aen_event *ev =
+		container_of(work, struct megasas_aen_event, hotplug_work);
+	struct megasas_instance *instance = ev->instance;
+	union megasas_evt_class_locale class_locale;
+	struct  Scsi_Host *host;
+	struct  scsi_device *sdev1;
+	u16     pd_index = 0;
+	u16	ld_index = 0;
+	int     i, j, doscan = 0;
+	u32 seq_num;
+	int error;
+
+	if (!instance) {
+		printk(KERN_ERR "invalid instance!\n");
+		kfree(ev);
+		return;
+	}
+	instance->ev = NULL;
+	host = instance->host;
+	if (instance->evt_detail) {
+
+		switch (instance->evt_detail->code) {
+		case MR_EVT_PD_INSERTED:
+			if (megasas_get_pd_list(instance) == 0) {
+			for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
+				for (j = 0;
+				j < MEGASAS_MAX_DEV_PER_CHANNEL;
+				j++) {
+
+				pd_index =
+				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+
+				sdev1 =
+				scsi_device_lookup(host, i, j, 0);
+
+				if (instance->pd_list[pd_index].driveState
+						== MR_PD_STATE_SYSTEM) {
+						if (!sdev1) {
+						scsi_add_device(host, i, j, 0);
+						}
+
+					if (sdev1)
+						scsi_device_put(sdev1);
+					}
+				}
+			}
+			}
+			doscan = 0;
+			break;
+
+		case MR_EVT_PD_REMOVED:
+			if (megasas_get_pd_list(instance) == 0) {
+			megasas_get_pd_list(instance);
+			for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
+				for (j = 0;
+				j < MEGASAS_MAX_DEV_PER_CHANNEL;
+				j++) {
+
+				pd_index =
+				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+
+				sdev1 =
+				scsi_device_lookup(host, i, j, 0);
+
+				if (instance->pd_list[pd_index].driveState
+					== MR_PD_STATE_SYSTEM) {
+					if (sdev1) {
+						scsi_device_put(sdev1);
+					}
+				} else {
+					if (sdev1) {
+						scsi_remove_device(sdev1);
+						scsi_device_put(sdev1);
+					}
+				}
+				}
+			}
+			}
+			doscan = 0;
+			break;
+
+		case MR_EVT_LD_OFFLINE:
+		case MR_EVT_LD_DELETED:
+			megasas_get_ld_list(instance);
+			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
+				for (j = 0;
+				j < MEGASAS_MAX_DEV_PER_CHANNEL;
+				j++) {
+
+				ld_index =
+				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+
+				sdev1 = scsi_device_lookup(host,
+					i + MEGASAS_MAX_LD_CHANNELS,
+					j,
+					0);
+
+				if (instance->ld_ids[ld_index] != 0xff) {
+					if (sdev1) {
+						scsi_device_put(sdev1);
+					}
+				} else {
+					if (sdev1) {
+						scsi_remove_device(sdev1);
+						scsi_device_put(sdev1);
+					}
+				}
+				}
+			}
+			doscan = 0;
+			break;
+		case MR_EVT_LD_CREATED:
+			megasas_get_ld_list(instance);
+			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
+				for (j = 0;
+					j < MEGASAS_MAX_DEV_PER_CHANNEL;
+					j++) {
+					ld_index =
+					(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+
+					sdev1 = scsi_device_lookup(host,
+						i+MEGASAS_MAX_LD_CHANNELS,
+						j, 0);
+
+					if (instance->ld_ids[ld_index] !=
+								0xff) {
+						if (!sdev1) {
+							scsi_add_device(host,
+								i + 2,
+								j, 0);
+						}
+					}
+					if (sdev1) {
+						scsi_device_put(sdev1);
+					}
+				}
+			}
+			doscan = 0;
+			break;
+		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
+		case MR_EVT_FOREIGN_CFG_IMPORTED:
+		case MR_EVT_LD_STATE_CHANGE:
+			doscan = 1;
+			break;
+		default:
+			doscan = 0;
+			break;
+		}
+	} else {
+		printk(KERN_ERR "invalid evt_detail!\n");
+		kfree(ev);
+		return;
+	}
+
+	if (doscan) {
+		printk(KERN_INFO "scanning ...\n");
+		megasas_get_pd_list(instance);
+		for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
+			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
+				pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
+				sdev1 = scsi_device_lookup(host, i, j, 0);
+				if (instance->pd_list[pd_index].driveState ==
+							MR_PD_STATE_SYSTEM) {
+					if (!sdev1) {
+						scsi_add_device(host, i, j, 0);
+					}
+					if (sdev1)
+						scsi_device_put(sdev1);
+				} else {
+					if (sdev1) {
+						scsi_remove_device(sdev1);
+						scsi_device_put(sdev1);
+					}
+				}
+			}
+		}
+
+		megasas_get_ld_list(instance);
+		for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
+			for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
+				ld_index =
+				(i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
+
+				sdev1 = scsi_device_lookup(host,
+					i+MEGASAS_MAX_LD_CHANNELS, j, 0);
+				if (instance->ld_ids[ld_index] != 0xff) {
+					if (!sdev1) {
+						scsi_add_device(host,
+								i+2,
+								j, 0);
+					} else {
+						scsi_device_put(sdev1);
+					}
+				} else {
+					if (sdev1) {
+						scsi_remove_device(sdev1);
+						scsi_device_put(sdev1);
+					}
+				}
+			}
+		}
+	}
+
+	if ( instance->aen_cmd != NULL ) {
+		kfree(ev);
+		return ;
+	}
+
+	seq_num = instance->evt_detail->seq_num + 1;
+
+	/* Register AEN with FW for latest sequence number plus 1 */
+	class_locale.members.reserved = 0;
+	class_locale.members.locale = MR_EVT_LOCALE_ALL;
+	class_locale.members.class = MR_EVT_CLASS_DEBUG;
+	mutex_lock(&instance->aen_mutex);
+	error = megasas_register_aen(instance, seq_num,
+					class_locale.word);
+	mutex_unlock(&instance->aen_mutex);
+
+	if (error)
+		printk(KERN_ERR "register aen failed error %x\n", error);
+
+	kfree(ev);
+}
+
+
+static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
+		megasas_sysfs_show_poll_mode_io,
+		megasas_sysfs_set_poll_mode_io);
+
+/**
+ * megasas_init - Driver load entry point
+ */
+static int __init megasas_init(void)
+{
+	int rval;
+
+	/*
+	 * Announce driver version and other information
+	 */
+	printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
+	       MEGASAS_EXT_VERSION);
+
+	support_poll_for_event = 2;
+	support_device_change = 1;
+
+	memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
+
+	/*
+	 * Register character device node
+	 */
+	rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops);
+
+	if (rval < 0) {
+		printk(KERN_DEBUG "megasas: failed to open device node\n");
+		return rval;
+	}
+
+	megasas_mgmt_majorno = rval;
+
+	/*
+	 * Register ourselves as PCI hotplug module
+	 */
+	rval = pci_register_driver(&megasas_pci_driver);
+
+	if (rval) {
+		printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n");
+		goto err_pcidrv;
+	}
+
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				  &driver_attr_version);
+	if (rval)
+		goto err_dcf_attr_ver;
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				  &driver_attr_release_date);
+	if (rval)
+		goto err_dcf_rel_date;
+
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				&driver_attr_support_poll_for_event);
+	if (rval)
+		goto err_dcf_support_poll_for_event;
+
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				  &driver_attr_dbg_lvl);
+	if (rval)
+		goto err_dcf_dbg_lvl;
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				  &driver_attr_poll_mode_io);
+	if (rval)
+		goto err_dcf_poll_mode_io;
+
+	rval = driver_create_file(&megasas_pci_driver.driver,
+				&driver_attr_support_device_change);
+	if (rval)
+		goto err_dcf_support_device_change;
+
+	return rval;
+
+err_dcf_support_device_change:
+	driver_remove_file(&megasas_pci_driver.driver,
+		  &driver_attr_poll_mode_io);
+
+err_dcf_poll_mode_io:
+	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_dbg_lvl);
+err_dcf_dbg_lvl:
+	driver_remove_file(&megasas_pci_driver.driver,
+			&driver_attr_support_poll_for_event);
+
+err_dcf_support_poll_for_event:
+	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_release_date);
+
+err_dcf_rel_date:
+	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
+err_dcf_attr_ver:
+	pci_unregister_driver(&megasas_pci_driver);
+err_pcidrv:
+	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
+	return rval;
+}
+
+/**
+ * megasas_exit - Driver unload entry point
+ */
+static void __exit megasas_exit(void)
+{
+	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_poll_mode_io);
+	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_dbg_lvl);
+	driver_remove_file(&megasas_pci_driver.driver,
+			&driver_attr_support_poll_for_event);
+	driver_remove_file(&megasas_pci_driver.driver,
+			&driver_attr_support_device_change);
+	driver_remove_file(&megasas_pci_driver.driver,
+			   &driver_attr_release_date);
+	driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
+
+	pci_unregister_driver(&megasas_pci_driver);
+	unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl");
+}
+
+module_init(megasas_init);
+module_exit(megasas_exit);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
new file mode 100644
index 0000000..53fa96ae
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -0,0 +1,516 @@
+/*
+ *  Linux MegaRAID driver for SAS based RAID controllers
+ *
+ *  Copyright (c) 2009-2011  LSI 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
+ *
+ *  FILE: megaraid_sas_fp.c
+ *
+ *  Authors: LSI Corporation
+ *           Sumant Patro
+ *           Varad Talamacki
+ *           Manoj Jose
+ *
+ *  Send feedback to: <megaraidlinux@lsi.com>
+ *
+ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ *     ATTN: Linuxraid
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <linux/blkdev.h>
+#include <linux/poll.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#include "megaraid_sas_fusion.h"
+#include <asm/div64.h>
+
+#define ABS_DIFF(a, b)   (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
+#define MR_LD_STATE_OPTIMAL 3
+#define FALSE 0
+#define TRUE 1
+
+/* Prototypes */
+void
+mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
+			      struct LD_LOAD_BALANCE_INFO *lbInfo);
+
+u32 mega_mod64(u64 dividend, u32 divisor)
+{
+	u64 d;
+	u32 remainder;
+
+	if (!divisor)
+		printk(KERN_ERR "megasas : DIVISOR is zero, in div fn\n");
+	d = dividend;
+	remainder = do_div(d, divisor);
+	return remainder;
+}
+
+/**
+ * @param dividend    : Dividend
+ * @param divisor    : Divisor
+ *
+ * @return quotient
+ **/
+u64 mega_div64_32(uint64_t dividend, uint32_t divisor)
+{
+	u32 remainder;
+	u64 d;
+
+	if (!divisor)
+		printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n");
+
+	d = dividend;
+	remainder = do_div(d, divisor);
+
+	return d;
+}
+
+struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
+{
+	return &map->raidMap.ldSpanMap[ld].ldRaid;
+}
+
+static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld,
+						   struct MR_FW_RAID_MAP_ALL
+						   *map)
+{
+	return &map->raidMap.ldSpanMap[ld].spanBlock[0];
+}
+
+static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map)
+{
+	return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
+}
+
+static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map)
+{
+	return map->raidMap.arMapInfo[ar].pd[arm];
+}
+
+static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map)
+{
+	return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef;
+}
+
+static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map)
+{
+	return map->raidMap.devHndlInfo[pd].curDevHdl;
+}
+
+u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
+{
+	return map->raidMap.ldSpanMap[ld].ldRaid.targetId;
+}
+
+u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map)
+{
+	return map->raidMap.ldTgtIdToLd[ldTgtId];
+}
+
+static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span,
+					  struct MR_FW_RAID_MAP_ALL *map)
+{
+	return &map->raidMap.ldSpanMap[ld].spanBlock[span].span;
+}
+
+/*
+ * This function will validate Map info data provided by FW
+ */
+u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
+		      struct LD_LOAD_BALANCE_INFO *lbInfo)
+{
+	struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap;
+
+	if (pFwRaidMap->totalSize !=
+	    (sizeof(struct MR_FW_RAID_MAP) -sizeof(struct MR_LD_SPAN_MAP) +
+	     (sizeof(struct MR_LD_SPAN_MAP) *pFwRaidMap->ldCount))) {
+		printk(KERN_ERR "megasas: map info structure size 0x%x is not matching with ld count\n",
+		       (unsigned int)((sizeof(struct MR_FW_RAID_MAP) -
+				       sizeof(struct MR_LD_SPAN_MAP)) +
+				      (sizeof(struct MR_LD_SPAN_MAP) *
+				       pFwRaidMap->ldCount)));
+		printk(KERN_ERR "megasas: span map %x, pFwRaidMap->totalSize "
+		       ": %x\n", (unsigned int)sizeof(struct MR_LD_SPAN_MAP),
+		       pFwRaidMap->totalSize);
+		return 0;
+	}
+
+	mr_update_load_balance_params(map, lbInfo);
+
+	return 1;
+}
+
+u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
+		    struct MR_FW_RAID_MAP_ALL *map, int *div_error)
+{
+	struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
+	struct MR_QUAD_ELEMENT    *quad;
+	struct MR_LD_RAID         *raid = MR_LdRaidGet(ld, map);
+	u32                span, j;
+
+	for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) {
+
+		for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) {
+			quad = &pSpanBlock->block_span_info.quad[j];
+
+			if (quad->diff == 0) {
+				*div_error = 1;
+				return span;
+			}
+			if (quad->logStart <= row  &&  row <= quad->logEnd  &&
+			    (mega_mod64(row-quad->logStart, quad->diff)) == 0) {
+				if (span_blk != NULL) {
+					u64  blk, debugBlk;
+					blk =
+						mega_div64_32(
+							(row-quad->logStart),
+							quad->diff);
+					debugBlk = blk;
+
+					blk = (blk + quad->offsetInSpan) <<
+						raid->stripeShift;
+					*span_blk = blk;
+				}
+				return span;
+			}
+		}
+	}
+	return span;
+}
+
+/*
+******************************************************************************
+*
+* This routine calculates the arm, span and block for the specified stripe and
+* reference in stripe.
+*
+* Inputs :
+*
+*    ld   - Logical drive number
+*    stripRow        - Stripe number
+*    stripRef    - Reference in stripe
+*
+* Outputs :
+*
+*    span          - Span number
+*    block         - Absolute Block number in the physical disk
+*/
+u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock,
+		   u16 *pDevHandle, struct RAID_CONTEXT *pRAID_Context,
+		   struct MR_FW_RAID_MAP_ALL *map)
+{
+	struct MR_LD_RAID  *raid = MR_LdRaidGet(ld, map);
+	u32         pd, arRef;
+	u8          physArm, span;
+	u64         row;
+	u8	    retval = TRUE;
+	int	    error_code = 0;
+
+	row =  mega_div64_32(stripRow, raid->rowDataSize);
+
+	if (raid->level == 6) {
+		/* logical arm within row */
+		u32 logArm =  mega_mod64(stripRow, raid->rowDataSize);
+		u32 rowMod, armQ, arm;
+
+		if (raid->rowSize == 0)
+			return FALSE;
+		/* get logical row mod */
+		rowMod = mega_mod64(row, raid->rowSize);
+		armQ = raid->rowSize-1-rowMod; /* index of Q drive */
+		arm = armQ+1+logArm; /* data always logically follows Q */
+		if (arm >= raid->rowSize) /* handle wrap condition */
+			arm -= raid->rowSize;
+		physArm = (u8)arm;
+	} else  {
+		if (raid->modFactor == 0)
+			return FALSE;
+		physArm = MR_LdDataArmGet(ld,  mega_mod64(stripRow,
+							  raid->modFactor),
+					  map);
+	}
+
+	if (raid->spanDepth == 1) {
+		span = 0;
+		*pdBlock = row << raid->stripeShift;
+	} else {
+		span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code);
+		if (error_code == 1)
+			return FALSE;
+	}
+
+	/* Get the array on which this span is present */
+	arRef       = MR_LdSpanArrayGet(ld, span, map);
+	pd          = MR_ArPdGet(arRef, physArm, map); /* Get the pd */
+
+	if (pd != MR_PD_INVALID)
+		/* Get dev handle from Pd. */
+		*pDevHandle = MR_PdDevHandleGet(pd, map);
+	else {
+		*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
+		if (raid->level >= 5)
+			pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
+		else if (raid->level == 1) {
+			/* Get alternate Pd. */
+			pd = MR_ArPdGet(arRef, physArm + 1, map);
+			if (pd != MR_PD_INVALID)
+				/* Get dev handle from Pd */
+				*pDevHandle = MR_PdDevHandleGet(pd, map);
+		}
+		retval = FALSE;
+	}
+
+	*pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
+	pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
+		physArm;
+	return retval;
+}
+
+/*
+******************************************************************************
+*
+* MR_BuildRaidContext function
+*
+* This function will initiate command processing.  The start/end row and strip
+* information is calculated then the lock is acquired.
+* This function will return 0 if region lock was acquired OR return num strips
+*/
+u8
+MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+		    struct RAID_CONTEXT *pRAID_Context,
+		    struct MR_FW_RAID_MAP_ALL *map)
+{
+	struct MR_LD_RAID  *raid;
+	u32         ld, stripSize, stripe_mask;
+	u64         endLba, endStrip, endRow, start_row, start_strip;
+	u64         regStart;
+	u32         regSize;
+	u8          num_strips, numRows;
+	u16         ref_in_start_stripe, ref_in_end_stripe;
+	u64         ldStartBlock;
+	u32         numBlocks, ldTgtId;
+	u8          isRead;
+	u8	    retval = 0;
+
+	ldStartBlock = io_info->ldStartBlock;
+	numBlocks = io_info->numBlocks;
+	ldTgtId = io_info->ldTgtId;
+	isRead = io_info->isRead;
+
+	ld = MR_TargetIdToLdGet(ldTgtId, map);
+	raid = MR_LdRaidGet(ld, map);
+
+	stripSize = 1 << raid->stripeShift;
+	stripe_mask = stripSize-1;
+	/*
+	 * calculate starting row and stripe, and number of strips and rows
+	 */
+	start_strip         = ldStartBlock >> raid->stripeShift;
+	ref_in_start_stripe = (u16)(ldStartBlock & stripe_mask);
+	endLba              = ldStartBlock + numBlocks - 1;
+	ref_in_end_stripe   = (u16)(endLba & stripe_mask);
+	endStrip            = endLba >> raid->stripeShift;
+	num_strips          = (u8)(endStrip - start_strip + 1); /* End strip */
+	if (raid->rowDataSize == 0)
+		return FALSE;
+	start_row           =  mega_div64_32(start_strip, raid->rowDataSize);
+	endRow              =  mega_div64_32(endStrip, raid->rowDataSize);
+	numRows             = (u8)(endRow - start_row + 1);
+
+	/*
+	 * calculate region info.
+	 */
+
+	/* assume region is at the start of the first row */
+	regStart            = start_row << raid->stripeShift;
+	/* assume this IO needs the full row - we'll adjust if not true */
+	regSize             = stripSize;
+
+	/* If IO spans more than 1 strip, fp is not possible
+	   FP is not possible for writes on non-0 raid levels
+	   FP is not possible if LD is not capable */
+	if (num_strips > 1 || (!isRead && raid->level != 0) ||
+	    !raid->capability.fpCapable) {
+		io_info->fpOkForIo = FALSE;
+	} else {
+		io_info->fpOkForIo = TRUE;
+	}
+
+	if (numRows == 1) {
+		/* single-strip IOs can always lock only the data needed */
+		if (num_strips == 1) {
+			regStart += ref_in_start_stripe;
+			regSize = numBlocks;
+		}
+		/* multi-strip IOs always need to full stripe locked */
+	} else {
+		if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
+			/* If the start strip is the last in the start row */
+			regStart += ref_in_start_stripe;
+			regSize = stripSize - ref_in_start_stripe;
+			/* initialize count to sectors from startref to end
+			   of strip */
+		}
+
+		if (numRows > 2)
+			/* Add complete rows in the middle of the transfer */
+			regSize += (numRows-2) << raid->stripeShift;
+
+		/* if IO ends within first strip of last row */
+		if (endStrip == endRow*raid->rowDataSize)
+			regSize += ref_in_end_stripe+1;
+		else
+			regSize += stripSize;
+	}
+
+	pRAID_Context->timeoutValue     = map->raidMap.fpPdIoTimeoutSec;
+	pRAID_Context->regLockFlags     = (isRead) ? REGION_TYPE_SHARED_READ :
+		raid->regTypeReqOnWrite;
+	pRAID_Context->VirtualDiskTgtId = raid->targetId;
+	pRAID_Context->regLockRowLBA    = regStart;
+	pRAID_Context->regLockLength    = regSize;
+	pRAID_Context->configSeqNum	= raid->seqNum;
+
+	/*Get Phy Params only if FP capable, or else leave it to MR firmware
+	  to do the calculation.*/
+	if (io_info->fpOkForIo) {
+		retval = MR_GetPhyParams(ld, start_strip, ref_in_start_stripe,
+					 &io_info->pdBlock,
+					 &io_info->devHandle, pRAID_Context,
+					 map);
+		/* If IO on an invalid Pd, then FP i snot possible */
+		if (io_info->devHandle == MR_PD_INVALID)
+			io_info->fpOkForIo = FALSE;
+		return retval;
+	} else if (isRead) {
+		uint stripIdx;
+		for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
+			if (!MR_GetPhyParams(ld, start_strip + stripIdx,
+					     ref_in_start_stripe,
+					     &io_info->pdBlock,
+					     &io_info->devHandle,
+					     pRAID_Context, map))
+				return TRUE;
+		}
+	}
+	return TRUE;
+}
+
+void
+mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
+			      struct LD_LOAD_BALANCE_INFO *lbInfo)
+{
+	int ldCount;
+	u16 ld;
+	struct MR_LD_RAID *raid;
+
+	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
+		ld = MR_TargetIdToLdGet(ldCount, map);
+		if (ld >= MAX_LOGICAL_DRIVES) {
+			lbInfo[ldCount].loadBalanceFlag = 0;
+			continue;
+		}
+
+		raid = MR_LdRaidGet(ld, map);
+
+		/* Two drive Optimal RAID 1 */
+		if ((raid->level == 1)  &&  (raid->rowSize == 2) &&
+		    (raid->spanDepth == 1) && raid->ldState ==
+		    MR_LD_STATE_OPTIMAL) {
+			u32 pd, arRef;
+
+			lbInfo[ldCount].loadBalanceFlag = 1;
+
+			/* Get the array on which this span is present */
+			arRef = MR_LdSpanArrayGet(ld, 0, map);
+
+			/* Get the Pd */
+			pd = MR_ArPdGet(arRef, 0, map);
+			/* Get dev handle from Pd */
+			lbInfo[ldCount].raid1DevHandle[0] =
+				MR_PdDevHandleGet(pd, map);
+			/* Get the Pd */
+			pd = MR_ArPdGet(arRef, 1, map);
+
+			/* Get the dev handle from Pd */
+			lbInfo[ldCount].raid1DevHandle[1] =
+				MR_PdDevHandleGet(pd, map);
+		} else
+			lbInfo[ldCount].loadBalanceFlag = 0;
+	}
+}
+
+u8 megasas_get_best_arm(struct LD_LOAD_BALANCE_INFO *lbInfo, u8 arm, u64 block,
+			u32 count)
+{
+	u16     pend0, pend1;
+	u64     diff0, diff1;
+	u8      bestArm;
+
+	/* get the pending cmds for the data and mirror arms */
+	pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]);
+	pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]);
+
+	/* Determine the disk whose head is nearer to the req. block */
+	diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]);
+	diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]);
+	bestArm = (diff0 <= diff1 ? 0 : 1);
+
+	if ((bestArm == arm && pend0 > pend1 + 16)  ||
+	    (bestArm != arm && pend1 > pend0 + 16))
+		bestArm ^= 1;
+
+	/* Update the last accessed block on the correct pd */
+	lbInfo->last_accessed_block[bestArm] = block + count - 1;
+
+	return bestArm;
+}
+
+u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
+			   struct IO_REQUEST_INFO *io_info)
+{
+	u8 arm, old_arm;
+	u16 devHandle;
+
+	old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1;
+
+	/* get best new arm */
+	arm  = megasas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock,
+				    io_info->numBlocks);
+	devHandle = lbInfo->raid1DevHandle[arm];
+	atomic_inc(&lbInfo->scsi_pending_cmds[arm]);
+
+	return devHandle;
+}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
new file mode 100644
index 0000000..c1e09d5
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -0,0 +1,2248 @@
+/*
+ *  Linux MegaRAID driver for SAS based RAID controllers
+ *
+ *  Copyright (c) 2009-2011  LSI 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
+ *
+ *  FILE: megaraid_sas_fusion.c
+ *
+ *  Authors: LSI Corporation
+ *           Sumant Patro
+ *           Adam Radford <linuxraid@lsi.com>
+ *
+ *  Send feedback to: <megaraidlinux@lsi.com>
+ *
+ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ *     ATTN: Linuxraid
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/compat.h>
+#include <linux/blkdev.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#include "megaraid_sas_fusion.h"
+#include "megaraid_sas.h"
+
+extern void megasas_free_cmds(struct megasas_instance *instance);
+extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+					   *instance);
+extern void
+megasas_complete_cmd(struct megasas_instance *instance,
+		     struct megasas_cmd *cmd, u8 alt_status);
+int megasas_is_ldio(struct scsi_cmnd *cmd);
+int
+wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd);
+
+void
+megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd);
+int megasas_alloc_cmds(struct megasas_instance *instance);
+int
+megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs);
+int
+megasas_issue_polled(struct megasas_instance *instance,
+		     struct megasas_cmd *cmd);
+
+u8
+MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info,
+		    struct RAID_CONTEXT *pRAID_Context,
+		    struct MR_FW_RAID_MAP_ALL *map);
+u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
+struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+
+u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
+		      struct LD_LOAD_BALANCE_INFO *lbInfo);
+u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
+			   struct IO_REQUEST_INFO *in_info);
+int megasas_transition_to_ready(struct megasas_instance *instance);
+void megaraid_sas_kill_hba(struct megasas_instance *instance);
+
+extern u32 megasas_dbg_lvl;
+
+/**
+ * megasas_enable_intr_fusion -	Enables interrupts
+ * @regs:			MFI register set
+ */
+void
+megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
+{
+	writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_fusion - Disables interrupt
+ * @regs:			 MFI register set
+ */
+void
+megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs)
+{
+	u32 mask = 0xFFFFFFFF;
+	u32 status;
+
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	status = readl(&regs->outbound_intr_mask);
+}
+
+int
+megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs)
+{
+	u32 status;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (status & 1) {
+		writel(status, &regs->outbound_intr_status);
+		readl(&regs->outbound_intr_status);
+		return 1;
+	}
+	if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
+		return 0;
+
+	/*
+	 * dummy read to flush PCI
+	 */
+	readl(&regs->outbound_intr_status);
+
+	return 1;
+}
+
+/**
+ * megasas_get_cmd_fusion -	Get a command from the free pool
+ * @instance:		Adapter soft state
+ *
+ * Returns a free command from the pool
+ */
+struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance
+						  *instance)
+{
+	unsigned long flags;
+	struct fusion_context *fusion =
+		(struct fusion_context *)instance->ctrl_context;
+	struct megasas_cmd_fusion *cmd = NULL;
+
+	spin_lock_irqsave(&fusion->cmd_pool_lock, flags);
+
+	if (!list_empty(&fusion->cmd_pool)) {
+		cmd = list_entry((&fusion->cmd_pool)->next,
+				 struct megasas_cmd_fusion, list);
+		list_del_init(&cmd->list);
+	} else {
+		printk(KERN_ERR "megasas: Command pool (fusion) empty!\n");
+	}
+
+	spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags);
+	return cmd;
+}
+
+/**
+ * megasas_return_cmd_fusion -	Return a cmd to free command pool
+ * @instance:		Adapter soft state
+ * @cmd:		Command packet to be returned to free command pool
+ */
+static inline void
+megasas_return_cmd_fusion(struct megasas_instance *instance,
+			  struct megasas_cmd_fusion *cmd)
+{
+	unsigned long flags;
+	struct fusion_context *fusion =
+		(struct fusion_context *)instance->ctrl_context;
+
+	spin_lock_irqsave(&fusion->cmd_pool_lock, flags);
+
+	cmd->scmd = NULL;
+	cmd->sync_cmd_idx = (u32)ULONG_MAX;
+	list_add_tail(&cmd->list, &fusion->cmd_pool);
+
+	spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags);
+}
+
+/**
+ * megasas_teardown_frame_pool_fusion -	Destroy the cmd frame DMA pool
+ * @instance:				Adapter soft state
+ */
+static void megasas_teardown_frame_pool_fusion(
+	struct megasas_instance *instance)
+{
+	int i;
+	struct fusion_context *fusion = instance->ctrl_context;
+
+	u16 max_cmd = instance->max_fw_cmds;
+
+	struct megasas_cmd_fusion *cmd;
+
+	if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) {
+		printk(KERN_ERR "megasas: dma pool is null. SG Pool %p, "
+		       "sense pool : %p\n", fusion->sg_dma_pool,
+		       fusion->sense_dma_pool);
+		return;
+	}
+
+	/*
+	 * Return all frames to pool
+	 */
+	for (i = 0; i < max_cmd; i++) {
+
+		cmd = fusion->cmd_list[i];
+
+		if (cmd->sg_frame)
+			pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame,
+				      cmd->sg_frame_phys_addr);
+
+		if (cmd->sense)
+			pci_pool_free(fusion->sense_dma_pool, cmd->sense,
+				      cmd->sense_phys_addr);
+	}
+
+	/*
+	 * Now destroy the pool itself
+	 */
+	pci_pool_destroy(fusion->sg_dma_pool);
+	pci_pool_destroy(fusion->sense_dma_pool);
+
+	fusion->sg_dma_pool = NULL;
+	fusion->sense_dma_pool = NULL;
+}
+
+/**
+ * megasas_free_cmds_fusion -	Free all the cmds in the free cmd pool
+ * @instance:		Adapter soft state
+ */
+void
+megasas_free_cmds_fusion(struct megasas_instance *instance)
+{
+	int i;
+	struct fusion_context *fusion = instance->ctrl_context;
+
+	u32 max_cmds, req_sz, reply_sz, io_frames_sz;
+
+
+	req_sz = fusion->request_alloc_sz;
+	reply_sz = fusion->reply_alloc_sz;
+	io_frames_sz = fusion->io_frames_alloc_sz;
+
+	max_cmds = instance->max_fw_cmds;
+
+	/* Free descriptors and request Frames memory */
+	if (fusion->req_frames_desc)
+		dma_free_coherent(&instance->pdev->dev, req_sz,
+				  fusion->req_frames_desc,
+				  fusion->req_frames_desc_phys);
+
+	if (fusion->reply_frames_desc) {
+		pci_pool_free(fusion->reply_frames_desc_pool,
+			      fusion->reply_frames_desc,
+			      fusion->reply_frames_desc_phys);
+		pci_pool_destroy(fusion->reply_frames_desc_pool);
+	}
+
+	if (fusion->io_request_frames) {
+		pci_pool_free(fusion->io_request_frames_pool,
+			      fusion->io_request_frames,
+			      fusion->io_request_frames_phys);
+		pci_pool_destroy(fusion->io_request_frames_pool);
+	}
+
+	/* Free the Fusion frame pool */
+	megasas_teardown_frame_pool_fusion(instance);
+
+	/* Free all the commands in the cmd_list */
+	for (i = 0; i < max_cmds; i++)
+		kfree(fusion->cmd_list[i]);
+
+	/* Free the cmd_list buffer itself */
+	kfree(fusion->cmd_list);
+	fusion->cmd_list = NULL;
+
+	INIT_LIST_HEAD(&fusion->cmd_pool);
+}
+
+/**
+ * megasas_create_frame_pool_fusion -	Creates DMA pool for cmd frames
+ * @instance:			Adapter soft state
+ *
+ */
+static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
+{
+	int i;
+	u32 max_cmd;
+	struct fusion_context *fusion;
+	struct megasas_cmd_fusion *cmd;
+	u32 total_sz_chain_frame;
+
+	fusion = instance->ctrl_context;
+	max_cmd = instance->max_fw_cmds;
+
+	total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME;
+
+	/*
+	 * Use DMA pool facility provided by PCI layer
+	 */
+
+	fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion",
+					      instance->pdev,
+					      total_sz_chain_frame, 4,
+					      0);
+	if (!fusion->sg_dma_pool) {
+		printk(KERN_DEBUG "megasas: failed to setup request pool "
+		       "fusion\n");
+		return -ENOMEM;
+	}
+	fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion",
+						 instance->pdev,
+						 SCSI_SENSE_BUFFERSIZE, 64, 0);
+
+	if (!fusion->sense_dma_pool) {
+		printk(KERN_DEBUG "megasas: failed to setup sense pool "
+		       "fusion\n");
+		pci_pool_destroy(fusion->sg_dma_pool);
+		fusion->sg_dma_pool = NULL;
+		return -ENOMEM;
+	}
+
+	/*
+	 * Allocate and attach a frame to each of the commands in cmd_list
+	 */
+	for (i = 0; i < max_cmd; i++) {
+
+		cmd = fusion->cmd_list[i];
+
+		cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool,
+					       GFP_KERNEL,
+					       &cmd->sg_frame_phys_addr);
+
+		cmd->sense = pci_pool_alloc(fusion->sense_dma_pool,
+					    GFP_KERNEL, &cmd->sense_phys_addr);
+		/*
+		 * megasas_teardown_frame_pool_fusion() takes care of freeing
+		 * whatever has been allocated
+		 */
+		if (!cmd->sg_frame || !cmd->sense) {
+			printk(KERN_DEBUG "megasas: pci_pool_alloc failed\n");
+			megasas_teardown_frame_pool_fusion(instance);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+/**
+ * megasas_alloc_cmds_fusion -	Allocates the command packets
+ * @instance:		Adapter soft state
+ *
+ *
+ * Each frame has a 32-bit field called context. This context is used to get
+ * back the megasas_cmd_fusion from the frame when a frame gets completed
+ * In this driver, the 32 bit values are the indices into an array cmd_list.
+ * This array is used only to look up the megasas_cmd_fusion given the context.
+ * The free commands themselves are maintained in a linked list called cmd_pool.
+ *
+ * cmds are formed in the io_request and sg_frame members of the
+ * megasas_cmd_fusion. The context field is used to get a request descriptor
+ * and is used as SMID of the cmd.
+ * SMID value range is from 1 to max_fw_cmds.
+ */
+int
+megasas_alloc_cmds_fusion(struct megasas_instance *instance)
+{
+	int i, j;
+	u32 max_cmd, io_frames_sz;
+	struct fusion_context *fusion;
+	struct megasas_cmd_fusion *cmd;
+	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
+	u32 offset;
+	dma_addr_t io_req_base_phys;
+	u8 *io_req_base;
+
+	fusion = instance->ctrl_context;
+
+	max_cmd = instance->max_fw_cmds;
+
+	fusion->req_frames_desc =
+		dma_alloc_coherent(&instance->pdev->dev,
+				   fusion->request_alloc_sz,
+				   &fusion->req_frames_desc_phys, GFP_KERNEL);
+
+	if (!fusion->req_frames_desc) {
+		printk(KERN_ERR "megasas; Could not allocate memory for "
+		       "request_frames\n");
+		goto fail_req_desc;
+	}
+
+	fusion->reply_frames_desc_pool =
+		pci_pool_create("reply_frames pool", instance->pdev,
+				fusion->reply_alloc_sz, 16, 0);
+
+	if (!fusion->reply_frames_desc_pool) {
+		printk(KERN_ERR "megasas; Could not allocate memory for "
+		       "reply_frame pool\n");
+		goto fail_reply_desc;
+	}
+
+	fusion->reply_frames_desc =
+		pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL,
+			       &fusion->reply_frames_desc_phys);
+	if (!fusion->reply_frames_desc) {
+		printk(KERN_ERR "megasas; Could not allocate memory for "
+		       "reply_frame pool\n");
+		pci_pool_destroy(fusion->reply_frames_desc_pool);
+		goto fail_reply_desc;
+	}
+
+	reply_desc = fusion->reply_frames_desc;
+	for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++)
+		reply_desc->Words = ULLONG_MAX;
+
+	io_frames_sz = fusion->io_frames_alloc_sz;
+
+	fusion->io_request_frames_pool =
+		pci_pool_create("io_request_frames pool", instance->pdev,
+				fusion->io_frames_alloc_sz, 16, 0);
+
+	if (!fusion->io_request_frames_pool) {
+		printk(KERN_ERR "megasas: Could not allocate memory for "
+		       "io_request_frame pool\n");
+		goto fail_io_frames;
+	}
+
+	fusion->io_request_frames =
+		pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL,
+			       &fusion->io_request_frames_phys);
+	if (!fusion->io_request_frames) {
+		printk(KERN_ERR "megasas: Could not allocate memory for "
+		       "io_request_frames frames\n");
+		pci_pool_destroy(fusion->io_request_frames_pool);
+		goto fail_io_frames;
+	}
+
+	/*
+	 * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers.
+	 * Allocate the dynamic array first and then allocate individual
+	 * commands.
+	 */
+	fusion->cmd_list = kmalloc(sizeof(struct megasas_cmd_fusion *)
+				   *max_cmd, GFP_KERNEL);
+
+	if (!fusion->cmd_list) {
+		printk(KERN_DEBUG "megasas: out of memory. Could not alloc "
+		       "memory for cmd_list_fusion\n");
+		goto fail_cmd_list;
+	}
+
+	memset(fusion->cmd_list, 0, sizeof(struct megasas_cmd_fusion *)
+	       *max_cmd);
+
+	max_cmd = instance->max_fw_cmds;
+	for (i = 0; i < max_cmd; i++) {
+		fusion->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd_fusion),
+					      GFP_KERNEL);
+		if (!fusion->cmd_list[i]) {
+			printk(KERN_ERR "Could not alloc cmd list fusion\n");
+
+			for (j = 0; j < i; j++)
+				kfree(fusion->cmd_list[j]);
+
+			kfree(fusion->cmd_list);
+			fusion->cmd_list = NULL;
+			goto fail_cmd_list;
+		}
+	}
+
+	/* The first 256 bytes (SMID 0) is not used. Don't add to cmd list */
+	io_req_base = fusion->io_request_frames +
+		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
+	io_req_base_phys = fusion->io_request_frames_phys +
+		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
+
+	/*
+	 * Add all the commands to command pool (fusion->cmd_pool)
+	 */
+
+	/* SMID 0 is reserved. Set SMID/index from 1 */
+	for (i = 0; i < max_cmd; i++) {
+		cmd = fusion->cmd_list[i];
+		offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
+		memset(cmd, 0, sizeof(struct megasas_cmd_fusion));
+		cmd->index = i + 1;
+		cmd->scmd = NULL;
+		cmd->sync_cmd_idx = (u32)ULONG_MAX; /* Set to Invalid */
+		cmd->instance = instance;
+		cmd->io_request =
+			(struct MPI2_RAID_SCSI_IO_REQUEST *)
+		  (io_req_base + offset);
+		memset(cmd->io_request, 0,
+		       sizeof(struct MPI2_RAID_SCSI_IO_REQUEST));
+		cmd->io_request_phys_addr = io_req_base_phys + offset;
+
+		list_add_tail(&cmd->list, &fusion->cmd_pool);
+	}
+
+	/*
+	 * Create a frame pool and assign one frame to each cmd
+	 */
+	if (megasas_create_frame_pool_fusion(instance)) {
+		printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n");
+		megasas_free_cmds_fusion(instance);
+		goto fail_req_desc;
+	}
+
+	return 0;
+
+fail_cmd_list:
+	pci_pool_free(fusion->io_request_frames_pool, fusion->io_request_frames,
+		      fusion->io_request_frames_phys);
+	pci_pool_destroy(fusion->io_request_frames_pool);
+fail_io_frames:
+	dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
+			  fusion->reply_frames_desc,
+			  fusion->reply_frames_desc_phys);
+	pci_pool_free(fusion->reply_frames_desc_pool,
+		      fusion->reply_frames_desc,
+		      fusion->reply_frames_desc_phys);
+	pci_pool_destroy(fusion->reply_frames_desc_pool);
+
+fail_reply_desc:
+	dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz,
+			  fusion->req_frames_desc,
+			  fusion->req_frames_desc_phys);
+fail_req_desc:
+	return -ENOMEM;
+}
+
+/**
+ * wait_and_poll -	Issues a polling command
+ * @instance:			Adapter soft state
+ * @cmd:			Command packet to be issued
+ *
+ * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
+ */
+int
+wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+	int i;
+	struct megasas_header *frame_hdr = &cmd->frame->hdr;
+
+	u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000;
+
+	/*
+	 * Wait for cmd_status to change
+	 */
+	for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) {
+		rmb();
+		msleep(20);
+	}
+
+	if (frame_hdr->cmd_status == 0xff)
+		return -ETIME;
+
+	return 0;
+}
+
+/**
+ * megasas_ioc_init_fusion -	Initializes the FW
+ * @instance:		Adapter soft state
+ *
+ * Issues the IOC Init cmd
+ */
+int
+megasas_ioc_init_fusion(struct megasas_instance *instance)
+{
+	struct megasas_init_frame *init_frame;
+	struct MPI2_IOC_INIT_REQUEST *IOCInitMessage;
+	dma_addr_t	ioc_init_handle;
+	u32 context;
+	struct megasas_cmd *cmd;
+	u8 ret;
+	struct fusion_context *fusion;
+	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+	int i;
+	struct megasas_header *frame_hdr;
+
+	fusion = instance->ctrl_context;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_ERR "Could not allocate cmd for INIT Frame\n");
+		ret = 1;
+		goto fail_get_cmd;
+	}
+
+	IOCInitMessage =
+	  dma_alloc_coherent(&instance->pdev->dev,
+			     sizeof(struct MPI2_IOC_INIT_REQUEST),
+			     &ioc_init_handle, GFP_KERNEL);
+
+	if (!IOCInitMessage) {
+		printk(KERN_ERR "Could not allocate memory for "
+		       "IOCInitMessage\n");
+		ret = 1;
+		goto fail_fw_init;
+	}
+
+	memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST));
+
+	IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT;
+	IOCInitMessage->WhoInit	= MPI2_WHOINIT_HOST_DRIVER;
+	IOCInitMessage->MsgVersion = MPI2_VERSION;
+	IOCInitMessage->HeaderVersion = MPI2_HEADER_VERSION;
+	IOCInitMessage->SystemRequestFrameSize =
+		MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4;
+
+	IOCInitMessage->ReplyDescriptorPostQueueDepth = fusion->reply_q_depth;
+	IOCInitMessage->ReplyDescriptorPostQueueAddress	=
+		fusion->reply_frames_desc_phys;
+	IOCInitMessage->SystemRequestFrameBaseAddress =
+		fusion->io_request_frames_phys;
+
+	init_frame = (struct megasas_init_frame *)cmd->frame;
+	memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
+
+	frame_hdr = &cmd->frame->hdr;
+	context = init_frame->context;
+	init_frame->context = context;
+
+	frame_hdr->cmd_status = 0xFF;
+	frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+	init_frame->cmd	= MFI_CMD_INIT;
+	init_frame->cmd_status = 0xFF;
+
+	init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
+	init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
+
+	req_desc =
+	  (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)fusion->req_frames_desc;
+
+	req_desc->Words = cmd->frame_phys_addr;
+	req_desc->MFAIo.RequestFlags =
+		(MEGASAS_REQ_DESCRIPT_FLAGS_MFA <<
+		 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+
+	/*
+	 * disable the intr before firing the init frame
+	 */
+	instance->instancet->disable_intr(instance->reg_set);
+
+	for (i = 0; i < (10 * 1000); i += 20) {
+		if (readl(&instance->reg_set->doorbell) & 1)
+			msleep(20);
+		else
+			break;
+	}
+
+	instance->instancet->fire_cmd(instance, req_desc->u.low,
+				      req_desc->u.high, instance->reg_set);
+
+	wait_and_poll(instance, cmd);
+
+	frame_hdr = &cmd->frame->hdr;
+	if (frame_hdr->cmd_status != 0) {
+		ret = 1;
+		goto fail_fw_init;
+	}
+	printk(KERN_ERR "megasas:IOC Init cmd success\n");
+
+	ret = 0;
+
+fail_fw_init:
+	megasas_return_cmd(instance, cmd);
+	if (IOCInitMessage)
+		dma_free_coherent(&instance->pdev->dev,
+				  sizeof(struct MPI2_IOC_INIT_REQUEST),
+				  IOCInitMessage, ioc_init_handle);
+fail_get_cmd:
+	return ret;
+}
+
+/*
+ * megasas_return_cmd_for_smid -	Returns a cmd_fusion for a SMID
+ * @instance:				Adapter soft state
+ *
+ */
+void
+megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid)
+{
+	struct fusion_context *fusion;
+	struct megasas_cmd_fusion *cmd;
+
+	fusion = instance->ctrl_context;
+	cmd = fusion->cmd_list[smid - 1];
+	megasas_return_cmd_fusion(instance, cmd);
+}
+
+/*
+ * megasas_get_ld_map_info -	Returns FW's ld_map structure
+ * @instance:				Adapter soft state
+ * @pend:				Pend the command or not
+ * Issues an internal command (DCMD) to get the FW's controller PD
+ * list structure.  This information is mainly used to find out SYSTEM
+ * supported by the FW.
+ */
+static int
+megasas_get_ld_map_info(struct megasas_instance *instance)
+{
+	int ret = 0;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	struct MR_FW_RAID_MAP_ALL *ci;
+	dma_addr_t ci_h = 0;
+	u32 size_map_info;
+	struct fusion_context *fusion;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas: Failed to get cmd for map info.\n");
+		return -ENOMEM;
+	}
+
+	fusion = instance->ctrl_context;
+
+	if (!fusion) {
+		megasas_return_cmd(instance, cmd);
+		return 1;
+	}
+
+	dcmd = &cmd->frame->dcmd;
+
+	size_map_info = sizeof(struct MR_FW_RAID_MAP) +
+		(sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
+
+	ci = fusion->ld_map[(instance->map_id & 1)];
+	ci_h = fusion->ld_map_phys[(instance->map_id & 1)];
+
+	if (!ci) {
+		printk(KERN_DEBUG "Failed to alloc mem for ld_map_info\n");
+		megasas_return_cmd(instance, cmd);
+		return -ENOMEM;
+	}
+
+	memset(ci, 0, sizeof(*ci));
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_READ;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = size_map_info;
+	dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
+	dcmd->sgl.sge32[0].phys_addr = ci_h;
+	dcmd->sgl.sge32[0].length = size_map_info;
+
+	if (!megasas_issue_polled(instance, cmd))
+		ret = 0;
+	else {
+		printk(KERN_ERR "megasas: Get LD Map Info Failed\n");
+		ret = -1;
+	}
+
+	megasas_return_cmd(instance, cmd);
+
+	return ret;
+}
+
+u8
+megasas_get_map_info(struct megasas_instance *instance)
+{
+	struct fusion_context *fusion = instance->ctrl_context;
+
+	fusion->fast_path_io = 0;
+	if (!megasas_get_ld_map_info(instance)) {
+		if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)],
+				       fusion->load_balance_info)) {
+			fusion->fast_path_io = 1;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+ * megasas_sync_map_info -	Returns FW's ld_map structure
+ * @instance:				Adapter soft state
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD
+ * list structure.  This information is mainly used to find out SYSTEM
+ * supported by the FW.
+ */
+int
+megasas_sync_map_info(struct megasas_instance *instance)
+{
+	int ret = 0, i;
+	struct megasas_cmd *cmd;
+	struct megasas_dcmd_frame *dcmd;
+	u32 size_sync_info, num_lds;
+	struct fusion_context *fusion;
+	struct MR_LD_TARGET_SYNC *ci = NULL;
+	struct MR_FW_RAID_MAP_ALL *map;
+	struct MR_LD_RAID  *raid;
+	struct MR_LD_TARGET_SYNC *ld_sync;
+	dma_addr_t ci_h = 0;
+	u32 size_map_info;
+
+	cmd = megasas_get_cmd(instance);
+
+	if (!cmd) {
+		printk(KERN_DEBUG "megasas: Failed to get cmd for sync"
+		       "info.\n");
+		return -ENOMEM;
+	}
+
+	fusion = instance->ctrl_context;
+
+	if (!fusion) {
+		megasas_return_cmd(instance, cmd);
+		return 1;
+	}
+
+	map = fusion->ld_map[instance->map_id & 1];
+
+	num_lds = map->raidMap.ldCount;
+
+	dcmd = &cmd->frame->dcmd;
+
+	size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds;
+
+	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+	ci = (struct MR_LD_TARGET_SYNC *)
+	  fusion->ld_map[(instance->map_id - 1) & 1];
+	memset(ci, 0, sizeof(struct MR_FW_RAID_MAP_ALL));
+
+	ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1];
+
+	ld_sync = (struct MR_LD_TARGET_SYNC *)ci;
+
+	for (i = 0; i < num_lds; i++, ld_sync++) {
+		raid = MR_LdRaidGet(i, map);
+		ld_sync->targetId = MR_GetLDTgtId(i, map);
+		ld_sync->seqNum = raid->seqNum;
+	}
+
+	size_map_info = sizeof(struct MR_FW_RAID_MAP) +
+		(sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
+
+	dcmd->cmd = MFI_CMD_DCMD;
+	dcmd->cmd_status = 0xFF;
+	dcmd->sge_count = 1;
+	dcmd->flags = MFI_FRAME_DIR_WRITE;
+	dcmd->timeout = 0;
+	dcmd->pad_0 = 0;
+	dcmd->data_xfer_len = size_map_info;
+	dcmd->mbox.b[0] = num_lds;
+	dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG;
+	dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
+	dcmd->sgl.sge32[0].phys_addr = ci_h;
+	dcmd->sgl.sge32[0].length = size_map_info;
+
+	instance->map_update_cmd = cmd;
+
+	instance->instancet->issue_dcmd(instance, cmd);
+
+	return ret;
+}
+
+/**
+ * megasas_init_adapter_fusion -	Initializes the FW
+ * @instance:		Adapter soft state
+ *
+ * This is the main function for initializing firmware.
+ */
+u32
+megasas_init_adapter_fusion(struct megasas_instance *instance)
+{
+	struct megasas_register_set __iomem *reg_set;
+	struct fusion_context *fusion;
+	u32 max_cmd;
+	int i = 0;
+
+	fusion = instance->ctrl_context;
+
+	reg_set = instance->reg_set;
+
+	/*
+	 * Get various operational parameters from status register
+	 */
+	instance->max_fw_cmds =
+		instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF;
+	instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)1008);
+
+	/*
+	 * Reduce the max supported cmds by 1. This is to ensure that the
+	 * reply_q_sz (1 more than the max cmd that driver may send)
+	 * does not exceed max cmds that the FW can support
+	 */
+	instance->max_fw_cmds = instance->max_fw_cmds-1;
+	/* Only internal cmds (DCMD) need to have MFI frames */
+	instance->max_mfi_cmds = MEGASAS_INT_CMDS;
+
+	max_cmd = instance->max_fw_cmds;
+
+	fusion->reply_q_depth = ((max_cmd + 1 + 15)/16)*16;
+
+	fusion->request_alloc_sz =
+		sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd;
+	fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)
+		*(fusion->reply_q_depth);
+	fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE +
+		(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE *
+		 (max_cmd + 1)); /* Extra 1 for SMID 0 */
+
+	fusion->max_sge_in_main_msg =
+	  (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
+	   offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
+
+	fusion->max_sge_in_chain =
+		MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION);
+
+	instance->max_num_sge = fusion->max_sge_in_main_msg +
+		fusion->max_sge_in_chain - 2;
+
+	/* Used for pass thru MFI frame (DCMD) */
+	fusion->chain_offset_mfi_pthru =
+		offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16;
+
+	fusion->chain_offset_io_request =
+		(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
+		 sizeof(union MPI2_SGE_IO_UNION))/16;
+
+	fusion->last_reply_idx = 0;
+
+	/*
+	 * Allocate memory for descriptors
+	 * Create a pool of commands
+	 */
+	if (megasas_alloc_cmds(instance))
+		goto fail_alloc_mfi_cmds;
+	if (megasas_alloc_cmds_fusion(instance))
+		goto fail_alloc_cmds;
+
+	if (megasas_ioc_init_fusion(instance))
+		goto fail_ioc_init;
+
+	instance->flag_ieee = 1;
+
+	fusion->map_sz =  sizeof(struct MR_FW_RAID_MAP) +
+	  (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
+
+	fusion->fast_path_io = 0;
+
+	for (i = 0; i < 2; i++) {
+		fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
+						       fusion->map_sz,
+						       &fusion->ld_map_phys[i],
+						       GFP_KERNEL);
+		if (!fusion->ld_map[i]) {
+			printk(KERN_ERR "megasas: Could not allocate memory "
+			       "for map info\n");
+			goto fail_map_info;
+		}
+	}
+
+	if (!megasas_get_map_info(instance))
+		megasas_sync_map_info(instance);
+
+	return 0;
+
+fail_alloc_cmds:
+fail_alloc_mfi_cmds:
+fail_map_info:
+	if (i == 1)
+		dma_free_coherent(&instance->pdev->dev, fusion->map_sz,
+				  fusion->ld_map[0], fusion->ld_map_phys[0]);
+fail_ioc_init:
+	return 1;
+}
+
+/**
+ * megasas_fire_cmd_fusion -	Sends command to the FW
+ * @frame_phys_addr :		Physical address of cmd
+ * @frame_count :		Number of frames for the command
+ * @regs :			MFI register set
+ */
+void
+megasas_fire_cmd_fusion(struct megasas_instance *instance,
+			dma_addr_t req_desc_lo,
+			u32 req_desc_hi,
+			struct megasas_register_set __iomem *regs)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+
+	writel(req_desc_lo,
+	       &(regs)->inbound_low_queue_port);
+	writel(req_desc_hi, &(regs)->inbound_high_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * map_cmd_status -	Maps FW cmd status to OS cmd status
+ * @cmd :		Pointer to cmd
+ * @status :		status of cmd returned by FW
+ * @ext_status :	ext status of cmd returned by FW
+ */
+
+void
+map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status)
+{
+
+	switch (status) {
+
+	case MFI_STAT_OK:
+		cmd->scmd->result = DID_OK << 16;
+		break;
+
+	case MFI_STAT_SCSI_IO_FAILED:
+	case MFI_STAT_LD_INIT_IN_PROGRESS:
+		cmd->scmd->result = (DID_ERROR << 16) | ext_status;
+		break;
+
+	case MFI_STAT_SCSI_DONE_WITH_ERROR:
+
+		cmd->scmd->result = (DID_OK << 16) | ext_status;
+		if (ext_status == SAM_STAT_CHECK_CONDITION) {
+			memset(cmd->scmd->sense_buffer, 0,
+			       SCSI_SENSE_BUFFERSIZE);
+			memcpy(cmd->scmd->sense_buffer, cmd->sense,
+			       SCSI_SENSE_BUFFERSIZE);
+			cmd->scmd->result |= DRIVER_SENSE << 24;
+		}
+		break;
+
+	case MFI_STAT_LD_OFFLINE:
+	case MFI_STAT_DEVICE_NOT_FOUND:
+		cmd->scmd->result = DID_BAD_TARGET << 16;
+		break;
+
+	default:
+		printk(KERN_DEBUG "megasas: FW status %#x\n", status);
+		cmd->scmd->result = DID_ERROR << 16;
+		break;
+	}
+}
+
+/**
+ * megasas_make_sgl_fusion -	Prepares 32-bit SGL
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command from the mid-layer
+ * @sgl_ptr:		SGL to be filled in
+ * @cmd:		cmd we are working on
+ *
+ * If successful, this function returns the number of SG elements.
+ */
+static int
+megasas_make_sgl_fusion(struct megasas_instance *instance,
+			struct scsi_cmnd *scp,
+			struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr,
+			struct megasas_cmd_fusion *cmd)
+{
+	int i, sg_processed;
+	int sge_count, sge_idx;
+	struct scatterlist *os_sgl;
+	struct fusion_context *fusion;
+
+	fusion = instance->ctrl_context;
+
+	cmd->io_request->ChainOffset = 0;
+
+	sge_count = scsi_dma_map(scp);
+
+	BUG_ON(sge_count < 0);
+
+	if (sge_count > instance->max_num_sge || !sge_count)
+		return sge_count;
+
+	if (sge_count > fusion->max_sge_in_main_msg) {
+		/* One element to store the chain info */
+		sge_idx = fusion->max_sge_in_main_msg - 1;
+	} else
+		sge_idx = sge_count;
+
+	scsi_for_each_sg(scp, os_sgl, sge_count, i) {
+		sgl_ptr->Length = sg_dma_len(os_sgl);
+		sgl_ptr->Address = sg_dma_address(os_sgl);
+		sgl_ptr->Flags = 0;
+		sgl_ptr++;
+
+		sg_processed = i + 1;
+
+		if ((sg_processed ==  (fusion->max_sge_in_main_msg - 1)) &&
+		    (sge_count > fusion->max_sge_in_main_msg)) {
+
+			struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
+			cmd->io_request->ChainOffset =
+				fusion->chain_offset_io_request;
+			sg_chain = sgl_ptr;
+			/* Prepare chain element */
+			sg_chain->NextChainOffset = 0;
+			sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+					   MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
+			sg_chain->Length =  (sizeof(union MPI2_SGE_IO_UNION)
+					     *(sge_count - sg_processed));
+			sg_chain->Address = cmd->sg_frame_phys_addr;
+
+			sgl_ptr =
+			  (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
+		}
+	}
+
+	return sge_count;
+}
+
+/**
+ * megasas_set_pd_lba -	Sets PD LBA
+ * @cdb:		CDB
+ * @cdb_len:		cdb length
+ * @start_blk:		Start block of IO
+ *
+ * Used to set the PD LBA in CDB for FP IOs
+ */
+void
+megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
+		   struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
+		   struct MR_FW_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
+{
+	struct MR_LD_RAID *raid;
+	u32 ld;
+	u64 start_blk = io_info->pdBlock;
+	u8 *cdb = io_request->CDB.CDB32;
+	u32 num_blocks = io_info->numBlocks;
+	u8 opcode, flagvals, groupnum, control;
+
+	/* Check if T10 PI (DIF) is enabled for this LD */
+	ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
+	raid = MR_LdRaidGet(ld, local_map_ptr);
+	if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
+		memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+		cdb[0] =  MEGASAS_SCSI_VARIABLE_LENGTH_CMD;
+		cdb[7] =  MEGASAS_SCSI_ADDL_CDB_LEN;
+
+		if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+			cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32;
+		else
+			cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32;
+		cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL;
+
+		/* LBA */
+		cdb[12] = (u8)((start_blk >> 56) & 0xff);
+		cdb[13] = (u8)((start_blk >> 48) & 0xff);
+		cdb[14] = (u8)((start_blk >> 40) & 0xff);
+		cdb[15] = (u8)((start_blk >> 32) & 0xff);
+		cdb[16] = (u8)((start_blk >> 24) & 0xff);
+		cdb[17] = (u8)((start_blk >> 16) & 0xff);
+		cdb[18] = (u8)((start_blk >> 8) & 0xff);
+		cdb[19] = (u8)(start_blk & 0xff);
+
+		/* Logical block reference tag */
+		io_request->CDB.EEDP32.PrimaryReferenceTag =
+			cpu_to_be32(ref_tag);
+		io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
+
+		io_request->DataLength = num_blocks * 512;
+		io_request->IoFlags = 32; /* Specify 32-byte cdb */
+
+		/* Transfer length */
+		cdb[28] = (u8)((num_blocks >> 24) & 0xff);
+		cdb[29] = (u8)((num_blocks >> 16) & 0xff);
+		cdb[30] = (u8)((num_blocks >> 8) & 0xff);
+		cdb[31] = (u8)(num_blocks & 0xff);
+
+		/* set SCSI IO EEDPFlags */
+		if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) {
+			io_request->EEDPFlags =
+				MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG  |
+				MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
+				MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
+				MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
+				MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
+		} else {
+			io_request->EEDPFlags =
+				MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
+				MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
+		}
+		io_request->Control |= (0x4 << 26);
+		io_request->EEDPBlockSize = MEGASAS_EEDPBLOCKSIZE;
+	} else {
+		/* Some drives don't support 16/12 byte CDB's, convert to 10 */
+		if (((cdb_len == 12) || (cdb_len == 16)) &&
+		    (start_blk <= 0xffffffff)) {
+			if (cdb_len == 16) {
+				opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
+				flagvals = cdb[1];
+				groupnum = cdb[14];
+				control = cdb[15];
+			} else {
+				opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
+				flagvals = cdb[1];
+				groupnum = cdb[10];
+				control = cdb[11];
+			}
+
+			memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+
+			cdb[0] = opcode;
+			cdb[1] = flagvals;
+			cdb[6] = groupnum;
+			cdb[9] = control;
+
+			/* Transfer length */
+			cdb[8] = (u8)(num_blocks & 0xff);
+			cdb[7] = (u8)((num_blocks >> 8) & 0xff);
+
+			cdb_len = 10;
+		}
+
+		/* Normal case, just load LBA here */
+		switch (cdb_len) {
+		case 6:
+		{
+			u8 val = cdb[1] & 0xE0;
+			cdb[3] = (u8)(start_blk & 0xff);
+			cdb[2] = (u8)((start_blk >> 8) & 0xff);
+			cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f);
+			break;
+		}
+		case 10:
+			cdb[5] = (u8)(start_blk & 0xff);
+			cdb[4] = (u8)((start_blk >> 8) & 0xff);
+			cdb[3] = (u8)((start_blk >> 16) & 0xff);
+			cdb[2] = (u8)((start_blk >> 24) & 0xff);
+			break;
+		case 12:
+			cdb[5]    = (u8)(start_blk & 0xff);
+			cdb[4]    = (u8)((start_blk >> 8) & 0xff);
+			cdb[3]    = (u8)((start_blk >> 16) & 0xff);
+			cdb[2]    = (u8)((start_blk >> 24) & 0xff);
+			break;
+		case 16:
+			cdb[9]    = (u8)(start_blk & 0xff);
+			cdb[8]    = (u8)((start_blk >> 8) & 0xff);
+			cdb[7]    = (u8)((start_blk >> 16) & 0xff);
+			cdb[6]    = (u8)((start_blk >> 24) & 0xff);
+			cdb[5]    = (u8)((start_blk >> 32) & 0xff);
+			cdb[4]    = (u8)((start_blk >> 40) & 0xff);
+			cdb[3]    = (u8)((start_blk >> 48) & 0xff);
+			cdb[2]    = (u8)((start_blk >> 56) & 0xff);
+			break;
+		}
+	}
+}
+
+/**
+ * megasas_build_ldio_fusion -	Prepares IOs to devices
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command
+ * @cmd:		Command to be prepared
+ *
+ * Prepares the io_request and chain elements (sg_frame) for IO
+ * The IO can be for PD (Fast Path) or LD
+ */
+void
+megasas_build_ldio_fusion(struct megasas_instance *instance,
+			  struct scsi_cmnd *scp,
+			  struct megasas_cmd_fusion *cmd)
+{
+	u8 fp_possible;
+	u32 start_lba_lo, start_lba_hi, device_id;
+	struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
+	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+	struct IO_REQUEST_INFO io_info;
+	struct fusion_context *fusion;
+	struct MR_FW_RAID_MAP_ALL *local_map_ptr;
+
+	device_id = MEGASAS_DEV_INDEX(instance, scp);
+
+	fusion = instance->ctrl_context;
+
+	io_request = cmd->io_request;
+	io_request->RaidContext.VirtualDiskTgtId = device_id;
+	io_request->RaidContext.status = 0;
+	io_request->RaidContext.exStatus = 0;
+
+	req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc;
+
+	start_lba_lo = 0;
+	start_lba_hi = 0;
+	fp_possible = 0;
+
+	/*
+	 * 6-byte READ(0x08) or WRITE(0x0A) cdb
+	 */
+	if (scp->cmd_len == 6) {
+		io_request->DataLength = (u32) scp->cmnd[4];
+		start_lba_lo = ((u32) scp->cmnd[1] << 16) |
+			((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3];
+
+		start_lba_lo &= 0x1FFFFF;
+	}
+
+	/*
+	 * 10-byte READ(0x28) or WRITE(0x2A) cdb
+	 */
+	else if (scp->cmd_len == 10) {
+		io_request->DataLength = (u32) scp->cmnd[8] |
+			((u32) scp->cmnd[7] << 8);
+		start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+			((u32) scp->cmnd[3] << 16) |
+			((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+	}
+
+	/*
+	 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
+	 */
+	else if (scp->cmd_len == 12) {
+		io_request->DataLength = ((u32) scp->cmnd[6] << 24) |
+			((u32) scp->cmnd[7] << 16) |
+			((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+		start_lba_lo = ((u32) scp->cmnd[2] << 24) |
+			((u32) scp->cmnd[3] << 16) |
+			((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+	}
+
+	/*
+	 * 16-byte READ(0x88) or WRITE(0x8A) cdb
+	 */
+	else if (scp->cmd_len == 16) {
+		io_request->DataLength = ((u32) scp->cmnd[10] << 24) |
+			((u32) scp->cmnd[11] << 16) |
+			((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13];
+		start_lba_lo = ((u32) scp->cmnd[6] << 24) |
+			((u32) scp->cmnd[7] << 16) |
+			((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9];
+
+		start_lba_hi = ((u32) scp->cmnd[2] << 24) |
+			((u32) scp->cmnd[3] << 16) |
+			((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5];
+	}
+
+	memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
+	io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo;
+	io_info.numBlocks = io_request->DataLength;
+	io_info.ldTgtId = device_id;
+
+	if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+		io_info.isRead = 1;
+
+	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
+
+	if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >=
+	     MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) {
+		io_request->RaidContext.regLockFlags  = 0;
+		fp_possible = 0;
+	} else {
+		if (MR_BuildRaidContext(&io_info, &io_request->RaidContext,
+					local_map_ptr))
+			fp_possible = io_info.fpOkForIo;
+	}
+
+	if (fp_possible) {
+		megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
+				   local_map_ptr, start_lba_lo);
+		io_request->DataLength = scsi_bufflen(scp);
+		io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+		cmd->request_desc->SCSIIO.RequestFlags =
+			(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
+			 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+		if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
+		    (io_info.isRead)) {
+			io_info.devHandle =
+				get_updated_dev_handle(
+					&fusion->load_balance_info[device_id],
+					&io_info);
+			scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG;
+		} else
+			scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
+		cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
+		io_request->DevHandle = io_info.devHandle;
+	} else {
+		io_request->RaidContext.timeoutValue =
+			local_map_ptr->raidMap.fpPdIoTimeoutSec;
+		io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
+		io_request->DevHandle = device_id;
+		cmd->request_desc->SCSIIO.RequestFlags =
+			(MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
+			 << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+	} /* Not FP */
+}
+
+/**
+ * megasas_build_dcdb_fusion -	Prepares IOs to devices
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command
+ * @cmd:		Command to be prepared
+ *
+ * Prepares the io_request frame for non-io cmds
+ */
+static void
+megasas_build_dcdb_fusion(struct megasas_instance *instance,
+			  struct scsi_cmnd *scmd,
+			  struct megasas_cmd_fusion *cmd)
+{
+	u32 device_id;
+	struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
+	u16 pd_index = 0;
+	struct MR_FW_RAID_MAP_ALL *local_map_ptr;
+	struct fusion_context *fusion = instance->ctrl_context;
+
+	io_request = cmd->io_request;
+	device_id = MEGASAS_DEV_INDEX(instance, scmd);
+	pd_index = (scmd->device->channel * MEGASAS_MAX_DEV_PER_CHANNEL)
+		+scmd->device->id;
+	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
+
+	/* Check if this is a system PD I/O */
+	if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
+	    (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
+		io_request->Function = 0;
+		io_request->DevHandle =
+			local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+		io_request->RaidContext.timeoutValue =
+			local_map_ptr->raidMap.fpPdIoTimeoutSec;
+		io_request->RaidContext.regLockFlags = 0;
+		io_request->RaidContext.regLockRowLBA = 0;
+		io_request->RaidContext.regLockLength = 0;
+		io_request->RaidContext.RAIDFlags =
+			MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD <<
+			MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
+		cmd->request_desc->SCSIIO.RequestFlags =
+			(MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
+			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+	} else {
+		io_request->Function  = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
+		io_request->DevHandle = device_id;
+		cmd->request_desc->SCSIIO.RequestFlags =
+			(MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
+			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+	}
+	io_request->RaidContext.VirtualDiskTgtId = device_id;
+	io_request->LUN[0] = scmd->device->lun;
+	io_request->DataLength = scsi_bufflen(scmd);
+}
+
+/**
+ * megasas_build_io_fusion -	Prepares IOs to devices
+ * @instance:		Adapter soft state
+ * @scp:		SCSI command
+ * @cmd:		Command to be prepared
+ *
+ * Invokes helper functions to prepare request frames
+ * and sets flags appropriate for IO/Non-IO cmd
+ */
+int
+megasas_build_io_fusion(struct megasas_instance *instance,
+			struct scsi_cmnd *scp,
+			struct megasas_cmd_fusion *cmd)
+{
+	u32 device_id, sge_count;
+	struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
+
+	device_id = MEGASAS_DEV_INDEX(instance, scp);
+
+	/* Zero out some fields so they don't get reused */
+	io_request->LUN[0] = 0;
+	io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
+	io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
+	io_request->EEDPFlags = 0;
+	io_request->Control = 0;
+	io_request->EEDPBlockSize = 0;
+	io_request->IoFlags = 0;
+	io_request->RaidContext.RAIDFlags = 0;
+
+	memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
+	/*
+	 * Just the CDB length,rest of the Flags are zero
+	 * This will be modified for FP in build_ldio_fusion
+	 */
+	io_request->IoFlags = scp->cmd_len;
+
+	if (megasas_is_ldio(scp))
+		megasas_build_ldio_fusion(instance, scp, cmd);
+	else
+		megasas_build_dcdb_fusion(instance, scp, cmd);
+
+	/*
+	 * Construct SGL
+	 */
+
+	sge_count =
+		megasas_make_sgl_fusion(instance, scp,
+					(struct MPI25_IEEE_SGE_CHAIN64 *)
+					&io_request->SGL, cmd);
+
+	if (sge_count > instance->max_num_sge) {
+		printk(KERN_ERR "megasas: Error. sge_count (0x%x) exceeds "
+		       "max (0x%x) allowed\n", sge_count,
+		       instance->max_num_sge);
+		return 1;
+	}
+
+	io_request->RaidContext.numSGE = sge_count;
+
+	io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
+
+	if (scp->sc_data_direction == PCI_DMA_TODEVICE)
+		io_request->Control |= MPI2_SCSIIO_CONTROL_WRITE;
+	else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
+		io_request->Control |= MPI2_SCSIIO_CONTROL_READ;
+
+	io_request->SGLOffset0 =
+		offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4;
+
+	io_request->SenseBufferLowAddress = cmd->sense_phys_addr;
+	io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
+
+	cmd->scmd = scp;
+	scp->SCp.ptr = (char *)cmd;
+
+	return 0;
+}
+
+union MEGASAS_REQUEST_DESCRIPTOR_UNION *
+megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
+{
+	u8 *p;
+	struct fusion_context *fusion;
+
+	if (index >= instance->max_fw_cmds) {
+		printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for "
+		       "descriptor\n", index);
+		return NULL;
+	}
+	fusion = instance->ctrl_context;
+	p = fusion->req_frames_desc
+		+sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index;
+
+	return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p;
+}
+
+/**
+ * megasas_build_and_issue_cmd_fusion -Main routine for building and
+ *                                     issuing non IOCTL cmd
+ * @instance:			Adapter soft state
+ * @scmd:			pointer to scsi cmd from OS
+ */
+static u32
+megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
+				   struct scsi_cmnd *scmd)
+{
+	struct megasas_cmd_fusion *cmd;
+	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+	u32 index;
+	struct fusion_context *fusion;
+
+	fusion = instance->ctrl_context;
+
+	cmd = megasas_get_cmd_fusion(instance);
+	if (!cmd)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	index = cmd->index;
+
+	req_desc = megasas_get_request_descriptor(instance, index-1);
+	if (!req_desc)
+		return 1;
+
+	req_desc->Words = 0;
+	cmd->request_desc = req_desc;
+	cmd->request_desc->Words = 0;
+
+	if (megasas_build_io_fusion(instance, scmd, cmd)) {
+		megasas_return_cmd_fusion(instance, cmd);
+		printk(KERN_ERR "megasas: Error building command.\n");
+		cmd->request_desc = NULL;
+		return 1;
+	}
+
+	req_desc = cmd->request_desc;
+	req_desc->SCSIIO.SMID = index;
+
+	if (cmd->io_request->ChainOffset != 0 &&
+	    cmd->io_request->ChainOffset != 0xF)
+		printk(KERN_ERR "megasas: The chain offset value is not "
+		       "correct : %x\n", cmd->io_request->ChainOffset);
+
+	/*
+	 * Issue the command to the FW
+	 */
+	atomic_inc(&instance->fw_outstanding);
+
+	instance->instancet->fire_cmd(instance,
+				      req_desc->u.low, req_desc->u.high,
+				      instance->reg_set);
+
+	return 0;
+}
+
+/**
+ * complete_cmd_fusion -	Completes command
+ * @instance:			Adapter soft state
+ * Completes all commands that is in reply descriptor queue
+ */
+int
+complete_cmd_fusion(struct megasas_instance *instance)
+{
+	union MPI2_REPLY_DESCRIPTORS_UNION *desc;
+	struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
+	struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req;
+	struct fusion_context *fusion;
+	struct megasas_cmd *cmd_mfi;
+	struct megasas_cmd_fusion *cmd_fusion;
+	u16 smid, num_completed;
+	u8 reply_descript_type, arm;
+	u32 status, extStatus, device_id;
+	union desc_value d_val;
+	struct LD_LOAD_BALANCE_INFO *lbinfo;
+
+	fusion = instance->ctrl_context;
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return IRQ_HANDLED;
+
+	desc = fusion->reply_frames_desc;
+	desc += fusion->last_reply_idx;
+
+	reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
+
+	d_val.word = desc->Words;
+
+	reply_descript_type = reply_desc->ReplyFlags &
+		MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+
+	if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+		return IRQ_NONE;
+
+	d_val.word = desc->Words;
+
+	num_completed = 0;
+
+	while ((d_val.u.low != UINT_MAX) && (d_val.u.high != UINT_MAX)) {
+		smid = reply_desc->SMID;
+
+		cmd_fusion = fusion->cmd_list[smid - 1];
+
+		scsi_io_req =
+			(struct MPI2_RAID_SCSI_IO_REQUEST *)
+		  cmd_fusion->io_request;
+
+		if (cmd_fusion->scmd)
+			cmd_fusion->scmd->SCp.ptr = NULL;
+
+		status = scsi_io_req->RaidContext.status;
+		extStatus = scsi_io_req->RaidContext.exStatus;
+
+		switch (scsi_io_req->Function) {
+		case MPI2_FUNCTION_SCSI_IO_REQUEST:  /*Fast Path IO.*/
+			/* Update load balancing info */
+			device_id = MEGASAS_DEV_INDEX(instance,
+						      cmd_fusion->scmd);
+			lbinfo = &fusion->load_balance_info[device_id];
+			if (cmd_fusion->scmd->SCp.Status &
+			    MEGASAS_LOAD_BALANCE_FLAG) {
+				arm = lbinfo->raid1DevHandle[0] ==
+					cmd_fusion->io_request->DevHandle ? 0 :
+					1;
+				atomic_dec(&lbinfo->scsi_pending_cmds[arm]);
+				cmd_fusion->scmd->SCp.Status &=
+					~MEGASAS_LOAD_BALANCE_FLAG;
+			}
+			if (reply_descript_type ==
+			    MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
+				if (megasas_dbg_lvl == 5)
+					printk(KERN_ERR "\nmegasas: FAST Path "
+					       "IO Success\n");
+			}
+			/* Fall thru and complete IO */
+		case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
+			/* Map the FW Cmd Status */
+			map_cmd_status(cmd_fusion, status, extStatus);
+			scsi_dma_unmap(cmd_fusion->scmd);
+			cmd_fusion->scmd->scsi_done(cmd_fusion->scmd);
+			scsi_io_req->RaidContext.status = 0;
+			scsi_io_req->RaidContext.exStatus = 0;
+			megasas_return_cmd_fusion(instance, cmd_fusion);
+			atomic_dec(&instance->fw_outstanding);
+
+			break;
+		case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */
+			cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
+			megasas_complete_cmd(instance, cmd_mfi, DID_OK);
+			cmd_fusion->flags = 0;
+			megasas_return_cmd_fusion(instance, cmd_fusion);
+
+			break;
+		}
+
+		fusion->last_reply_idx++;
+		if (fusion->last_reply_idx >= fusion->reply_q_depth)
+			fusion->last_reply_idx = 0;
+
+		desc->Words = ULLONG_MAX;
+		num_completed++;
+
+		/* Get the next reply descriptor */
+		if (!fusion->last_reply_idx)
+			desc = fusion->reply_frames_desc;
+		else
+			desc++;
+
+		reply_desc =
+		  (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
+
+		d_val.word = desc->Words;
+
+		reply_descript_type = reply_desc->ReplyFlags &
+			MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+
+		if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+			break;
+	}
+
+	if (!num_completed)
+		return IRQ_NONE;
+
+	wmb();
+	writel(fusion->last_reply_idx,
+	       &instance->reg_set->reply_post_host_index);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * megasas_complete_cmd_dpc_fusion -	Completes command
+ * @instance:			Adapter soft state
+ *
+ * Tasklet to complete cmds
+ */
+void
+megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
+{
+	struct megasas_instance *instance =
+		(struct megasas_instance *)instance_addr;
+	unsigned long flags;
+
+	/* If we have already declared adapter dead, donot complete cmds */
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	spin_lock_irqsave(&instance->completion_lock, flags);
+	complete_cmd_fusion(instance);
+	spin_unlock_irqrestore(&instance->completion_lock, flags);
+}
+
+/**
+ * megasas_isr_fusion - isr entry point
+ */
+irqreturn_t megasas_isr_fusion(int irq, void *devp)
+{
+	struct megasas_instance *instance = (struct megasas_instance *)devp;
+	u32 mfiStatus, fw_state;
+
+	if (!instance->msi_flag) {
+		mfiStatus = instance->instancet->clear_intr(instance->reg_set);
+		if (!mfiStatus)
+			return IRQ_NONE;
+	}
+
+	/* If we are resetting, bail */
+	if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags))
+		return IRQ_HANDLED;
+
+	if (!complete_cmd_fusion(instance)) {
+		/* If we didn't complete any commands, check for FW fault */
+		fw_state = instance->instancet->read_fw_status_reg(
+			instance->reg_set) & MFI_STATE_MASK;
+		if (fw_state == MFI_STATE_FAULT)
+			schedule_work(&instance->work_init);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru
+ * @instance:			Adapter soft state
+ * mfi_cmd:			megasas_cmd pointer
+ *
+ */
+u8
+build_mpt_mfi_pass_thru(struct megasas_instance *instance,
+			struct megasas_cmd *mfi_cmd)
+{
+	struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
+	struct MPI2_RAID_SCSI_IO_REQUEST *io_req;
+	struct megasas_cmd_fusion *cmd;
+	struct fusion_context *fusion;
+	struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr;
+
+	cmd = megasas_get_cmd_fusion(instance);
+	if (!cmd)
+		return 1;
+
+	/*  Save the smid. To be used for returning the cmd */
+	mfi_cmd->context.smid = cmd->index;
+
+	cmd->sync_cmd_idx = mfi_cmd->index;
+
+	/*
+	 * For cmds where the flag is set, store the flag and check
+	 * on completion. For cmds with this flag, don't call
+	 * megasas_complete_cmd
+	 */
+
+	if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
+		cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+	fusion = instance->ctrl_context;
+	io_req = cmd->io_request;
+	mpi25_ieee_chain =
+	  (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
+
+	io_req->Function    = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
+	io_req->SGLOffset0  = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST,
+				       SGL) / 4;
+	io_req->ChainOffset = fusion->chain_offset_mfi_pthru;
+
+	mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr;
+
+	mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+		MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
+
+	mpi25_ieee_chain->Length = MEGASAS_MAX_SZ_CHAIN_FRAME;
+
+	return 0;
+}
+
+/**
+ * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd
+ * @instance:			Adapter soft state
+ * @cmd:			mfi cmd to build
+ *
+ */
+union MEGASAS_REQUEST_DESCRIPTOR_UNION *
+build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+	u16 index;
+
+	if (build_mpt_mfi_pass_thru(instance, cmd)) {
+		printk(KERN_ERR "Couldn't build MFI pass thru cmd\n");
+		return NULL;
+	}
+
+	index = cmd->context.smid;
+
+	req_desc = megasas_get_request_descriptor(instance, index - 1);
+
+	if (!req_desc)
+		return NULL;
+
+	req_desc->Words = 0;
+	req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
+					 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+
+	req_desc->SCSIIO.SMID = index;
+
+	return req_desc;
+}
+
+/**
+ * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd
+ * @instance:			Adapter soft state
+ * @cmd:			mfi cmd pointer
+ *
+ */
+void
+megasas_issue_dcmd_fusion(struct megasas_instance *instance,
+			  struct megasas_cmd *cmd)
+{
+	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+	union desc_value d_val;
+
+	req_desc = build_mpt_cmd(instance, cmd);
+	if (!req_desc) {
+		printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n");
+		return;
+	}
+	d_val.word = req_desc->Words;
+
+	instance->instancet->fire_cmd(instance, req_desc->u.low,
+				      req_desc->u.high, instance->reg_set);
+}
+
+/**
+ * megasas_release_fusion -	Reverses the FW initialization
+ * @intance:			Adapter soft state
+ */
+void
+megasas_release_fusion(struct megasas_instance *instance)
+{
+	megasas_free_cmds(instance);
+	megasas_free_cmds_fusion(instance);
+
+	iounmap(instance->reg_set);
+
+	pci_release_selected_regions(instance->pdev, instance->bar);
+}
+
+/**
+ * megasas_read_fw_status_reg_fusion - returns the current FW status value
+ * @regs:			MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs)
+{
+	return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_adp_reset_fusion -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_fusion(struct megasas_instance *instance,
+			 struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_fusion -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_fusion(struct megasas_instance *instance,
+			   struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+/* This function waits for outstanding commands on fusion to complete */
+int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
+{
+	int i, outstanding, retval = 0;
+	u32 fw_state, wait_time = MEGASAS_RESET_WAIT_TIME;
+
+	for (i = 0; i < wait_time; i++) {
+		/* Check if firmware is in fault state */
+		fw_state = instance->instancet->read_fw_status_reg(
+			instance->reg_set) & MFI_STATE_MASK;
+		if (fw_state == MFI_STATE_FAULT) {
+			printk(KERN_WARNING "megasas: Found FW in FAULT state,"
+			       " will reset adapter.\n");
+			retval = 1;
+			goto out;
+		}
+
+		outstanding = atomic_read(&instance->fw_outstanding);
+		if (!outstanding)
+			goto out;
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
+			       "commands to complete\n", i, outstanding);
+			megasas_complete_cmd_dpc_fusion(
+				(unsigned long)instance);
+		}
+		msleep(1000);
+	}
+
+	if (atomic_read(&instance->fw_outstanding)) {
+		printk("megaraid_sas: pending commands remain after waiting, "
+		       "will reset adapter.\n");
+		retval = 1;
+	}
+out:
+	return retval;
+}
+
+void  megasas_reset_reply_desc(struct megasas_instance *instance)
+{
+	int i;
+	struct fusion_context *fusion;
+	union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
+
+	fusion = instance->ctrl_context;
+	fusion->last_reply_idx = 0;
+	reply_desc = fusion->reply_frames_desc;
+	for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++)
+		reply_desc->Words = ULLONG_MAX;
+}
+
+/* Core fusion reset function */
+int megasas_reset_fusion(struct Scsi_Host *shost)
+{
+	int retval = SUCCESS, i, j, retry = 0;
+	struct megasas_instance *instance;
+	struct megasas_cmd_fusion *cmd_fusion;
+	struct fusion_context *fusion;
+	struct megasas_cmd *cmd_mfi;
+	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+	u32 host_diag, abs_state;
+
+	instance = (struct megasas_instance *)shost->hostdata;
+	fusion = instance->ctrl_context;
+
+	mutex_lock(&instance->reset_mutex);
+	set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
+	instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
+	instance->instancet->disable_intr(instance->reg_set);
+	msleep(1000);
+
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		printk(KERN_WARNING "megaraid_sas: Hardware critical error, "
+		       "returning FAILED.\n");
+		retval = FAILED;
+		goto out;
+	}
+
+	/* First try waiting for commands to complete */
+	if (megasas_wait_for_outstanding_fusion(instance)) {
+		printk(KERN_WARNING "megaraid_sas: resetting fusion "
+		       "adapter.\n");
+		/* Now return commands back to the OS */
+		for (i = 0 ; i < instance->max_fw_cmds; i++) {
+			cmd_fusion = fusion->cmd_list[i];
+			if (cmd_fusion->scmd) {
+				scsi_dma_unmap(cmd_fusion->scmd);
+				cmd_fusion->scmd->result = (DID_RESET << 16);
+				cmd_fusion->scmd->scsi_done(cmd_fusion->scmd);
+				megasas_return_cmd_fusion(instance, cmd_fusion);
+				atomic_dec(&instance->fw_outstanding);
+			}
+		}
+
+		if (instance->disableOnlineCtrlReset == 1) {
+			/* Reset not supported, kill adapter */
+			printk(KERN_WARNING "megaraid_sas: Reset not supported"
+			       ", killing adapter.\n");
+			megaraid_sas_kill_hba(instance);
+			instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
+			retval = FAILED;
+			goto out;
+		}
+
+		/* Now try to reset the chip */
+		for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
+			writel(MPI2_WRSEQ_FLUSH_KEY_VALUE,
+			       &instance->reg_set->fusion_seq_offset);
+			writel(MPI2_WRSEQ_1ST_KEY_VALUE,
+			       &instance->reg_set->fusion_seq_offset);
+			writel(MPI2_WRSEQ_2ND_KEY_VALUE,
+			       &instance->reg_set->fusion_seq_offset);
+			writel(MPI2_WRSEQ_3RD_KEY_VALUE,
+			       &instance->reg_set->fusion_seq_offset);
+			writel(MPI2_WRSEQ_4TH_KEY_VALUE,
+			       &instance->reg_set->fusion_seq_offset);
+			writel(MPI2_WRSEQ_5TH_KEY_VALUE,
+			       &instance->reg_set->fusion_seq_offset);
+			writel(MPI2_WRSEQ_6TH_KEY_VALUE,
+			       &instance->reg_set->fusion_seq_offset);
+
+			/* Check that the diag write enable (DRWE) bit is on */
+			host_diag = readl(&instance->reg_set->fusion_host_diag);
+			while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
+				msleep(100);
+				host_diag =
+				readl(&instance->reg_set->fusion_host_diag);
+				if (retry++ == 100) {
+					printk(KERN_WARNING "megaraid_sas: "
+					       "Host diag unlock failed!\n");
+					break;
+				}
+			}
+			if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
+				continue;
+
+			/* Send chip reset command */
+			writel(host_diag | HOST_DIAG_RESET_ADAPTER,
+			       &instance->reg_set->fusion_host_diag);
+			msleep(3000);
+
+			/* Make sure reset adapter bit is cleared */
+			host_diag = readl(&instance->reg_set->fusion_host_diag);
+			retry = 0;
+			while (host_diag & HOST_DIAG_RESET_ADAPTER) {
+				msleep(100);
+				host_diag =
+				readl(&instance->reg_set->fusion_host_diag);
+				if (retry++ == 1000) {
+					printk(KERN_WARNING "megaraid_sas: "
+					       "Diag reset adapter never "
+					       "cleared!\n");
+					break;
+				}
+			}
+			if (host_diag & HOST_DIAG_RESET_ADAPTER)
+				continue;
+
+			abs_state =
+				instance->instancet->read_fw_status_reg(
+					instance->reg_set);
+			retry = 0;
+
+			while ((abs_state <= MFI_STATE_FW_INIT) &&
+			       (retry++ < 1000)) {
+				msleep(100);
+				abs_state =
+				instance->instancet->read_fw_status_reg(
+					instance->reg_set);
+			}
+			if (abs_state <= MFI_STATE_FW_INIT) {
+				printk(KERN_WARNING "megaraid_sas: firmware "
+				       "state < MFI_STATE_FW_INIT, state = "
+				       "0x%x\n", abs_state);
+				continue;
+			}
+
+			/* Wait for FW to become ready */
+			if (megasas_transition_to_ready(instance)) {
+				printk(KERN_WARNING "megaraid_sas: Failed to "
+				       "transition controller to ready.\n");
+				continue;
+			}
+
+			megasas_reset_reply_desc(instance);
+			if (megasas_ioc_init_fusion(instance)) {
+				printk(KERN_WARNING "megaraid_sas: "
+				       "megasas_ioc_init_fusion() failed!\n");
+				continue;
+			}
+
+			instance->instancet->enable_intr(instance->reg_set);
+			instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+
+			/* Re-fire management commands */
+			for (j = 0 ; j < instance->max_fw_cmds; j++) {
+				cmd_fusion = fusion->cmd_list[j];
+				if (cmd_fusion->sync_cmd_idx !=
+				    (u32)ULONG_MAX) {
+					cmd_mfi =
+					instance->
+					cmd_list[cmd_fusion->sync_cmd_idx];
+					if (cmd_mfi->frame->dcmd.opcode ==
+					    MR_DCMD_LD_MAP_GET_INFO) {
+						megasas_return_cmd(instance,
+								   cmd_mfi);
+						megasas_return_cmd_fusion(
+							instance, cmd_fusion);
+					} else  {
+						req_desc =
+						megasas_get_request_descriptor(
+							instance,
+							cmd_mfi->context.smid
+							-1);
+						if (!req_desc)
+							printk(KERN_WARNING
+							       "req_desc NULL"
+							       "\n");
+						else {
+							instance->instancet->
+							fire_cmd(instance,
+								 req_desc->
+								 u.low,
+								 req_desc->
+								 u.high,
+								 instance->
+								 reg_set);
+						}
+					}
+				}
+			}
+
+			/* Reset load balance info */
+			memset(fusion->load_balance_info, 0,
+			       sizeof(struct LD_LOAD_BALANCE_INFO)
+			       *MAX_LOGICAL_DRIVES);
+
+			if (!megasas_get_map_info(instance))
+				megasas_sync_map_info(instance);
+
+			/* Adapter reset completed successfully */
+			printk(KERN_WARNING "megaraid_sas: Reset "
+			       "successful.\n");
+			retval = SUCCESS;
+			goto out;
+		}
+		/* Reset failed, kill the adapter */
+		printk(KERN_WARNING "megaraid_sas: Reset failed, killing "
+		       "adapter.\n");
+		megaraid_sas_kill_hba(instance);
+		retval = FAILED;
+	} else {
+		instance->instancet->enable_intr(instance->reg_set);
+		instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+	}
+out:
+	clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
+	mutex_unlock(&instance->reset_mutex);
+	return retval;
+}
+
+/* Fusion OCR work queue */
+void megasas_fusion_ocr_wq(struct work_struct *work)
+{
+	struct megasas_instance *instance =
+		container_of(work, struct megasas_instance, work_init);
+
+	megasas_reset_fusion(instance->host);
+}
+
+struct megasas_instance_template megasas_instance_template_fusion = {
+	.fire_cmd = megasas_fire_cmd_fusion,
+	.enable_intr = megasas_enable_intr_fusion,
+	.disable_intr = megasas_disable_intr_fusion,
+	.clear_intr = megasas_clear_intr_fusion,
+	.read_fw_status_reg = megasas_read_fw_status_reg_fusion,
+	.adp_reset = megasas_adp_reset_fusion,
+	.check_reset = megasas_check_reset_fusion,
+	.service_isr = megasas_isr_fusion,
+	.tasklet = megasas_complete_cmd_dpc_fusion,
+	.init_adapter = megasas_init_adapter_fusion,
+	.build_and_issue_cmd = megasas_build_and_issue_cmd_fusion,
+	.issue_dcmd = megasas_issue_dcmd_fusion,
+};
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
new file mode 100644
index 0000000..82b577a
--- /dev/null
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -0,0 +1,695 @@
+/*
+ *  Linux MegaRAID driver for SAS based RAID controllers
+ *
+ *  Copyright (c) 2009-2011  LSI 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
+ *
+ *  FILE: megaraid_sas_fusion.h
+ *
+ *  Authors: LSI Corporation
+ *           Manoj Jose
+ *           Sumant Patro
+ *
+ *  Send feedback to: <megaraidlinux@lsi.com>
+ *
+ *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
+ *     ATTN: Linuxraid
+ */
+
+#ifndef _MEGARAID_SAS_FUSION_H_
+#define _MEGARAID_SAS_FUSION_H_
+
+/* Fusion defines */
+#define MEGASAS_MAX_SZ_CHAIN_FRAME 1024
+#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009)
+#define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256
+#define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST   0xF0
+#define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST         0xF1
+#define MEGASAS_LOAD_BALANCE_FLAG		    0x1
+#define MEGASAS_DCMD_MBOX_PEND_FLAG		    0x1
+#define HOST_DIAG_WRITE_ENABLE			    0x80
+#define HOST_DIAG_RESET_ADAPTER			    0x4
+#define MEGASAS_FUSION_MAX_RESET_TRIES		    3
+
+/* T10 PI defines */
+#define MR_PROT_INFO_TYPE_CONTROLLER                0x8
+#define MEGASAS_SCSI_VARIABLE_LENGTH_CMD            0x7f
+#define MEGASAS_SCSI_SERVICE_ACTION_READ32          0x9
+#define MEGASAS_SCSI_SERVICE_ACTION_WRITE32         0xB
+#define MEGASAS_SCSI_ADDL_CDB_LEN                   0x18
+#define MEGASAS_RD_WR_PROTECT_CHECK_ALL		    0x20
+#define MEGASAS_RD_WR_PROTECT_CHECK_NONE	    0x60
+#define MEGASAS_EEDPBLOCKSIZE			    512
+
+/*
+ * Raid context flags
+ */
+
+#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT   0x4
+#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK    0x30
+enum MR_RAID_FLAGS_IO_SUB_TYPE {
+	MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0,
+	MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1,
+};
+
+/*
+ * Request descriptor types
+ */
+#define MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO           0x7
+#define MEGASAS_REQ_DESCRIPT_FLAGS_MFA             0x1
+
+#define MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT      1
+
+#define MEGASAS_FP_CMD_LEN	16
+#define MEGASAS_FUSION_IN_RESET 0
+
+/*
+ * Raid Context structure which describes MegaRAID specific IO Paramenters
+ * This resides at offset 0x60 where the SGL normally starts in MPT IO Frames
+ */
+
+struct RAID_CONTEXT {
+	u16     resvd0;
+	u16     timeoutValue;
+	u8      regLockFlags;
+	u8      resvd1;
+	u16     VirtualDiskTgtId;
+	u64     regLockRowLBA;
+	u32     regLockLength;
+	u16     nextLMId;
+	u8      exStatus;
+	u8      status;
+	u8      RAIDFlags;
+	u8      numSGE;
+	u16	configSeqNum;
+	u8      spanArm;
+	u8      resvd2[3];
+};
+
+#define RAID_CTX_SPANARM_ARM_SHIFT	(0)
+#define RAID_CTX_SPANARM_ARM_MASK	(0x1f)
+
+#define RAID_CTX_SPANARM_SPAN_SHIFT	(5)
+#define RAID_CTX_SPANARM_SPAN_MASK	(0xE0)
+
+/*
+ * define region lock types
+ */
+enum REGION_TYPE {
+	REGION_TYPE_UNUSED       = 0,
+	REGION_TYPE_SHARED_READ  = 1,
+	REGION_TYPE_SHARED_WRITE = 2,
+	REGION_TYPE_EXCLUSIVE    = 3,
+};
+
+/* MPI2 defines */
+#define MPI2_FUNCTION_IOC_INIT              (0x02) /* IOC Init */
+#define MPI2_WHOINIT_HOST_DRIVER            (0x04)
+#define MPI2_VERSION_MAJOR                  (0x02)
+#define MPI2_VERSION_MINOR                  (0x00)
+#define MPI2_VERSION_MAJOR_MASK             (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT            (8)
+#define MPI2_VERSION_MINOR_MASK             (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT            (0)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
+		      MPI2_VERSION_MINOR)
+#define MPI2_HEADER_VERSION_UNIT            (0x10)
+#define MPI2_HEADER_VERSION_DEV             (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
+#define MPI2_HEADER_VERSION_DEV_MASK        (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT       (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \
+			     MPI2_HEADER_VERSION_DEV)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG        (0x8000)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG          (0x0400)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP       (0x0003)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG          (0x0200)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD           (0x0100)
+#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP             (0x0004)
+#define MPI2_FUNCTION_SCSI_IO_REQUEST               (0x00) /* SCSI IO */
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY           (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO                 (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING        (0x02)
+#define MPI2_SCSIIO_CONTROL_WRITE               (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ                (0x02000000)
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK       (0x0E)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED          (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK       (0x0F)
+#define MPI2_WRSEQ_FLUSH_KEY_VALUE              (0x0)
+#define MPI2_WRITE_SEQUENCE_OFFSET              (0x00000004)
+#define MPI2_WRSEQ_1ST_KEY_VALUE                (0xF)
+#define MPI2_WRSEQ_2ND_KEY_VALUE                (0x4)
+#define MPI2_WRSEQ_3RD_KEY_VALUE                (0xB)
+#define MPI2_WRSEQ_4TH_KEY_VALUE                (0x2)
+#define MPI2_WRSEQ_5TH_KEY_VALUE                (0x7)
+#define MPI2_WRSEQ_6TH_KEY_VALUE                (0xD)
+
+struct MPI25_IEEE_SGE_CHAIN64 {
+	u64                     Address;
+	u32                     Length;
+	u16                     Reserved1;
+	u8                      NextChainOffset;
+	u8                      Flags;
+};
+
+struct MPI2_SGE_SIMPLE_UNION {
+	u32                     FlagsLength;
+	union {
+		u32                 Address32;
+		u64                 Address64;
+	} u;
+};
+
+struct MPI2_SCSI_IO_CDB_EEDP32 {
+	u8                      CDB[20];                    /* 0x00 */
+	u32                     PrimaryReferenceTag;        /* 0x14 */
+	u16                     PrimaryApplicationTag;      /* 0x18 */
+	u16                     PrimaryApplicationTagMask;  /* 0x1A */
+	u32                     TransferLength;             /* 0x1C */
+};
+
+struct MPI2_SGE_CHAIN_UNION {
+	u16                     Length;
+	u8                      NextChainOffset;
+	u8                      Flags;
+	union {
+		u32                 Address32;
+		u64                 Address64;
+	} u;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE32 {
+	u32                     Address;
+	u32                     FlagsLength;
+};
+
+struct MPI2_IEEE_SGE_CHAIN32 {
+	u32                     Address;
+	u32                     FlagsLength;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE64 {
+	u64                     Address;
+	u32                     Length;
+	u16                     Reserved1;
+	u8                      Reserved2;
+	u8                      Flags;
+};
+
+struct MPI2_IEEE_SGE_CHAIN64 {
+	u64                     Address;
+	u32                     Length;
+	u16                     Reserved1;
+	u8                      Reserved2;
+	u8                      Flags;
+};
+
+union MPI2_IEEE_SGE_SIMPLE_UNION {
+	struct MPI2_IEEE_SGE_SIMPLE32  Simple32;
+	struct MPI2_IEEE_SGE_SIMPLE64  Simple64;
+};
+
+union MPI2_IEEE_SGE_CHAIN_UNION {
+	struct MPI2_IEEE_SGE_CHAIN32   Chain32;
+	struct MPI2_IEEE_SGE_CHAIN64   Chain64;
+};
+
+union MPI2_SGE_IO_UNION {
+	struct MPI2_SGE_SIMPLE_UNION       MpiSimple;
+	struct MPI2_SGE_CHAIN_UNION        MpiChain;
+	union MPI2_IEEE_SGE_SIMPLE_UNION  IeeeSimple;
+	union MPI2_IEEE_SGE_CHAIN_UNION   IeeeChain;
+};
+
+union MPI2_SCSI_IO_CDB_UNION {
+	u8                      CDB32[32];
+	struct MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+	struct MPI2_SGE_SIMPLE_UNION SGE;
+};
+
+/*
+ * RAID SCSI IO Request Message
+ * Total SGE count will be one less than  _MPI2_SCSI_IO_REQUEST
+ */
+struct MPI2_RAID_SCSI_IO_REQUEST {
+	u16                     DevHandle;                      /* 0x00 */
+	u8                      ChainOffset;                    /* 0x02 */
+	u8                      Function;                       /* 0x03 */
+	u16                     Reserved1;                      /* 0x04 */
+	u8                      Reserved2;                      /* 0x06 */
+	u8                      MsgFlags;                       /* 0x07 */
+	u8                      VP_ID;                          /* 0x08 */
+	u8                      VF_ID;                          /* 0x09 */
+	u16                     Reserved3;                      /* 0x0A */
+	u32                     SenseBufferLowAddress;          /* 0x0C */
+	u16                     SGLFlags;                       /* 0x10 */
+	u8                      SenseBufferLength;              /* 0x12 */
+	u8                      Reserved4;                      /* 0x13 */
+	u8                      SGLOffset0;                     /* 0x14 */
+	u8                      SGLOffset1;                     /* 0x15 */
+	u8                      SGLOffset2;                     /* 0x16 */
+	u8                      SGLOffset3;                     /* 0x17 */
+	u32                     SkipCount;                      /* 0x18 */
+	u32                     DataLength;                     /* 0x1C */
+	u32                     BidirectionalDataLength;        /* 0x20 */
+	u16                     IoFlags;                        /* 0x24 */
+	u16                     EEDPFlags;                      /* 0x26 */
+	u32                     EEDPBlockSize;                  /* 0x28 */
+	u32                     SecondaryReferenceTag;          /* 0x2C */
+	u16                     SecondaryApplicationTag;        /* 0x30 */
+	u16                     ApplicationTagTranslationMask;  /* 0x32 */
+	u8                      LUN[8];                         /* 0x34 */
+	u32                     Control;                        /* 0x3C */
+	union MPI2_SCSI_IO_CDB_UNION  CDB;			/* 0x40 */
+	struct RAID_CONTEXT	RaidContext;                    /* 0x60 */
+	union MPI2_SGE_IO_UNION       SGL;			/* 0x80 */
+};
+
+/*
+ * MPT RAID MFA IO Descriptor.
+ */
+struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR {
+	u32     RequestFlags:8;
+	u32     MessageAddress1:24; /* bits 31:8*/
+	u32     MessageAddress2;      /* bits 61:32 */
+};
+
+/* Default Request Descriptor */
+struct MPI2_DEFAULT_REQUEST_DESCRIPTOR {
+	u8              RequestFlags;               /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u16             LMID;                       /* 0x04 */
+	u16             DescriptorTypeDependent;    /* 0x06 */
+};
+
+/* High Priority Request Descriptor */
+struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR {
+	u8              RequestFlags;               /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u16             LMID;                       /* 0x04 */
+	u16             Reserved1;                  /* 0x06 */
+};
+
+/* SCSI IO Request Descriptor */
+struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR {
+	u8              RequestFlags;               /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u16             LMID;                       /* 0x04 */
+	u16             DevHandle;                  /* 0x06 */
+};
+
+/* SCSI Target Request Descriptor */
+struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR {
+	u8              RequestFlags;               /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u16             LMID;                       /* 0x04 */
+	u16             IoIndex;                    /* 0x06 */
+};
+
+/* RAID Accelerator Request Descriptor */
+struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
+	u8              RequestFlags;               /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u16             LMID;                       /* 0x04 */
+	u16             Reserved;                   /* 0x06 */
+};
+
+/* union of Request Descriptors */
+union MEGASAS_REQUEST_DESCRIPTOR_UNION {
+	struct MPI2_DEFAULT_REQUEST_DESCRIPTOR             Default;
+	struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR       HighPriority;
+	struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR             SCSIIO;
+	struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR         SCSITarget;
+	struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR          RAIDAccelerator;
+	struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR      MFAIo;
+	union {
+		struct {
+			u32 low;
+			u32 high;
+		} u;
+		u64 Words;
+	};
+};
+
+/* Default Reply Descriptor */
+struct MPI2_DEFAULT_REPLY_DESCRIPTOR {
+	u8              ReplyFlags;                 /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             DescriptorTypeDependent1;   /* 0x02 */
+	u32             DescriptorTypeDependent2;   /* 0x04 */
+};
+
+/* Address Reply Descriptor */
+struct MPI2_ADDRESS_REPLY_DESCRIPTOR {
+	u8              ReplyFlags;                 /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u32             ReplyFrameAddress;          /* 0x04 */
+};
+
+/* SCSI IO Success Reply Descriptor */
+struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR {
+	u8              ReplyFlags;                 /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u16             TaskTag;                    /* 0x04 */
+	u16             Reserved1;                  /* 0x06 */
+};
+
+/* TargetAssist Success Reply Descriptor */
+struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR {
+	u8              ReplyFlags;                 /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u8              SequenceNumber;             /* 0x04 */
+	u8              Reserved1;                  /* 0x05 */
+	u16             IoIndex;                    /* 0x06 */
+};
+
+/* Target Command Buffer Reply Descriptor */
+struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR {
+	u8              ReplyFlags;                 /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u8              VP_ID;                      /* 0x02 */
+	u8              Flags;                      /* 0x03 */
+	u16             InitiatorDevHandle;         /* 0x04 */
+	u16             IoIndex;                    /* 0x06 */
+};
+
+/* RAID Accelerator Success Reply Descriptor */
+struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
+	u8              ReplyFlags;                 /* 0x00 */
+	u8              MSIxIndex;                  /* 0x01 */
+	u16             SMID;                       /* 0x02 */
+	u32             Reserved;                   /* 0x04 */
+};
+
+/* union of Reply Descriptors */
+union MPI2_REPLY_DESCRIPTORS_UNION {
+	struct MPI2_DEFAULT_REPLY_DESCRIPTOR                   Default;
+	struct MPI2_ADDRESS_REPLY_DESCRIPTOR                   AddressReply;
+	struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR           SCSIIOSuccess;
+	struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
+	struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
+	struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR
+	RAIDAcceleratorSuccess;
+	u64                                             Words;
+};
+
+/* IOCInit Request message */
+struct MPI2_IOC_INIT_REQUEST {
+	u8                      WhoInit;                        /* 0x00 */
+	u8                      Reserved1;                      /* 0x01 */
+	u8                      ChainOffset;                    /* 0x02 */
+	u8                      Function;                       /* 0x03 */
+	u16                     Reserved2;                      /* 0x04 */
+	u8                      Reserved3;                      /* 0x06 */
+	u8                      MsgFlags;                       /* 0x07 */
+	u8                      VP_ID;                          /* 0x08 */
+	u8                      VF_ID;                          /* 0x09 */
+	u16                     Reserved4;                      /* 0x0A */
+	u16                     MsgVersion;                     /* 0x0C */
+	u16                     HeaderVersion;                  /* 0x0E */
+	u32                     Reserved5;                      /* 0x10 */
+	u16                     Reserved6;                      /* 0x14 */
+	u8                      Reserved7;                      /* 0x16 */
+	u8                      HostMSIxVectors;                /* 0x17 */
+	u16                     Reserved8;                      /* 0x18 */
+	u16                     SystemRequestFrameSize;         /* 0x1A */
+	u16                     ReplyDescriptorPostQueueDepth;  /* 0x1C */
+	u16                     ReplyFreeQueueDepth;            /* 0x1E */
+	u32                     SenseBufferAddressHigh;         /* 0x20 */
+	u32                     SystemReplyAddressHigh;         /* 0x24 */
+	u64                     SystemRequestFrameBaseAddress;  /* 0x28 */
+	u64                     ReplyDescriptorPostQueueAddress;/* 0x30 */
+	u64                     ReplyFreeQueueAddress;          /* 0x38 */
+	u64                     TimeStamp;                      /* 0x40 */
+};
+
+/* mrpriv defines */
+#define MR_PD_INVALID 0xFFFF
+#define MAX_SPAN_DEPTH 8
+#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
+#define MAX_ROW_SIZE 32
+#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
+#define MAX_LOGICAL_DRIVES 64
+#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
+#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
+#define MAX_ARRAYS 128
+#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
+#define MAX_PHYSICAL_DEVICES 256
+#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
+#define MR_DCMD_LD_MAP_GET_INFO             0x0300e101
+
+struct MR_DEV_HANDLE_INFO {
+	u16     curDevHdl;
+	u8      validHandles;
+	u8      reserved;
+	u16     devHandle[2];
+};
+
+struct MR_ARRAY_INFO {
+	u16      pd[MAX_RAIDMAP_ROW_SIZE];
+};
+
+struct MR_QUAD_ELEMENT {
+	u64     logStart;
+	u64     logEnd;
+	u64     offsetInSpan;
+	u32     diff;
+	u32     reserved1;
+};
+
+struct MR_SPAN_INFO {
+	u32             noElements;
+	u32             reserved1;
+	struct MR_QUAD_ELEMENT quad[MAX_RAIDMAP_SPAN_DEPTH];
+};
+
+struct MR_LD_SPAN {
+	u64      startBlk;
+	u64      numBlks;
+	u16      arrayRef;
+	u8       reserved[6];
+};
+
+struct MR_SPAN_BLOCK_INFO {
+	u64          num_rows;
+	struct MR_LD_SPAN   span;
+	struct MR_SPAN_INFO block_span_info;
+};
+
+struct MR_LD_RAID {
+	struct {
+		u32     fpCapable:1;
+		u32     reserved5:3;
+		u32     ldPiMode:4;
+		u32     pdPiMode:4;
+		u32     encryptionType:8;
+		u32     fpWriteCapable:1;
+		u32     fpReadCapable:1;
+		u32     fpWriteAcrossStripe:1;
+		u32     fpReadAcrossStripe:1;
+		u32     reserved4:8;
+	} capability;
+	u32     reserved6;
+	u64     size;
+	u8      spanDepth;
+	u8      level;
+	u8      stripeShift;
+	u8      rowSize;
+	u8      rowDataSize;
+	u8      writeMode;
+	u8      PRL;
+	u8      SRL;
+	u16     targetId;
+	u8      ldState;
+	u8      regTypeReqOnWrite;
+	u8      modFactor;
+	u8      reserved2[1];
+	u16     seqNum;
+
+	struct {
+		u32 ldSyncRequired:1;
+		u32 reserved:31;
+	} flags;
+
+	u8      reserved3[0x5C];
+};
+
+struct MR_LD_SPAN_MAP {
+	struct MR_LD_RAID          ldRaid;
+	u8                  dataArmMap[MAX_RAIDMAP_ROW_SIZE];
+	struct MR_SPAN_BLOCK_INFO  spanBlock[MAX_RAIDMAP_SPAN_DEPTH];
+};
+
+struct MR_FW_RAID_MAP {
+	u32                 totalSize;
+	union {
+		struct {
+			u32         maxLd;
+			u32         maxSpanDepth;
+			u32         maxRowSize;
+			u32         maxPdCount;
+			u32         maxArrays;
+		} validationInfo;
+		u32             version[5];
+		u32             reserved1[5];
+	};
+
+	u32                 ldCount;
+	u32                 Reserved1;
+	u8                  ldTgtIdToLd[MAX_RAIDMAP_LOGICAL_DRIVES+
+					MAX_RAIDMAP_VIEWS];
+	u8                  fpPdIoTimeoutSec;
+	u8                  reserved2[7];
+	struct MR_ARRAY_INFO       arMapInfo[MAX_RAIDMAP_ARRAYS];
+	struct MR_DEV_HANDLE_INFO  devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
+	struct MR_LD_SPAN_MAP      ldSpanMap[1];
+};
+
+struct IO_REQUEST_INFO {
+	u64 ldStartBlock;
+	u32 numBlocks;
+	u16 ldTgtId;
+	u8 isRead;
+	u16 devHandle;
+	u64 pdBlock;
+	u8 fpOkForIo;
+};
+
+struct MR_LD_TARGET_SYNC {
+	u8  targetId;
+	u8  reserved;
+	u16 seqNum;
+};
+
+#define IEEE_SGE_FLAGS_ADDR_MASK            (0x03)
+#define IEEE_SGE_FLAGS_SYSTEM_ADDR          (0x00)
+#define IEEE_SGE_FLAGS_IOCDDR_ADDR          (0x01)
+#define IEEE_SGE_FLAGS_IOCPLB_ADDR          (0x02)
+#define IEEE_SGE_FLAGS_IOCPLBNTA_ADDR       (0x03)
+#define IEEE_SGE_FLAGS_CHAIN_ELEMENT        (0x80)
+#define IEEE_SGE_FLAGS_END_OF_LIST          (0x40)
+
+struct megasas_register_set;
+struct megasas_instance;
+
+union desc_word {
+	u64 word;
+	struct {
+		u32 low;
+		u32 high;
+	} u;
+};
+
+struct megasas_cmd_fusion {
+	struct MPI2_RAID_SCSI_IO_REQUEST	*io_request;
+	dma_addr_t			io_request_phys_addr;
+
+	union MPI2_SGE_IO_UNION	*sg_frame;
+	dma_addr_t		sg_frame_phys_addr;
+
+	u8 *sense;
+	dma_addr_t sense_phys_addr;
+
+	struct list_head list;
+	struct scsi_cmnd *scmd;
+	struct megasas_instance *instance;
+
+	u8 retry_for_fw_reset;
+	union MEGASAS_REQUEST_DESCRIPTOR_UNION  *request_desc;
+
+	/*
+	 * Context for a MFI frame.
+	 * Used to get the mfi cmd from list when a MFI cmd is completed
+	 */
+	u32 sync_cmd_idx;
+	u32 index;
+	u8 flags;
+};
+
+struct LD_LOAD_BALANCE_INFO {
+	u8	loadBalanceFlag;
+	u8	reserved1;
+	u16     raid1DevHandle[2];
+	atomic_t     scsi_pending_cmds[2];
+	u64     last_accessed_block[2];
+};
+
+struct MR_FW_RAID_MAP_ALL {
+	struct MR_FW_RAID_MAP raidMap;
+	struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
+} __attribute__ ((packed));
+
+struct fusion_context {
+	struct megasas_cmd_fusion **cmd_list;
+	struct list_head cmd_pool;
+
+	spinlock_t cmd_pool_lock;
+
+	dma_addr_t req_frames_desc_phys;
+	u8 *req_frames_desc;
+
+	struct dma_pool *io_request_frames_pool;
+	dma_addr_t io_request_frames_phys;
+	u8 *io_request_frames;
+
+	struct dma_pool *sg_dma_pool;
+	struct dma_pool *sense_dma_pool;
+
+	dma_addr_t reply_frames_desc_phys;
+	union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
+	struct dma_pool *reply_frames_desc_pool;
+
+	u16 last_reply_idx;
+
+	u32 reply_q_depth;
+	u32 request_alloc_sz;
+	u32 reply_alloc_sz;
+	u32 io_frames_alloc_sz;
+
+	u16	max_sge_in_main_msg;
+	u16	max_sge_in_chain;
+
+	u8	chain_offset_io_request;
+	u8	chain_offset_mfi_pthru;
+
+	struct MR_FW_RAID_MAP_ALL *ld_map[2];
+	dma_addr_t ld_map_phys[2];
+
+	u32 map_sz;
+	u8 fast_path_io;
+	struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
+};
+
+union desc_value {
+	u64 word;
+	struct {
+		u32 low;
+		u32 high;
+	} u;
+};
+
+#endif /* _MEGARAID_SAS_FUSION_H_ */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index 4b1c2f0..8be75e6 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -8,7 +8,7 @@
  *                  scatter/gather formats.
  *  Creation Date:  June 21, 2006
  *
- *  mpi2.h Version:  02.00.15
+ *  mpi2.h Version:  02.00.16
  *
  *  Version History
  *  ---------------
@@ -61,6 +61,8 @@
  *                      Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
  *                      Added defines for product-specific range of message
  *                      function codes, 0xF0 to 0xFF.
+ *  05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added alternative defines for the SGE Direction bit.
  *  --------------------------------------------------------------------------
  */
 
@@ -86,7 +88,7 @@
 #define MPI2_VERSION_02_00                  (0x0200)
 
 /* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x0F)
+#define MPI2_HEADER_VERSION_UNIT            (0x10)
 #define MPI2_HEADER_VERSION_DEV             (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
@@ -929,6 +931,9 @@
 #define MPI2_SGE_FLAGS_IOC_TO_HOST              (0x00)
 #define MPI2_SGE_FLAGS_HOST_TO_IOC              (0x04)
 
+#define MPI2_SGE_FLAGS_DEST                     (MPI2_SGE_FLAGS_IOC_TO_HOST)
+#define MPI2_SGE_FLAGS_SOURCE                   (MPI2_SGE_FLAGS_HOST_TO_IOC)
+
 /* Address Size */
 
 #define MPI2_SGE_FLAGS_32_BIT_ADDRESSING        (0x00)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index e3728d7..d76a658 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Configuration messages and pages
  *  Creation Date:  November 10, 2006
  *
- *    mpi2_cnfg.h Version:  02.00.14
+ *    mpi2_cnfg.h Version:  02.00.15
  *
  *  Version History
  *  ---------------
@@ -121,6 +121,10 @@
  *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines.
  *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines.
  *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines.
+ *  05-12-10  02.00.15  Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
+ *                      define.
+ *                      Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
+ *                      Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
  *  --------------------------------------------------------------------------
  */
 
@@ -333,7 +337,7 @@
 #define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM          (0x06)
 #define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE      (0x07)
 
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
 
 
 /* Config Reply Message */
@@ -379,6 +383,8 @@
 #define MPI2_MFGPAGE_DEVID_SAS2116_1                (0x0064)
 #define MPI2_MFGPAGE_DEVID_SAS2116_2                (0x0065)
 
+#define MPI2_MFGPAGE_DEVID_SSS6200                  (0x007E)
+
 #define MPI2_MFGPAGE_DEVID_SAS2208_1                (0x0080)
 #define MPI2_MFGPAGE_DEVID_SAS2208_2                (0x0081)
 #define MPI2_MFGPAGE_DEVID_SAS2208_3                (0x0082)
@@ -390,6 +396,8 @@
 #define MPI2_MFGPAGE_DEVID_SAS2308_3                (0x006E)
 
 
+
+
 /* Manufacturing Page 0 */
 
 typedef struct _MPI2_CONFIG_PAGE_MAN_0
@@ -729,6 +737,7 @@
 /* IO Unit Page 1 Flags defines */
 #define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY    (0x00000800)
 #define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE          (0x00000600)
+#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT         (9)
 #define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE        (0x00000000)
 #define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE       (0x00000200)
 #define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE     (0x00000400)
@@ -1347,6 +1356,7 @@
 #define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION        (0x00040000)
 #define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT           (0x00020000)
 #define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS        (0x00010000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT        (0x00000080)
 #define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED               (0x00000040)
 #define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE              (0x00000020)
 #define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR          (0x00000000)
@@ -1469,11 +1479,15 @@
 #define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA             (0x03)
 #define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD   (0x04)
 #define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA    (0x05)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE          (0x06)
 #define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN             (0xFF)
 
 /* PhysDiskAttributes defines */
+#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK                (0x0C)
 #define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE         (0x08)
 #define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE           (0x04)
+
+#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK             (0x03)
 #define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL              (0x02)
 #define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL             (0x01)
 
@@ -1545,6 +1559,7 @@
 #define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE        (0x03)
 #define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR            (0x04)
 #define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS    (0x05)
+#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY          (0x06)
 #define MPI2_SAS_NEG_LINK_RATE_1_5                      (0x08)
 #define MPI2_SAS_NEG_LINK_RATE_3_0                      (0x09)
 #define MPI2_SAS_NEG_LINK_RATE_6_0                      (0x0A)
@@ -1571,6 +1586,7 @@
 #define MPI2_SAS_PHYINFO_PHY_VACANT                     (0x80000000)
 
 #define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK       (0x18000000)
+#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION      (27)
 #define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE               (0x00000000)
 #define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL              (0x08000000)
 #define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER              (0x10000000)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
index bd6c92b..b1e88f2 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
@@ -291,6 +291,7 @@
  *                      can be sized by the build environment.
  *  07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
  *                      VolumeCreationFlags and marked the old one as obsolete.
+ *  05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
  *  --------------------------------------------------------------------------
 
 mpi2_sas.h
@@ -301,6 +302,7 @@
  *                      Request.
  *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
  *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
+ *  05-12-10  02.00.04  Modified some comments.
  *  --------------------------------------------------------------------------
 
 mpi2_targ.h
@@ -324,6 +326,7 @@
  *                      and reply messages.
  *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
  *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
+ *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
  *  --------------------------------------------------------------------------
 
 mpi2_type.h
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
index c4c99df..20e6b88 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -6,7 +6,7 @@
  *          Title:  MPI SCSI initiator mode messages and structures
  *  Creation Date:  June 23, 2006
  *
- *    mpi2_init.h Version:  02.00.09
+ *    mpi2_init.h Version:  02.00.10
  *
  *  Version History
  *  ---------------
@@ -32,6 +32,7 @@
  *                      Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
  *                      Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
  *  02-10-10  02.00.09  Removed unused structure that had "#if 0" around it.
+ *  05-12-10  02.00.10  Added optional vendor-unique region to SCSI IO Request.
  *  --------------------------------------------------------------------------
  */
 
@@ -98,7 +99,13 @@
     U8                      LUN[8];                         /* 0x34 */
     U32                     Control;                        /* 0x3C */
     MPI2_SCSI_IO_CDB_UNION  CDB;                            /* 0x40 */
+
+#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */
+	MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion;
+#endif
+
     MPI2_SGE_IO_UNION       SGL;                            /* 0x60 */
+
 } MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST,
   Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t;
 
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
index 495bedc..761cbdb 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -6,7 +6,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  October 11, 2006
  *
- *  mpi2_ioc.h Version:  02.00.14
+ *  mpi2_ioc.h Version:  02.00.15
  *
  *  Version History
  *  ---------------
@@ -101,6 +101,8 @@
  *  02-10-10  02.00.14  Added SAS Quiesce Event structure and defines.
  *                      Added PowerManagementControl Request structures and
  *                      defines.
+ *  05-12-10  02.00.15  Marked Task Set Full Event as obsolete.
+ *                      Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
  *  --------------------------------------------------------------------------
  */
 
@@ -456,7 +458,7 @@
 #define MPI2_EVENT_STATE_CHANGE                     (0x0002)
 #define MPI2_EVENT_HARD_RESET_RECEIVED              (0x0005)
 #define MPI2_EVENT_EVENT_CHANGE                     (0x000A)
-#define MPI2_EVENT_TASK_SET_FULL                    (0x000E)
+#define MPI2_EVENT_TASK_SET_FULL                    (0x000E) /* obsolete */
 #define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE         (0x000F)
 #define MPI2_EVENT_IR_OPERATION_STATUS              (0x0014)
 #define MPI2_EVENT_SAS_DISCOVERY                    (0x0016)
@@ -517,6 +519,7 @@
   MPI2_POINTER pMpi2EventDataHardResetReceived_t;
 
 /* Task Set Full Event data */
+/*   this event is obsolete */
 
 typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL
 {
@@ -831,6 +834,7 @@
 #define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE            (0x03)
 #define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR                (0x04)
 #define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS        (0x05)
+#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY              (0x06)
 #define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5                     (0x08)
 #define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0                     (0x09)
 #define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0                     (0x0A)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
index 5160c33..bd61a7b 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2008 LSI Corporation.
+ *  Copyright (c) 2000-2010 LSI Corporation.
  *
  *
  *           Name:  mpi2_raid.h
  *          Title:  MPI Integrated RAID messages and structures
  *  Creation Date:  April 26, 2007
  *
- *    mpi2_raid.h Version:  02.00.04
+ *    mpi2_raid.h Version:  02.00.05
  *
  *  Version History
  *  ---------------
@@ -22,6 +22,7 @@
  *                      can be sized by the build environment.
  *  07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
  *                      VolumeCreationFlags and marked the old one as obsolete.
+ *  05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
  *  --------------------------------------------------------------------------
  */
 
@@ -260,6 +261,7 @@
 #define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
 #define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK    (0x00000002)
 #define MPI2_RAID_VOL_FLAGS_OP_RESYNC               (0x00000003)
+#define MPI2_RAID_VOL_FLAGS_OP_MDC                  (0x00000004)
 
 
 /* RAID Action Reply ActionData union */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
index 2d8aeed..608f6d6 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2007 LSI Corporation.
+ *  Copyright (c) 2000-2010 LSI Corporation.
  *
  *
  *           Name:  mpi2_sas.h
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  February 9, 2007
  *
- *  mpi2.h Version:  02.00.03
+ *  mpi2_sas.h Version:  02.00.04
  *
  *  Version History
  *  ---------------
@@ -20,6 +20,7 @@
  *                      Request.
  *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
  *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
+ *  05-12-10  02.00.04  Modified some comments.
  *  --------------------------------------------------------------------------
  */
 
@@ -110,7 +111,7 @@
 /* values for PassthroughFlags field */
 #define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE      (0x80)
 
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
 
 
 /* SMP Passthrough Reply Message */
@@ -174,7 +175,7 @@
 #define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE             (0x0002)
 #define MPI2_SATA_PT_REQ_PT_FLAGS_READ              (0x0001)
 
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
 
 
 /* SATA Passthrough Reply Message */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
index 686b09b..5c6e3a6 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
@@ -6,7 +6,7 @@
  *          Title:  MPI diagnostic tool structures and definitions
  *  Creation Date:  March 26, 2007
  *
- *    mpi2_tool.h Version:  02.00.04
+ *    mpi2_tool.h Version:  02.00.05
  *
  *  Version History
  *  ---------------
@@ -22,6 +22,7 @@
  *                      and reply messages.
  *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
  *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
+ *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
  *  --------------------------------------------------------------------------
  */
 
@@ -37,6 +38,7 @@
 /* defines for the Tools */
 #define MPI2_TOOLBOX_CLEAN_TOOL                     (0x00)
 #define MPI2_TOOLBOX_MEMORY_MOVE_TOOL               (0x01)
+#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL          (0x02)
 #define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL          (0x03)
 #define MPI2_TOOLBOX_BEACON_TOOL                    (0x05)
 #define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL            (0x06)
@@ -102,8 +104,7 @@
 *  Toolbox Memory Move request
 ****************************************************************************/
 
-typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
-{
+typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST {
     U8                      Tool;                       /* 0x00 */
     U8                      Reserved1;                  /* 0x01 */
     U8                      ChainOffset;                /* 0x02 */
@@ -120,6 +121,44 @@
 
 
 /****************************************************************************
+*  Toolbox Diagnostic Data Upload request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST {
+	U8                      Tool;                       /* 0x00 */
+	U8                      Reserved1;                  /* 0x01 */
+	U8                      ChainOffset;                /* 0x02 */
+	U8                      Function;                   /* 0x03 */
+	U16                     Reserved2;                  /* 0x04 */
+	U8                      Reserved3;                  /* 0x06 */
+	U8                      MsgFlags;                   /* 0x07 */
+	U8                      VP_ID;                      /* 0x08 */
+	U8                      VF_ID;                      /* 0x09 */
+	U16                     Reserved4;                  /* 0x0A */
+	U8                      SGLFlags;                   /* 0x0C */
+	U8                      Reserved5;                  /* 0x0D */
+	U16                     Reserved6;                  /* 0x0E */
+	U32                     Flags;                      /* 0x10 */
+	U32                     DataLength;                 /* 0x14 */
+	MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x18 */
+} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
+Mpi2ToolboxDiagDataUploadRequest_t,
+MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t;
+
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
+
+
+typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER {
+	U32                     DiagDataLength;             /* 00h */
+	U8                      FormatCode;                 /* 04h */
+	U8                      Reserved1;                  /* 05h */
+	U16                     Reserved2;                  /* 06h */
+} MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER,
+Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_t;
+
+
+/****************************************************************************
 *  Toolbox ISTWI Read Write Tool
 ****************************************************************************/
 
@@ -162,7 +201,7 @@
 #define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS          (0x11)
 #define MPI2_TOOL_ISTWI_ACTION_RESET                (0x12)
 
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
 
 
 /* Toolbox ISTWI Read Write Tool reply message */
@@ -248,7 +287,7 @@
   Mpi2ToolboxDiagnosticCliRequest_t,
   MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t;
 
-/* values for SGLFlags field are in the SGL section of mpi2.h */
+/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
 
 
 /* Toolbox Diagnostic CLI Tool reply message */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 12faf64..b2a8170 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -65,7 +65,6 @@
 static MPT_CALLBACK	mpt_callbacks[MPT_MAX_CALLBACKS];
 
 #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
-#define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */
 
 static int max_queue_depth = -1;
 module_param(max_queue_depth, int, 0);
@@ -79,6 +78,10 @@
 module_param(msix_disable, int, 0);
 MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
 
+static int missing_delay[2] = {-1, -1};
+module_param_array(missing_delay, int, NULL, 0);
+MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
+
 /* diag_buffer_enable is bitwise
  * bit 0 set = TRACE
  * bit 1 set = SNAPSHOT
@@ -515,9 +518,6 @@
 	case MPI2_EVENT_EVENT_CHANGE:
 		desc = "Event Change";
 		break;
-	case MPI2_EVENT_TASK_SET_FULL:
-		desc = "Task Set Full";
-		break;
 	case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
 		desc = "Device Status Change";
 		break;
@@ -758,7 +758,7 @@
 		if (smid < ioc->internal_smid) {
 			i = smid - ioc->hi_priority_smid;
 			cb_idx = ioc->hpr_lookup[i].cb_idx;
-		} else {
+		} else if (smid <= ioc->hba_queue_depth)  {
 			i = smid - ioc->internal_smid;
 			cb_idx = ioc->internal_lookup[i].cb_idx;
 		}
@@ -848,6 +848,7 @@
 		return IRQ_NONE;
 
 	completed_cmds = 0;
+	cb_idx = 0xFF;
 	do {
 		rd.word = rpf->Words;
 		if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
@@ -860,6 +861,9 @@
 		    MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
 			reply = le32_to_cpu
 				(rpf->AddressReply.ReplyFrameAddress);
+			if (reply > ioc->reply_dma_max_address ||
+			    reply < ioc->reply_dma_min_address)
+				reply = 0;
 		} else if (request_desript_type ==
 		    MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
 			goto next;
@@ -1489,6 +1493,7 @@
 {
 	unsigned long flags;
 	int i;
+	struct chain_tracker *chain_req, *next;
 
 	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
 	if (smid >= ioc->hi_priority_smid) {
@@ -1511,6 +1516,14 @@
 
 	/* scsiio queue */
 	i = smid - 1;
+	if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
+		list_for_each_entry_safe(chain_req, next,
+		    &ioc->scsi_lookup[i].chain_list, tracker_list) {
+			list_del_init(&chain_req->tracker_list);
+			list_add_tail(&chain_req->tracker_list,
+			    &ioc->free_chain_list);
+		}
+	}
 	ioc->scsi_lookup[i].cb_idx = 0xFF;
 	ioc->scsi_lookup[i].scmd = NULL;
 	list_add_tail(&ioc->scsi_lookup[i].tracker_list,
@@ -1819,6 +1832,97 @@
 }
 
 /**
+ * _base_update_missing_delay - change the missing delay timers
+ * @ioc: per adapter object
+ * @device_missing_delay: amount of time till device is reported missing
+ * @io_missing_delay: interval IO is returned when there is a missing device
+ *
+ * Return nothing.
+ *
+ * Passed on the command line, this function will modify the device missing
+ * delay, as well as the io missing delay. This should be called at driver
+ * load time.
+ */
+static void
+_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
+	u16 device_missing_delay, u8 io_missing_delay)
+{
+	u16 dmd, dmd_new, dmd_orignal;
+	u8 io_missing_delay_original;
+	u16 sz;
+	Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+	Mpi2ConfigReply_t mpi_reply;
+	u8 num_phys = 0;
+	u16 ioc_status;
+
+	mpt2sas_config_get_number_hba_phys(ioc, &num_phys);
+	if (!num_phys)
+		return;
+
+	sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
+	    sizeof(Mpi2SasIOUnit1PhyData_t));
+	sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+	if (!sas_iounit_pg1) {
+		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+		    ioc->name, __FILE__, __LINE__, __func__);
+		goto out;
+	}
+	if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+	    sas_iounit_pg1, sz))) {
+		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+		    ioc->name, __FILE__, __LINE__, __func__);
+		goto out;
+	}
+	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+	    MPI2_IOCSTATUS_MASK;
+	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+		    ioc->name, __FILE__, __LINE__, __func__);
+		goto out;
+	}
+
+	/* device missing delay */
+	dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
+	if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+		dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+	else
+		dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+	dmd_orignal = dmd;
+	if (device_missing_delay > 0x7F) {
+		dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
+		    device_missing_delay;
+		dmd = dmd / 16;
+		dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
+	} else
+		dmd = device_missing_delay;
+	sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
+
+	/* io missing delay */
+	io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
+	sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
+
+	if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
+	    sz)) {
+		if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+			dmd_new = (dmd &
+			    MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+		else
+			dmd_new =
+		    dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+		printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), "
+		    "new(%d)\n", ioc->name, dmd_orignal, dmd_new);
+		printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), "
+		    "new(%d)\n", ioc->name, io_missing_delay_original,
+		    io_missing_delay);
+		ioc->device_missing_delay = dmd_new;
+		ioc->io_missing_delay = io_missing_delay;
+	}
+
+out:
+	kfree(sas_iounit_pg1);
+}
+
+/**
  * _base_static_config_pages - static start of day config pages
  * @ioc: per adapter object
  *
@@ -1855,6 +1959,7 @@
 		    MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
 	ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
 	mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
+
 }
 
 /**
@@ -1868,6 +1973,8 @@
 static void
 _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
 {
+	int i;
+
 	dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
 	    __func__));
 
@@ -1932,6 +2039,20 @@
 	}
 	kfree(ioc->hpr_lookup);
 	kfree(ioc->internal_lookup);
+	if (ioc->chain_lookup) {
+		for (i = 0; i < ioc->chain_depth; i++) {
+			if (ioc->chain_lookup[i].chain_buffer)
+				pci_pool_free(ioc->chain_dma_pool,
+				    ioc->chain_lookup[i].chain_buffer,
+				    ioc->chain_lookup[i].chain_buffer_dma);
+		}
+		if (ioc->chain_dma_pool)
+			pci_pool_destroy(ioc->chain_dma_pool);
+	}
+	if (ioc->chain_lookup) {
+		free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
+		ioc->chain_lookup = NULL;
+	}
 }
 
 
@@ -1953,6 +2074,7 @@
 	u32 sz, total_sz;
 	u32 retry_sz;
 	u16 max_request_credit;
+	int i;
 
 	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
 	    __func__));
@@ -1970,14 +2092,11 @@
 	}
 
 	/* command line tunables  for max controller queue depth */
-	if (max_queue_depth != -1) {
+	if (max_queue_depth != -1)
 		max_request_credit = (max_queue_depth < facts->RequestCredit)
 		    ? max_queue_depth : facts->RequestCredit;
-	} else {
-		max_request_credit = (facts->RequestCredit >
-		    MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE :
-		    facts->RequestCredit;
-	}
+	else
+		max_request_credit = facts->RequestCredit;
 
 	ioc->hba_queue_depth = max_request_credit;
 	ioc->hi_priority_depth = facts->HighPriorityCredit;
@@ -2083,7 +2202,7 @@
 	 * "frame for smid=0
 	 */
 	ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
-	sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz);
+	sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
 
 	/* hi-priority queue */
 	sz += (ioc->hi_priority_depth * ioc->request_sz);
@@ -2124,19 +2243,11 @@
 	ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
 	    ioc->request_sz);
 
-	ioc->chain = ioc->internal + (ioc->internal_depth *
-	    ioc->request_sz);
-	ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth *
-	    ioc->request_sz);
 
 	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
 	    "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
 	    ioc->request, ioc->hba_queue_depth, ioc->request_sz,
 	    (ioc->hba_queue_depth * ioc->request_sz)/1024));
-	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth"
-	    "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain,
-	    ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
-	    ioc->request_sz))/1024));
 	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
 	    ioc->name, (unsigned long long) ioc->request_dma));
 	total_sz += sz;
@@ -2155,6 +2266,38 @@
 	    "depth(%d)\n", ioc->name, ioc->request,
 	    ioc->scsiio_depth));
 
+	/* loop till the allocation succeeds */
+	do {
+		sz = ioc->chain_depth * sizeof(struct chain_tracker);
+		ioc->chain_pages = get_order(sz);
+		ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
+		    GFP_KERNEL, ioc->chain_pages);
+		if (ioc->chain_lookup == NULL)
+			ioc->chain_depth -= 100;
+	} while (ioc->chain_lookup == NULL);
+	ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
+	    ioc->request_sz, 16, 0);
+	if (!ioc->chain_dma_pool) {
+		printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create "
+		    "failed\n", ioc->name);
+		goto out;
+	}
+	for (i = 0; i < ioc->chain_depth; i++) {
+		ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
+		    ioc->chain_dma_pool , GFP_KERNEL,
+		    &ioc->chain_lookup[i].chain_buffer_dma);
+		if (!ioc->chain_lookup[i].chain_buffer) {
+			ioc->chain_depth = i;
+			goto chain_done;
+		}
+		total_sz += ioc->request_sz;
+	}
+chain_done:
+	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth"
+	    "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
+	    ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
+	    ioc->request_sz))/1024));
+
 	/* initialize hi-priority queue smid's */
 	ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
 	    sizeof(struct request_tracker), GFP_KERNEL);
@@ -2221,6 +2364,8 @@
 		    ioc->name);
 		goto out;
 	}
+	ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
+	ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
 	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
 	    "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
 	    ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
@@ -2302,7 +2447,6 @@
 	return 0;
 
  out:
-	_base_release_memory_pools(ioc);
 	return -ENOMEM;
 }
 
@@ -3485,6 +3629,7 @@
 	INIT_LIST_HEAD(&ioc->free_list);
 	smid = 1;
 	for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
+		INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
 		ioc->scsi_lookup[i].cb_idx = 0xFF;
 		ioc->scsi_lookup[i].smid = smid;
 		ioc->scsi_lookup[i].scmd = NULL;
@@ -3511,6 +3656,13 @@
 		list_add_tail(&ioc->internal_lookup[i].tracker_list,
 		    &ioc->internal_free_list);
 	}
+
+	/* chain pool */
+	INIT_LIST_HEAD(&ioc->free_chain_list);
+	for (i = 0; i < ioc->chain_depth; i++)
+		list_add_tail(&ioc->chain_lookup[i].tracker_list,
+		    &ioc->free_chain_list);
+
 	spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 
 	/* initialize Reply Free Queue */
@@ -3708,12 +3860,15 @@
 	_base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
 	_base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
 	_base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
-	_base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL);
 	_base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
 	r = _base_make_ioc_operational(ioc, CAN_SLEEP);
 	if (r)
 		goto out_free_resources;
 
+	if (missing_delay[0] != -1 && missing_delay[1] != -1)
+		_base_update_missing_delay(ioc, missing_delay[0],
+		    missing_delay[1]);
+
 	mpt2sas_base_start_watchdog(ioc);
 	return 0;
 
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 0b15a8b..283568c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,8 +69,8 @@
 #define MPT2SAS_DRIVER_NAME		"mpt2sas"
 #define MPT2SAS_AUTHOR	"LSI Corporation <DL-MPTFusionLinux@lsi.com>"
 #define MPT2SAS_DESCRIPTION	"LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION		"06.100.00.00"
-#define MPT2SAS_MAJOR_VERSION		06
+#define MPT2SAS_DRIVER_VERSION		"07.100.00.00"
+#define MPT2SAS_MAJOR_VERSION		07
 #define MPT2SAS_MINOR_VERSION		100
 #define MPT2SAS_BUILD_VERSION		00
 #define MPT2SAS_RELEASE_VERSION		00
@@ -419,6 +419,18 @@
 };
 
 /**
+ * struct chain_tracker - firmware chain tracker
+ * @chain_buffer: chain buffer
+ * @chain_buffer_dma: physical address
+ * @tracker_list: list of free request (ioc->free_chain_list)
+ */
+struct chain_tracker {
+	void *chain_buffer;
+	dma_addr_t chain_buffer_dma;
+	struct list_head tracker_list;
+};
+
+/**
  * struct request_tracker - firmware request tracker
  * @smid: system message id
  * @scmd: scsi request pointer
@@ -430,6 +442,7 @@
 	u16	smid;
 	struct scsi_cmnd *scmd;
 	u8	cb_idx;
+	struct list_head chain_list;
 	struct list_head tracker_list;
 };
 
@@ -704,8 +717,10 @@
 	wait_queue_head_t reset_wq;
 
 	/* chain */
-	u8		*chain;
-	dma_addr_t	chain_dma;
+	struct chain_tracker *chain_lookup;
+	struct list_head free_chain_list;
+	struct dma_pool *chain_dma_pool;
+	ulong		chain_pages;
 	u16 		max_sges_in_main_message;
 	u16		max_sges_in_chain_message;
 	u16		chains_needed_per_io;
@@ -737,6 +752,8 @@
 	u16		reply_sz;
 	u8		*reply;
 	dma_addr_t	reply_dma;
+	u32		reply_dma_max_address;
+	u32		reply_dma_min_address;
 	struct dma_pool *reply_dma_pool;
 
 	/* reply free queue */
@@ -832,6 +849,8 @@
     ulong timeout, struct scsi_cmnd *scmd);
 void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
 void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
+void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
+void mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
 struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
     u16 handle);
 struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index 40cb8ae..e92b77a 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -81,6 +81,7 @@
 	BLOCKING,
 };
 
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 /**
  * _ctl_sas_device_find_by_handle - sas device search
  * @ioc: per adapter object
@@ -107,7 +108,6 @@
 	return r;
 }
 
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 /**
  * _ctl_display_some_debug - debug routine
  * @ioc: per adapter object
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 1a96a00..eda347c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -931,31 +931,32 @@
 }
 
 /**
- * _scsih_get_chain_buffer_dma - obtain block of chains (dma address)
+ * _scsih_get_chain_buffer_tracker - obtain chain tracker
  * @ioc: per adapter object
- * @smid: system request message index
+ * @smid: smid associated to an IO request
  *
- * Returns phys pointer to chain buffer.
+ * Returns chain tracker(from ioc->free_chain_list)
  */
-static dma_addr_t
-_scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+static struct chain_tracker *
+_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 {
-	return ioc->chain_dma + ((smid - 1) * (ioc->request_sz *
-	    ioc->chains_needed_per_io));
-}
+	struct chain_tracker *chain_req;
+	unsigned long flags;
 
-/**
- * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns virt pointer to chain buffer.
- */
-static void *
-_scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-	return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz *
-	    ioc->chains_needed_per_io)));
+	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+	if (list_empty(&ioc->free_chain_list)) {
+		spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+		printk(MPT2SAS_WARN_FMT "chain buffers not available\n",
+		    ioc->name);
+		return NULL;
+	}
+	chain_req = list_entry(ioc->free_chain_list.next,
+	    struct chain_tracker, tracker_list);
+	list_del_init(&chain_req->tracker_list);
+	list_add_tail(&chain_req->tracker_list,
+	    &ioc->scsi_lookup[smid - 1].chain_list);
+	spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+	return chain_req;
 }
 
 /**
@@ -986,6 +987,7 @@
 	u32 sgl_flags;
 	u32 sgl_flags_last_element;
 	u32 sgl_flags_end_buffer;
+	struct chain_tracker *chain_req;
 
 	mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
 
@@ -1033,8 +1035,11 @@
 
 	/* initializing the chain flags and pointers */
 	chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
-	chain = _scsih_get_chain_buffer(ioc, smid);
-	chain_dma = _scsih_get_chain_buffer_dma(ioc, smid);
+	chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
+	if (!chain_req)
+		return -1;
+	chain = chain_req->chain_buffer;
+	chain_dma = chain_req->chain_buffer_dma;
 	do {
 		sges_in_segment = (sges_left <=
 		    ioc->max_sges_in_chain_message) ? sges_left :
@@ -1070,8 +1075,11 @@
 			sges_in_segment--;
 		}
 
-		chain_dma += ioc->request_sz;
-		chain += ioc->request_sz;
+		chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
+		if (!chain_req)
+			return -1;
+		chain = chain_req->chain_buffer;
+		chain_dma = chain_req->chain_buffer_dma;
 	} while (1);
 
 
@@ -1094,28 +1102,24 @@
 }
 
 /**
- * _scsih_change_queue_depth - setting device queue depth
+ * _scsih_adjust_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
- * @reason: calling context
  *
- * Returns queue depth.
+ *
+ * Returns nothing
  */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+static void
+_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
 {
 	struct Scsi_Host *shost = sdev->host;
 	int max_depth;
-	int tag_type;
 	struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
 	struct MPT2SAS_DEVICE *sas_device_priv_data;
 	struct MPT2SAS_TARGET *sas_target_priv_data;
 	struct _sas_device *sas_device;
 	unsigned long flags;
 
-	if (reason != SCSI_QDEPTH_DEFAULT)
-		return -EOPNOTSUPP;
-
 	max_depth = shost->can_queue;
 
 	/* limit max device queue for SATA to 32 */
@@ -1141,8 +1145,27 @@
 		max_depth = 1;
 	if (qdepth > max_depth)
 		qdepth = max_depth;
-	tag_type = (qdepth == 1) ? 0 : MSG_SIMPLE_TAG;
-	scsi_adjust_queue_depth(sdev, tag_type, qdepth);
+	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+}
+
+/**
+ * _scsih_change_queue_depth - setting device queue depth
+ * @sdev: scsi device struct
+ * @qdepth: requested queue depth
+ * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
+ * (see include/scsi/scsi_host.h for definition)
+ *
+ * Returns queue depth.
+ */
+static int
+_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+{
+	if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
+		_scsih_adjust_queue_depth(sdev, qdepth);
+	else if (reason == SCSI_QDEPTH_QFULL)
+		scsi_track_queue_full(sdev, qdepth);
+	else
+		return -EOPNOTSUPP;
 
 	if (sdev->inquiry_len > 7)
 		sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
@@ -2251,13 +2274,13 @@
 
 	struct scsi_target *starget = scmd->device->sdev_target;
 
-	starget_printk(KERN_INFO, starget, "attempting target reset! "
+	starget_printk(KERN_INFO, starget, "attempting device reset! "
 	    "scmd(%p)\n", scmd);
 	_scsih_tm_display_info(ioc, scmd);
 
 	sas_device_priv_data = scmd->device->hostdata;
 	if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
-		starget_printk(KERN_INFO, starget, "target been deleted! "
+		starget_printk(KERN_INFO, starget, "device been deleted! "
 		    "scmd(%p)\n", scmd);
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
@@ -2576,9 +2599,9 @@
 	   &sas_expander->sas_port_list, port_list) {
 
 		if (mpt2sas_port->remote_identify.device_type ==
-		    MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+		    SAS_EDGE_EXPANDER_DEVICE ||
 		    mpt2sas_port->remote_identify.device_type ==
-		    MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
+		    SAS_FANOUT_EXPANDER_DEVICE) {
 
 			spin_lock_irqsave(&ioc->sas_node_lock, flags);
 			expander_sibling =
@@ -2715,9 +2738,10 @@
 _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
     u8 msix_index, u32 reply)
 {
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 	Mpi2SasIoUnitControlReply_t *mpi_reply =
 	    mpt2sas_base_get_reply_virt_addr(ioc, reply);
-
+#endif
 	dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
 	    "sc_complete:handle(0x%04x), (open) "
 	    "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
@@ -3963,6 +3987,7 @@
 	Mpi2ConfigReply_t mpi_reply;
 	Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
 	u16 attached_handle;
+	u8 link_rate;
 
 	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
 	    "updating handles for sas_host(0x%016llx)\n",
@@ -3984,15 +4009,17 @@
 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
 		goto out;
 	for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+		link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
 		if (i == 0)
 			ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
 			    PhyData[0].ControllerDevHandle);
 		ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
 		attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
 		    AttachedDevHandle);
+		if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
+			link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
 		mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
-		    attached_handle, i, sas_iounit_pg0->PhyData[i].
-		    NegotiatedLinkRate >> 4);
+		    attached_handle, i, link_rate);
 	}
  out:
 	kfree(sas_iounit_pg0);
@@ -4336,14 +4363,14 @@
 }
 
 /**
- * _scsih_expander_remove - removing expander object
+ * mpt2sas_expander_remove - removing expander object
  * @ioc: per adapter object
  * @sas_address: expander sas_address
  *
  * Return nothing.
  */
-static void
-_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
+void
+mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
 {
 	struct _sas_node *sas_expander;
 	unsigned long flags;
@@ -4354,6 +4381,11 @@
 	spin_lock_irqsave(&ioc->sas_node_lock, flags);
 	sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
 	    sas_address);
+	if (!sas_expander) {
+		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+		return;
+	}
+	list_del(&sas_expander->list);
 	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
 	_scsih_expander_node_remove(ioc, sas_expander);
 }
@@ -4643,6 +4675,33 @@
 	    sas_device_backup.sas_address));
 }
 
+/**
+ * mpt2sas_device_remove - removing device object
+ * @ioc: per adapter object
+ * @sas_address: expander sas_address
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
+{
+	struct _sas_device *sas_device;
+	unsigned long flags;
+
+	if (ioc->shost_recovery)
+		return;
+
+	spin_lock_irqsave(&ioc->sas_device_lock, flags);
+	sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+	    sas_address);
+	if (!sas_device) {
+		spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+	_scsih_remove_device(ioc, sas_device);
+}
+
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 /**
  * _scsih_sas_topology_change_event_debug - debug for topology event
@@ -4737,7 +4796,7 @@
 	int i;
 	u16 parent_handle, handle;
 	u16 reason_code;
-	u8 phy_number;
+	u8 phy_number, max_phys;
 	struct _sas_node *sas_expander;
 	struct _sas_device *sas_device;
 	u64 sas_address;
@@ -4775,11 +4834,13 @@
 	sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
 	    parent_handle);
 	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-	if (sas_expander)
+	if (sas_expander) {
 		sas_address = sas_expander->sas_address;
-	else if (parent_handle < ioc->sas_hba.num_phys)
+		max_phys = sas_expander->num_phys;
+	} else if (parent_handle < ioc->sas_hba.num_phys) {
 		sas_address = ioc->sas_hba.sas_address;
-	else
+		max_phys = ioc->sas_hba.num_phys;
+	} else
 		return;
 
 	/* handle siblings events */
@@ -4793,6 +4854,8 @@
 		    ioc->pci_error_recovery)
 			return;
 		phy_number = event_data->StartPhyNum + i;
+		if (phy_number >= max_phys)
+			continue;
 		reason_code = event_data->PHY[i].PhyStatus &
 		    MPI2_EVENT_SAS_TOPO_RC_MASK;
 		if ((event_data->PHY[i].PhyStatus &
@@ -4844,7 +4907,7 @@
 	/* handle expander removal */
 	if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
 	    sas_expander)
-		_scsih_expander_remove(ioc, sas_address);
+		mpt2sas_expander_remove(ioc, sas_address);
 
 }
 
@@ -5773,90 +5836,6 @@
 }
 
 /**
- * _scsih_task_set_full - handle task set full
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Throttle back qdepth.
- */
-static void
-_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
-	*fw_event)
-{
-	unsigned long flags;
-	struct _sas_device *sas_device;
-	static struct _raid_device *raid_device;
-	struct scsi_device *sdev;
-	int depth;
-	u16 current_depth;
-	u16 handle;
-	int id, channel;
-	u64 sas_address;
-	Mpi2EventDataTaskSetFull_t *event_data = fw_event->event_data;
-
-	current_depth = le16_to_cpu(event_data->CurrentDepth);
-	handle = le16_to_cpu(event_data->DevHandle);
-	spin_lock_irqsave(&ioc->sas_device_lock, flags);
-	sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
-	if (!sas_device) {
-		spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-	id = sas_device->id;
-	channel = sas_device->channel;
-	sas_address = sas_device->sas_address;
-
-	/* if hidden raid component, then change to volume characteristics */
-	if (test_bit(handle, ioc->pd_handles) && sas_device->volume_handle) {
-		spin_lock_irqsave(&ioc->raid_device_lock, flags);
-		raid_device = _scsih_raid_device_find_by_handle(
-		    ioc, sas_device->volume_handle);
-		spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-		if (raid_device) {
-			id = raid_device->id;
-			channel = raid_device->channel;
-			handle = raid_device->handle;
-			sas_address = raid_device->wwid;
-		}
-	}
-
-	if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL)
-		starget_printk(KERN_INFO, sas_device->starget, "task set "
-		    "full: handle(0x%04x), sas_addr(0x%016llx), depth(%d)\n",
-		    handle, (unsigned long long)sas_address, current_depth);
-
-	shost_for_each_device(sdev, ioc->shost) {
-		if (sdev->id == id && sdev->channel == channel) {
-			if (current_depth > sdev->queue_depth) {
-				if (ioc->logging_level &
-				    MPT_DEBUG_TASK_SET_FULL)
-					sdev_printk(KERN_INFO, sdev, "strange "
-					    "observation, the queue depth is"
-					    " (%d) meanwhile fw queue depth "
-					    "is (%d)\n", sdev->queue_depth,
-					    current_depth);
-				continue;
-			}
-			depth = scsi_track_queue_full(sdev,
-			    current_depth - 1);
-			if (depth > 0)
-				sdev_printk(KERN_INFO, sdev, "Queue depth "
-				    "reduced to (%d)\n", depth);
-			else if (depth < 0)
-				sdev_printk(KERN_INFO, sdev, "Tagged Command "
-				    "Queueing is being disabled\n");
-			else if (depth == 0)
-				if (ioc->logging_level &
-				     MPT_DEBUG_TASK_SET_FULL)
-					sdev_printk(KERN_INFO, sdev,
-					     "Queue depth not changed yet\n");
-		}
-	}
-}
-
-/**
  * _scsih_prep_device_scan - initialize parameters prior to device scan
  * @ioc: per adapter object
  *
@@ -6219,7 +6198,7 @@
 			sas_expander->responding = 0;
 			continue;
 		}
-		_scsih_expander_remove(ioc, sas_expander->sas_address);
+		mpt2sas_expander_remove(ioc, sas_expander->sas_address);
 		goto retry_expander_search;
 	}
 }
@@ -6343,9 +6322,6 @@
 	case MPI2_EVENT_IR_OPERATION_STATUS:
 		_scsih_sas_ir_operation_status_event(ioc, fw_event);
 		break;
-	case MPI2_EVENT_TASK_SET_FULL:
-		_scsih_task_set_full(ioc, fw_event);
-		break;
 	}
 	_scsih_fw_event_free(ioc, fw_event);
 }
@@ -6415,7 +6391,6 @@
 	case MPI2_EVENT_SAS_DISCOVERY:
 	case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
 	case MPI2_EVENT_IR_PHYSICAL_DISK:
-	case MPI2_EVENT_TASK_SET_FULL:
 		break;
 
 	default: /* ignore the rest */
@@ -6490,56 +6465,23 @@
 _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
     struct _sas_node *sas_expander)
 {
-	struct _sas_port *mpt2sas_port;
-	struct _sas_device *sas_device;
-	struct _sas_node *expander_sibling;
-	unsigned long flags;
-
-	if (!sas_expander)
-		return;
+	struct _sas_port *mpt2sas_port, *next;
 
 	/* remove sibling ports attached to this expander */
- retry_device_search:
-	list_for_each_entry(mpt2sas_port,
+	list_for_each_entry_safe(mpt2sas_port, next,
 	   &sas_expander->sas_port_list, port_list) {
+		if (ioc->shost_recovery)
+			return;
 		if (mpt2sas_port->remote_identify.device_type ==
-		    SAS_END_DEVICE) {
-			spin_lock_irqsave(&ioc->sas_device_lock, flags);
-			sas_device =
-			    mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
-			   mpt2sas_port->remote_identify.sas_address);
-			spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-			if (!sas_device)
-				continue;
-			_scsih_remove_device(ioc, sas_device);
-			if (ioc->shost_recovery)
-				return;
-			goto retry_device_search;
-		}
-	}
-
- retry_expander_search:
-	list_for_each_entry(mpt2sas_port,
-	   &sas_expander->sas_port_list, port_list) {
-
-		if (mpt2sas_port->remote_identify.device_type ==
-		    MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+		    SAS_END_DEVICE)
+			mpt2sas_device_remove(ioc,
+			    mpt2sas_port->remote_identify.sas_address);
+		else if (mpt2sas_port->remote_identify.device_type ==
+		    SAS_EDGE_EXPANDER_DEVICE ||
 		    mpt2sas_port->remote_identify.device_type ==
-		    MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
-
-			spin_lock_irqsave(&ioc->sas_node_lock, flags);
-			expander_sibling =
-			    mpt2sas_scsih_expander_find_by_sas_address(
-			    ioc, mpt2sas_port->remote_identify.sas_address);
-			spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-			if (!expander_sibling)
-				continue;
-			_scsih_expander_remove(ioc,
-			    expander_sibling->sas_address);
-			if (ioc->shost_recovery)
-				return;
-			goto retry_expander_search;
-		}
+		    SAS_FANOUT_EXPANDER_DEVICE)
+			mpt2sas_expander_remove(ioc,
+			    mpt2sas_port->remote_identify.sas_address);
 	}
 
 	mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
@@ -6550,7 +6492,6 @@
 	    sas_expander->handle, (unsigned long long)
 	    sas_expander->sas_address);
 
-	list_del(&sas_expander->list);
 	kfree(sas_expander->phy);
 	kfree(sas_expander);
 }
@@ -6668,9 +6609,7 @@
 {
 	struct Scsi_Host *shost = pci_get_drvdata(pdev);
 	struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-	struct _sas_port *mpt2sas_port;
-	struct _sas_device *sas_device;
-	struct _sas_node *expander_sibling;
+	struct _sas_port *mpt2sas_port, *next_port;
 	struct _raid_device *raid_device, *next;
 	struct MPT2SAS_TARGET *sas_target_priv_data;
 	struct workqueue_struct	*wq;
@@ -6702,28 +6641,18 @@
 	}
 
 	/* free ports attached to the sas_host */
- retry_again:
-	list_for_each_entry(mpt2sas_port,
+	list_for_each_entry_safe(mpt2sas_port, next_port,
 	   &ioc->sas_hba.sas_port_list, port_list) {
 		if (mpt2sas_port->remote_identify.device_type ==
-		    SAS_END_DEVICE) {
-			sas_device =
-			    mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
-			   mpt2sas_port->remote_identify.sas_address);
-			if (sas_device) {
-				_scsih_remove_device(ioc, sas_device);
-				goto retry_again;
-			}
-		} else {
-			expander_sibling =
-			    mpt2sas_scsih_expander_find_by_sas_address(ioc,
+		    SAS_END_DEVICE)
+			mpt2sas_device_remove(ioc,
 			    mpt2sas_port->remote_identify.sas_address);
-			if (expander_sibling) {
-				_scsih_expander_remove(ioc,
-				    expander_sibling->sas_address);
-				goto retry_again;
-			}
-		}
+		else if (mpt2sas_port->remote_identify.device_type ==
+		    SAS_EDGE_EXPANDER_DEVICE ||
+		    mpt2sas_port->remote_identify.device_type ==
+		    SAS_FANOUT_EXPANDER_DEVICE)
+			mpt2sas_expander_remove(ioc,
+			    mpt2sas_port->remote_identify.sas_address);
 	}
 
 	/* free phys attached to the sas_host */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index b55c6dc..cb1cdec 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -465,62 +465,149 @@
 	return rc;
 }
 
-
 /**
- * _transport_delete_duplicate_port - (see below description)
+ * _transport_delete_port - helper function to removing a port
  * @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @sas_address: sas address of device being added
- * @phy_num: phy number
+ * @mpt2sas_port: mpt2sas per port object
  *
- * This function is called when attempting to add a new port that is claiming
- * the same phy resources already in use by another port.  If we don't release
- * the claimed phy resources, the sas transport layer will hang from the BUG
- * in sas_port_add_phy.
- *
- * The reason we would hit this issue is becuase someone is changing the
- * sas address of a device on the fly, meanwhile controller firmware sends
- * EVENTs out of order when removing the previous instance of the device.
+ * Returns nothing.
  */
 static void
-_transport_delete_duplicate_port(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_node *sas_node, u64 sas_address, int phy_num)
+_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
+	struct _sas_port *mpt2sas_port)
 {
-	struct _sas_port *mpt2sas_port, *mpt2sas_port_duplicate;
-	struct _sas_phy *mpt2sas_phy;
+	u64 sas_address = mpt2sas_port->remote_identify.sas_address;
+	enum sas_device_type device_type =
+	    mpt2sas_port->remote_identify.device_type;
 
-	printk(MPT2SAS_ERR_FMT "new device located at sas_addr(0x%016llx), "
-	    "phy_id(%d)\n", ioc->name, (unsigned long long)sas_address,
-	    phy_num);
+	dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
+	    "remove: sas_addr(0x%016llx)\n",
+	    (unsigned long long) sas_address);
 
-	mpt2sas_port_duplicate = NULL;
-	list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, port_list) {
-		dev_printk(KERN_ERR, &mpt2sas_port->port->dev,
-		    "existing device at sas_addr(0x%016llx), num_phys(%d)\n",
-		    (unsigned long long)
-		    mpt2sas_port->remote_identify.sas_address,
-		    mpt2sas_port->num_phys);
-		list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
-		    port_siblings) {
-			dev_printk(KERN_ERR, &mpt2sas_phy->phy->dev,
-			    "phy_number(%d)\n", mpt2sas_phy->phy_id);
-			if (mpt2sas_phy->phy_id == phy_num)
-				mpt2sas_port_duplicate = mpt2sas_port;
-		}
-	}
+	ioc->logging_level |= MPT_DEBUG_TRANSPORT;
+	if (device_type == SAS_END_DEVICE)
+		mpt2sas_device_remove(ioc, sas_address);
+	else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
+	    device_type == SAS_FANOUT_EXPANDER_DEVICE)
+		mpt2sas_expander_remove(ioc, sas_address);
+	ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
+}
 
-	if (!mpt2sas_port_duplicate)
+/**
+ * _transport_delete_phy - helper function to removing single phy from port
+ * @ioc: per adapter object
+ * @mpt2sas_port: mpt2sas per port object
+ * @mpt2sas_phy: mpt2sas per phy object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
+	struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
+{
+	u64 sas_address = mpt2sas_port->remote_identify.sas_address;
+
+	dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
+	    "remove: sas_addr(0x%016llx), phy(%d)\n",
+	    (unsigned long long) sas_address, mpt2sas_phy->phy_id);
+
+	list_del(&mpt2sas_phy->port_siblings);
+	mpt2sas_port->num_phys--;
+	sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
+	mpt2sas_phy->phy_belongs_to_port = 0;
+}
+
+/**
+ * _transport_add_phy - helper function to adding single phy to port
+ * @ioc: per adapter object
+ * @mpt2sas_port: mpt2sas per port object
+ * @mpt2sas_phy: mpt2sas per phy object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
+	struct _sas_phy *mpt2sas_phy)
+{
+	u64 sas_address = mpt2sas_port->remote_identify.sas_address;
+
+	dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
+	    "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
+	    sas_address, mpt2sas_phy->phy_id);
+
+	list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
+	mpt2sas_port->num_phys++;
+	sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
+	mpt2sas_phy->phy_belongs_to_port = 1;
+}
+
+/**
+ * _transport_add_phy_to_an_existing_port - adding new phy to existing port
+ * @ioc: per adapter object
+ * @sas_node: sas node object (either expander or sas host)
+ * @mpt2sas_phy: mpt2sas per phy object
+ * @sas_address: sas address of device/expander were phy needs to be added to
+ *
+ * Returns nothing.
+ */
+static void
+_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
+struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
+{
+	struct _sas_port *mpt2sas_port;
+	struct _sas_phy *phy_srch;
+
+	if (mpt2sas_phy->phy_belongs_to_port == 1)
 		return;
 
-	dev_printk(KERN_ERR, &mpt2sas_port_duplicate->port->dev,
-	    "deleting duplicate device at sas_addr(0x%016llx), phy(%d)!!!!\n",
-	    (unsigned long long)
-	    mpt2sas_port_duplicate->remote_identify.sas_address, phy_num);
-	ioc->logging_level |= MPT_DEBUG_TRANSPORT;
-	mpt2sas_transport_port_remove(ioc,
-	    mpt2sas_port_duplicate->remote_identify.sas_address,
-	    sas_node->sas_address);
-	ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
+	list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
+	    port_list) {
+		if (mpt2sas_port->remote_identify.sas_address !=
+		    sas_address)
+			continue;
+		list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
+		    port_siblings) {
+			if (phy_srch == mpt2sas_phy)
+				return;
+		}
+		_transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
+			return;
+	}
+
+}
+
+/**
+ * _transport_del_phy_from_an_existing_port - delete phy from existing port
+ * @ioc: per adapter object
+ * @sas_node: sas node object (either expander or sas host)
+ * @mpt2sas_phy: mpt2sas per phy object
+ *
+ * Returns nothing.
+ */
+static void
+_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
+	struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
+{
+	struct _sas_port *mpt2sas_port, *next;
+	struct _sas_phy *phy_srch;
+
+	if (mpt2sas_phy->phy_belongs_to_port == 0)
+		return;
+
+	list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
+	    port_list) {
+		list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
+		    port_siblings) {
+			if (phy_srch != mpt2sas_phy)
+				continue;
+			if (mpt2sas_port->num_phys == 1)
+				_transport_delete_port(ioc, mpt2sas_port);
+			else
+				_transport_delete_phy(ioc, mpt2sas_port,
+				    mpt2sas_phy);
+			return;
+		}
+	}
 }
 
 /**
@@ -537,11 +624,13 @@
 {
 	int i;
 
-	for (i = 0; i < sas_node->num_phys; i++)
-		if (sas_node->phy[i].remote_identify.sas_address == sas_address)
-			if (sas_node->phy[i].phy_belongs_to_port)
-				_transport_delete_duplicate_port(ioc, sas_node,
-					sas_address, i);
+	for (i = 0; i < sas_node->num_phys; i++) {
+		if (sas_node->phy[i].remote_identify.sas_address != sas_address)
+			continue;
+		if (sas_node->phy[i].phy_belongs_to_port == 1)
+			_transport_del_phy_from_an_existing_port(ioc, sas_node,
+			    &sas_node->phy[i]);
+	}
 }
 
 /**
@@ -905,10 +994,12 @@
 
 	mpt2sas_phy = &sas_node->phy[phy_number];
 	mpt2sas_phy->attached_handle = handle;
-	if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
+	if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
 		_transport_set_identify(ioc, handle,
 		    &mpt2sas_phy->remote_identify);
-	else
+		_transport_add_phy_to_an_existing_port(ioc, sas_node,
+		    mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
+	} else
 		memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
 		    sas_identify));
 
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index bc8194f..44578b5 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1309,6 +1309,31 @@
 }
 
 static ssize_t
+qla2x00_thermal_temp_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+	int rval = QLA_FUNCTION_FAILED;
+	uint16_t temp, frac;
+
+	if (!vha->hw->flags.thermal_supported)
+		return snprintf(buf, PAGE_SIZE, "\n");
+
+	temp = frac = 0;
+	if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
+	    test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
+		DEBUG2_3_11(printk(KERN_WARNING
+		    "%s(%ld): isp reset in progress.\n",
+		    __func__, vha->host_no));
+	else if (!vha->hw->flags.eeh_busy)
+		rval = qla2x00_get_thermal_temp(vha, &temp, &frac);
+	if (rval != QLA_SUCCESS)
+		temp = frac = 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d.%02d\n", temp, frac);
+}
+
+static ssize_t
 qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
     char *buf)
 {
@@ -1366,6 +1391,7 @@
 		   qla2x00_vn_port_mac_address_show, NULL);
 static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL);
 static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL);
+static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL);
 
 struct device_attribute *qla2x00_host_attrs[] = {
 	&dev_attr_driver_version,
@@ -1394,6 +1420,7 @@
 	&dev_attr_fabric_param,
 	&dev_attr_fw_state,
 	&dev_attr_optrom_gold_fw_version,
+	&dev_attr_thermal_temp,
 	NULL,
 };
 
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 31a4121..903b058 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -103,7 +103,7 @@
 
 	bsg_job->reply->reply_payload_rcv_len = 0;
 
-	if (!IS_QLA24XX_TYPE(ha) || !IS_QLA25XX(ha)) {
+	if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))) {
 		ret = -EINVAL;
 		goto exit_fcp_prio_cfg;
 	}
@@ -753,7 +753,7 @@
 			command_sent = INT_DEF_LB_LOOPBACK_CMD;
 			rval = qla2x00_loopback_test(vha, &elreq, response);
 
-			if (new_config[1]) {
+			if (new_config[0]) {
 				/* Revert back to original port config
 				 * Also clear internal loopback
 				 */
@@ -1512,6 +1512,7 @@
 				if (((sp_bsg->type == SRB_CT_CMD) ||
 					(sp_bsg->type == SRB_ELS_CMD_HST))
 					&& (sp_bsg->u.bsg_job == bsg_job)) {
+					spin_unlock_irqrestore(&ha->hardware_lock, flags);
 					if (ha->isp_ops->abort_command(sp)) {
 						DEBUG2(qla_printk(KERN_INFO, ha,
 						    "scsi(%ld): mbx "
@@ -1527,6 +1528,7 @@
 						bsg_job->req->errors =
 						bsg_job->reply->result = 0;
 					}
+					spin_lock_irqsave(&ha->hardware_lock, flags);
 					goto done;
 				}
 			}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 9ce539d..ccfc8e7 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2425,6 +2425,9 @@
 		uint32_t	disable_msix_handshake	:1;
 		uint32_t	fcp_prio_enabled	:1;
 		uint32_t	fw_hung	:1;
+		uint32_t        quiesce_owner:1;
+		uint32_t	thermal_supported:1;
+		/* 26 bits */
 	} flags;
 
 	/* This spinlock is used to protect "io transactions", you must
@@ -2863,6 +2866,7 @@
 #define ISP_UNRECOVERABLE	17
 #define FCOE_CTX_RESET_NEEDED	18	/* Initiate FCoE context reset */
 #define MPI_RESET_NEEDED	19	/* Initiate MPI FW reset */
+#define ISP_QUIESCE_NEEDED	20	/* Driver need some quiescence */
 
 	uint32_t	device_flags;
 #define SWITCH_FOUND		BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 9382a81..89e900a 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -36,6 +36,7 @@
 extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
 extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *);
 
+extern int qla2x00_perform_loop_resync(scsi_qla_host_t *);
 extern int qla2x00_loop_resync(scsi_qla_host_t *);
 
 extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
@@ -45,12 +46,15 @@
 
 extern int qla2x00_abort_isp(scsi_qla_host_t *);
 extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *);
+extern void qla82xx_quiescent_state_cleanup(scsi_qla_host_t *);
 
 extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
 
 extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
 extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
 
+extern int qla2x00_get_thermal_temp(scsi_qla_host_t *, uint16_t *, uint16_t *);
+
 extern void qla84xx_put_chip(struct scsi_qla_host *);
 
 extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
@@ -68,6 +72,7 @@
 extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *,
 	struct srb_iocb *);
 extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
+extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
 
 extern fc_port_t *
 qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
@@ -90,7 +95,6 @@
 extern int ql2xetsenable;
 extern int ql2xshiftctondsd;
 extern int ql2xdbwr;
-extern int ql2xdontresethba;
 extern int ql2xasynctmfenable;
 extern int ql2xgffidenable;
 extern int ql2xenabledif;
@@ -549,9 +553,11 @@
 
 /* ISP 8021 IDC */
 extern void qla82xx_clear_drv_active(struct qla_hw_data *);
+extern uint32_t  qla82xx_wait_for_state_change(scsi_qla_host_t *, uint32_t);
 extern int qla82xx_idc_lock(struct qla_hw_data *);
 extern void qla82xx_idc_unlock(struct qla_hw_data *);
 extern int qla82xx_device_state_handler(scsi_qla_host_t *);
+extern void qla82xx_clear_qsnt_ready(scsi_qla_host_t *);
 
 extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *,
     size_t, char *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 259f511..f948e1a 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -498,6 +498,7 @@
 	vha->flags.reset_active = 0;
 	ha->flags.pci_channel_io_perm_failure = 0;
 	ha->flags.eeh_busy = 0;
+	ha->flags.thermal_supported = 1;
 	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 	atomic_set(&vha->loop_state, LOOP_DOWN);
 	vha->device_flags = DFLG_NO_CABLE;
@@ -2023,6 +2024,7 @@
 	    &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
 	if (rval != QLA_SUCCESS) {
 		if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) ||
+		    IS_QLA8XXX_TYPE(ha) ||
 		    (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
 			DEBUG2(printk("%s(%ld) Loop is in a transition state\n",
 			    __func__, vha->host_no));
@@ -2928,6 +2930,7 @@
 	fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
 
 	qla2x00_iidma_fcport(vha, fcport);
+	qla24xx_update_fcport_fcp_prio(vha, fcport);
 	qla2x00_reg_remote_port(vha, fcport);
 	atomic_set(&fcport->state, FCS_ONLINE);
 }
@@ -3844,6 +3847,37 @@
 	return (rval);
 }
 
+/*
+* qla2x00_perform_loop_resync
+* Description: This function will set the appropriate flags and call
+*              qla2x00_loop_resync. If successful loop will be resynced
+* Arguments : scsi_qla_host_t pointer
+* returm    : Success or Failure
+*/
+
+int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
+{
+	int32_t rval = 0;
+
+	if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) {
+		/*Configure the flags so that resync happens properly*/
+		atomic_set(&ha->loop_down_timer, 0);
+		if (!(ha->device_flags & DFLG_NO_CABLE)) {
+			atomic_set(&ha->loop_state, LOOP_UP);
+			set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+			set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+			set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+
+			rval = qla2x00_loop_resync(ha);
+		} else
+			atomic_set(&ha->loop_state, LOOP_DEAD);
+
+		clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
+	}
+
+	return rval;
+}
+
 void
 qla2x00_update_fcports(scsi_qla_host_t *base_vha)
 {
@@ -3857,7 +3891,7 @@
 	list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
 		atomic_inc(&vha->vref_count);
 		list_for_each_entry(fcport, &vha->vp_fcports, list) {
-			if (fcport && fcport->drport &&
+			if (fcport->drport &&
 			    atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
 				spin_unlock_irqrestore(&ha->vport_slock, flags);
 
@@ -3871,11 +3905,43 @@
 	spin_unlock_irqrestore(&ha->vport_slock, flags);
 }
 
+/*
+* qla82xx_quiescent_state_cleanup
+* Description: This function will block the new I/Os
+*              Its not aborting any I/Os as context
+*              is not destroyed during quiescence
+* Arguments: scsi_qla_host_t
+* return   : void
+*/
+void
+qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha)
+{
+	struct qla_hw_data *ha = vha->hw;
+	struct scsi_qla_host *vp;
+
+	qla_printk(KERN_INFO, ha,
+			"Performing ISP error recovery - ha= %p.\n", ha);
+
+	atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
+	if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
+		atomic_set(&vha->loop_state, LOOP_DOWN);
+		qla2x00_mark_all_devices_lost(vha, 0);
+		list_for_each_entry(vp, &ha->vp_list, list)
+			qla2x00_mark_all_devices_lost(vha, 0);
+	} else {
+		if (!atomic_read(&vha->loop_down_timer))
+			atomic_set(&vha->loop_down_timer,
+					LOOP_DOWN_TIME);
+	}
+	/* Wait for pending cmds to complete */
+	qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
+}
+
 void
 qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
 {
 	struct qla_hw_data *ha = vha->hw;
-	struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
+	struct scsi_qla_host *vp;
 	unsigned long flags;
 
 	vha->flags.online = 0;
@@ -3896,7 +3962,7 @@
 		qla2x00_mark_all_devices_lost(vha, 0);
 
 		spin_lock_irqsave(&ha->vport_slock, flags);
-		list_for_each_entry(vp, &base_vha->hw->vp_list, list) {
+		list_for_each_entry(vp, &ha->vp_list, list) {
 			atomic_inc(&vp->vref_count);
 			spin_unlock_irqrestore(&ha->vport_slock, flags);
 
@@ -5410,7 +5476,7 @@
  *	the tag (priority) value is returned.
  *
  * Input:
- *	ha = adapter block po
+ *	vha = scsi host structure pointer.
  *	fcport = port structure pointer.
  *
  * Return:
@@ -5504,7 +5570,7 @@
  *	Activates fcp priority for the logged in fc port
  *
  * Input:
- *	ha = adapter block pointer.
+ *	vha = scsi host structure pointer.
  *	fcp = port structure pointer.
  *
  * Return:
@@ -5514,25 +5580,24 @@
  *	Kernel context.
  */
 int
-qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *ha, fc_port_t *fcport)
+qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
 {
 	int ret;
 	uint8_t priority;
 	uint16_t mb[5];
 
-	if (atomic_read(&fcport->state) == FCS_UNCONFIGURED ||
-		fcport->port_type != FCT_TARGET ||
-		fcport->loop_id == FC_NO_LOOP_ID)
+	if (fcport->port_type != FCT_TARGET ||
+	    fcport->loop_id == FC_NO_LOOP_ID)
 		return QLA_FUNCTION_FAILED;
 
-	priority = qla24xx_get_fcp_prio(ha, fcport);
-	ret = qla24xx_set_fcp_prio(ha, fcport->loop_id, priority, mb);
+	priority = qla24xx_get_fcp_prio(vha, fcport);
+	ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb);
 	if (ret == QLA_SUCCESS)
 		fcport->fcp_prio = priority;
 	else
 		DEBUG2(printk(KERN_WARNING
 			"scsi(%ld): Unable to activate fcp priority, "
-			" ret=0x%x\n", ha->host_no, ret));
+			" ret=0x%x\n", vha->host_no, ret));
 
 	return  ret;
 }
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 7f77898..d17ed9a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -321,6 +321,7 @@
 	struct qla_hw_data *ha = vha->hw;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 	struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
+	struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
 	uint32_t	rscn_entry, host_pid;
 	uint8_t		rscn_queue_index;
 	unsigned long	flags;
@@ -498,6 +499,7 @@
 
 	case MBA_LOOP_DOWN:		/* Loop Down Event */
 		mbx = IS_QLA81XX(ha) ? RD_REG_WORD(&reg24->mailbox4) : 0;
+		mbx = IS_QLA82XX(ha) ? RD_REG_WORD(&reg82->mailbox_out[4]) : mbx;
 		DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
 		    "(%x %x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3],
 		    mbx));
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index effd8a1..e473e9f 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -4125,7 +4125,7 @@
 		return QLA_FUNCTION_FAILED;
 
 	DEBUG11(printk(KERN_INFO
-	    "%s(%ld): entered.\n", __func__, ha->host_no));
+	    "%s(%ld): entered.\n", __func__, vha->host_no));
 
 	mcp->mb[0] = MBC_PORT_PARAMS;
 	mcp->mb[1] = loop_id;
@@ -4160,6 +4160,71 @@
 }
 
 int
+qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
+{
+	int rval;
+	mbx_cmd_t mc;
+	mbx_cmd_t *mcp = &mc;
+	struct qla_hw_data *ha = vha->hw;
+
+	DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, ha->host_no));
+
+	/* High bits. */
+	mcp->mb[0] = MBC_READ_SFP;
+	mcp->mb[1] = 0x98;
+	mcp->mb[2] = 0;
+	mcp->mb[3] = 0;
+	mcp->mb[6] = 0;
+	mcp->mb[7] = 0;
+	mcp->mb[8] = 1;
+	mcp->mb[9] = 0x01;
+	mcp->mb[10] = BIT_13|BIT_0;
+	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_1|MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(vha, mcp);
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk(KERN_WARNING
+		    "%s(%ld): failed=%x (%x).\n", __func__,
+		    vha->host_no, rval, mcp->mb[0]));
+		ha->flags.thermal_supported = 0;
+		goto fail;
+	}
+	*temp = mcp->mb[1] & 0xFF;
+
+	/* Low bits. */
+	mcp->mb[0] = MBC_READ_SFP;
+	mcp->mb[1] = 0x98;
+	mcp->mb[2] = 0;
+	mcp->mb[3] = 0;
+	mcp->mb[6] = 0;
+	mcp->mb[7] = 0;
+	mcp->mb[8] = 1;
+	mcp->mb[9] = 0x10;
+	mcp->mb[10] = BIT_13|BIT_0;
+	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+	mcp->in_mb = MBX_1|MBX_0;
+	mcp->tov = MBX_TOV_SECONDS;
+	mcp->flags = 0;
+	rval = qla2x00_mailbox_command(vha, mcp);
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk(KERN_WARNING
+		    "%s(%ld): failed=%x (%x).\n", __func__,
+		    vha->host_no, rval, mcp->mb[0]));
+		ha->flags.thermal_supported = 0;
+		goto fail;
+	}
+	*frac = ((mcp->mb[1] & 0xFF) >> 6) * 25;
+
+	if (rval == QLA_SUCCESS)
+		DEBUG11(printk(KERN_INFO
+		    "%s(%ld): done.\n", __func__, ha->host_no));
+fail:
+	return rval;
+}
+
+int
 qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
 {
 	int rval;
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index ae2acac..fdb96a3 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -1079,11 +1079,55 @@
 
 	/* Halt all the indiviual PEGs and other blocks of the ISP */
 	qla82xx_rom_lock(ha);
+
+	/* mask all niu interrupts */
+	qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff);
+	/* disable xge rx/tx */
+	qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00);
+	/* disable xg1 rx/tx */
+	qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00);
+
+	/* halt sre */
+	val = qla82xx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000);
+	qla82xx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1)));
+
+	/* halt epg */
+	qla82xx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1);
+
+	/* halt timers */
+	qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0);
+	qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0);
+
+	/* halt pegs */
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1);
+	qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1);
+
+	/* big hammer */
+	msleep(1000);
 	if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
 		/* don't reset CAM block on reset */
 		qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff);
 	else
 		qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff);
+
+	/* reset ms */
+	val = qla82xx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+	val |= (1 << 1);
+	qla82xx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+	msleep(20);
+
+	/* unreset ms */
+	val = qla82xx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+	val &= ~(1 << 1);
+	qla82xx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+	msleep(20);
+
 	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
 
 	/* Read the signature value from the flash.
@@ -1210,25 +1254,6 @@
 }
 
 static int
-qla82xx_check_for_bad_spd(struct qla_hw_data *ha)
-{
-	u32 val = 0;
-	val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS);
-	val &= QLA82XX_BOOT_LOADER_MN_ISSUE;
-	if (val & QLA82XX_PEG_TUNE_MN_SPD_ZEROED) {
-		qla_printk(KERN_INFO, ha,
-			"Memory DIMM SPD not programmed. "
-			" Assumed valid.\n");
-		return 1;
-	} else if (val) {
-		qla_printk(KERN_INFO, ha,
-			"Memory DIMM type incorrect.Info:%08X.\n", val);
-		return 2;
-	}
-	return 0;
-}
-
-static int
 qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
 		u64 off, void *data, int size)
 {
@@ -1293,11 +1318,6 @@
 		word[startword+1] |= tmpw >> (sz[0] * 8);
 	}
 
-	/*
-	 * don't lock here - write_wx gets the lock if each time
-	 * write_lock_irqsave(&adapter->adapter_lock, flags);
-	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
-	 */
 	for (i = 0; i < loop; i++) {
 		temp = off8 + (i << shift_amount);
 		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
@@ -1399,12 +1419,6 @@
 	off0[1] = 0;
 	sz[1] = size - sz[0];
 
-	/*
-	 * don't lock here - write_wx gets the lock if each time
-	 * write_lock_irqsave(&adapter->adapter_lock, flags);
-	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
-	 */
-
 	for (i = 0; i < loop; i++) {
 		temp = off8 + (i << shift_amount);
 		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
@@ -1437,11 +1451,6 @@
 		}
 	}
 
-	/*
-	 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
-	 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
-	 */
-
 	if (j >= MAX_CTL_CHECK)
 		return -1;
 
@@ -1872,7 +1881,6 @@
 	qla_printk(KERN_INFO, ha,
 	    "Cmd Peg initialization failed: 0x%x.\n", val);
 
-	qla82xx_check_for_bad_spd(ha);
 	val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_PEGTUNE_DONE);
 	read_lock(&ha->hw_lock);
 	qla82xx_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
@@ -2343,6 +2351,17 @@
 	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
 }
 
+void
+qla82xx_clear_qsnt_ready(scsi_qla_host_t *vha)
+{
+	struct qla_hw_data *ha = vha->hw;
+	uint32_t qsnt_state;
+
+	qsnt_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+	qsnt_state &= ~(QLA82XX_DRVST_QSNT_RDY << (ha->portnum * 4));
+	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
+}
+
 static int
 qla82xx_load_fw(scsi_qla_host_t *vha)
 {
@@ -2542,7 +2561,7 @@
 			*cur_dsd++ = cpu_to_le32(LSD(sle_dma));
 			*cur_dsd++ = cpu_to_le32(MSD(sle_dma));
 			*cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
-			cur_seg++;
+			cur_seg = sg_next(cur_seg);
 			avail_dsds--;
 		}
 	}
@@ -3261,6 +3280,104 @@
 	return QLA_SUCCESS;
 }
 
+/*
+* qla82xx_need_qsnt_handler
+*    Code to start quiescence sequence
+*
+* Note:
+*      IDC lock must be held upon entry
+*
+* Return: void
+*/
+
+static void
+qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
+{
+	struct qla_hw_data *ha = vha->hw;
+	uint32_t dev_state, drv_state, drv_active;
+	unsigned long reset_timeout;
+
+	if (vha->flags.online) {
+		/*Block any further I/O and wait for pending cmnds to complete*/
+		qla82xx_quiescent_state_cleanup(vha);
+	}
+
+	/* Set the quiescence ready bit */
+	qla82xx_set_qsnt_ready(ha);
+
+	/*wait for 30 secs for other functions to ack */
+	reset_timeout = jiffies + (30 * HZ);
+
+	drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+	drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+	/* Its 2 that is written when qsnt is acked, moving one bit */
+	drv_active = drv_active << 0x01;
+
+	while (drv_state != drv_active) {
+
+		if (time_after_eq(jiffies, reset_timeout)) {
+			/* quiescence timeout, other functions didn't ack
+			 * changing the state to DEV_READY
+			 */
+			qla_printk(KERN_INFO, ha,
+			    "%s: QUIESCENT TIMEOUT\n", QLA2XXX_DRIVER_NAME);
+			qla_printk(KERN_INFO, ha,
+			    "DRV_ACTIVE:%d DRV_STATE:%d\n", drv_active,
+			    drv_state);
+			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+						QLA82XX_DEV_READY);
+			qla_printk(KERN_INFO, ha,
+			    "HW State: DEV_READY\n");
+			qla82xx_idc_unlock(ha);
+			qla2x00_perform_loop_resync(vha);
+			qla82xx_idc_lock(ha);
+
+			qla82xx_clear_qsnt_ready(vha);
+			return;
+		}
+
+		qla82xx_idc_unlock(ha);
+		msleep(1000);
+		qla82xx_idc_lock(ha);
+
+		drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
+		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+		drv_active = drv_active << 0x01;
+	}
+	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+	/* everyone acked so set the state to DEV_QUIESCENCE */
+	if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) {
+		qla_printk(KERN_INFO, ha, "HW State: DEV_QUIESCENT\n");
+		qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT);
+	}
+}
+
+/*
+* qla82xx_wait_for_state_change
+*    Wait for device state to change from given current state
+*
+* Note:
+*     IDC lock must not be held upon entry
+*
+* Return:
+*    Changed device state.
+*/
+uint32_t
+qla82xx_wait_for_state_change(scsi_qla_host_t *vha, uint32_t curr_state)
+{
+	struct qla_hw_data *ha = vha->hw;
+	uint32_t dev_state;
+
+	do {
+		msleep(1000);
+		qla82xx_idc_lock(ha);
+		dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+		qla82xx_idc_unlock(ha);
+	} while (dev_state == curr_state);
+
+	return dev_state;
+}
+
 static void
 qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
 {
@@ -3439,15 +3556,28 @@
 			qla82xx_idc_lock(ha);
 			break;
 		case QLA82XX_DEV_NEED_RESET:
-			if (!ql2xdontresethba)
-				qla82xx_need_reset_handler(vha);
+			qla82xx_need_reset_handler(vha);
 			break;
 		case QLA82XX_DEV_NEED_QUIESCENT:
-			qla82xx_set_qsnt_ready(ha);
+			qla82xx_need_qsnt_handler(vha);
+			/* Reset timeout value after quiescence handler */
+			dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
+							 * HZ);
+			break;
 		case QLA82XX_DEV_QUIESCENT:
+			/* Owner will exit and other will wait for the state
+			 * to get changed
+			 */
+			if (ha->flags.quiesce_owner)
+				goto exit;
+
 			qla82xx_idc_unlock(ha);
 			msleep(1000);
 			qla82xx_idc_lock(ha);
+
+			/* Reset timeout value after quiescence handler */
+			dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
+							 * HZ);
 			break;
 		case QLA82XX_DEV_FAILED:
 			qla82xx_dev_failed_handler(vha);
@@ -3490,6 +3620,13 @@
 					&ha->mbx_cmd_flags))
 					complete(&ha->mbx_intr_comp);
 			}
+		} else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
+			!test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
+			DEBUG(qla_printk(KERN_INFO, ha,
+				"scsi(%ld) %s - detected quiescence needed\n",
+				vha->host_no, __func__));
+			set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
+			qla2xxx_wake_dpc(vha);
 		} else {
 			qla82xx_check_fw_alive(vha);
 		}
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 51ec0c5..ed5883f 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -523,8 +523,6 @@
 # define QLA82XX_CAM_RAM_BASE		(QLA82XX_CRB_CAM + 0x02000)
 # define QLA82XX_CAM_RAM(reg)		(QLA82XX_CAM_RAM_BASE + (reg))
 
-#define QLA82XX_PEG_TUNE_MN_SPD_ZEROED	0x80000000
-#define QLA82XX_BOOT_LOADER_MN_ISSUE	0xff00ffff
 #define QLA82XX_PORT_MODE_ADDR		(QLA82XX_CAM_RAM(0x24))
 #define QLA82XX_PEG_HALT_STATUS1	(QLA82XX_CAM_RAM(0xa8))
 #define QLA82XX_PEG_HALT_STATUS2	(QLA82XX_CAM_RAM(0xac))
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2c0876c..c194c23 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -37,12 +37,12 @@
 static struct kmem_cache *ctx_cachep;
 
 int ql2xlogintimeout = 20;
-module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
+module_param(ql2xlogintimeout, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xlogintimeout,
 		"Login timeout value in seconds.");
 
 int qlport_down_retry;
-module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
+module_param(qlport_down_retry, int, S_IRUGO);
 MODULE_PARM_DESC(qlport_down_retry,
 		"Maximum number of command retries to a port that returns "
 		"a PORT-DOWN status.");
@@ -55,12 +55,12 @@
 		"Default is 0 - no PLOGI. 1 - perfom PLOGI.");
 
 int ql2xloginretrycount = 0;
-module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
+module_param(ql2xloginretrycount, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xloginretrycount,
 		"Specify an alternate value for the NVRAM login retry count.");
 
 int ql2xallocfwdump = 1;
-module_param(ql2xallocfwdump, int, S_IRUGO|S_IRUSR);
+module_param(ql2xallocfwdump, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xallocfwdump,
 		"Option to enable allocation of memory for a firmware dump "
 		"during HBA initialization.  Memory allocation requirements "
@@ -73,7 +73,7 @@
 		"Default is 0 - no logging. 1 - log errors.");
 
 int ql2xshiftctondsd = 6;
-module_param(ql2xshiftctondsd, int, S_IRUGO|S_IRUSR);
+module_param(ql2xshiftctondsd, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xshiftctondsd,
 		"Set to control shifting of command type processing "
 		"based on total number of SG elements.");
@@ -81,7 +81,7 @@
 static void qla2x00_free_device(scsi_qla_host_t *);
 
 int ql2xfdmienable=1;
-module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xfdmienable, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xfdmienable,
 		"Enables FDMI registrations. "
 		"0 - no FDMI. Default is 1 - perform FDMI.");
@@ -106,27 +106,27 @@
 		" Default is 0 - Error isolation disabled, 1 - Enable it");
 
 int ql2xiidmaenable=1;
-module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xiidmaenable, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xiidmaenable,
 		"Enables iIDMA settings "
 		"Default is 1 - perform iIDMA. 0 - no iIDMA.");
 
 int ql2xmaxqueues = 1;
-module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR);
+module_param(ql2xmaxqueues, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xmaxqueues,
 		"Enables MQ settings "
 		"Default is 1 for single queue. Set it to number "
 		"of queues in MQ mode.");
 
 int ql2xmultique_tag;
-module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR);
+module_param(ql2xmultique_tag, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xmultique_tag,
 		"Enables CPU affinity settings for the driver "
 		"Default is 0 for no affinity of request and response IO. "
 		"Set it to 1 to turn on the cpu affinity.");
 
 int ql2xfwloadbin;
-module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
+module_param(ql2xfwloadbin, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xfwloadbin,
 		"Option to specify location from which to load ISP firmware:\n"
 		" 2 -- load firmware via the request_firmware() (hotplug)\n"
@@ -135,39 +135,32 @@
 		" 0 -- use default semantics.\n");
 
 int ql2xetsenable;
-module_param(ql2xetsenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xetsenable, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xetsenable,
 		"Enables firmware ETS burst."
 		"Default is 0 - skip ETS enablement.");
 
 int ql2xdbwr = 1;
-module_param(ql2xdbwr, int, S_IRUGO|S_IRUSR);
+module_param(ql2xdbwr, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xdbwr,
 	"Option to specify scheme for request queue posting\n"
 	" 0 -- Regular doorbell.\n"
 	" 1 -- CAMRAM doorbell (faster).\n");
 
-int ql2xdontresethba;
-module_param(ql2xdontresethba, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ql2xdontresethba,
-	"Option to specify reset behaviour\n"
-	" 0 (Default) -- Reset on failure.\n"
-	" 1 -- Do not reset on failure.\n");
-
 int ql2xtargetreset = 1;
-module_param(ql2xtargetreset, int, S_IRUGO|S_IRUSR);
+module_param(ql2xtargetreset, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xtargetreset,
 		 "Enable target reset."
 		 "Default is 1 - use hw defaults.");
 
 int ql2xgffidenable;
-module_param(ql2xgffidenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xgffidenable, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xgffidenable,
 		"Enables GFF_ID checks of port type. "
 		"Default is 0 - Do not use GFF_ID information.");
 
 int ql2xasynctmfenable;
-module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR);
+module_param(ql2xasynctmfenable, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xasynctmfenable,
 		"Enables issue of TM IOCBs asynchronously via IOCB mechanism"
 		"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
@@ -2371,7 +2364,7 @@
 	list_for_each_entry(vha, &ha->vp_list, list) {
 		atomic_inc(&vha->vref_count);
 
-		if (vha && vha->fc_vport) {
+		if (vha->fc_vport) {
 			spin_unlock_irqrestore(&ha->vport_slock, flags);
 
 			fc_vport_terminate(vha->fc_vport);
@@ -3386,6 +3379,21 @@
 			clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
 		}
 
+		if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
+			DEBUG(printk(KERN_INFO "scsi(%ld): dpc: sched "
+			    "qla2x00_quiesce_needed ha = %p\n",
+			    base_vha->host_no, ha));
+			qla82xx_device_state_handler(base_vha);
+			clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags);
+			if (!ha->flags.quiesce_owner) {
+				qla2x00_perform_loop_resync(base_vha);
+
+				qla82xx_idc_lock(ha);
+				qla82xx_clear_qsnt_ready(base_vha);
+				qla82xx_idc_unlock(ha);
+			}
+		}
+
 		if (test_and_clear_bit(RESET_MARKER_NEEDED,
 							&base_vha->dpc_flags) &&
 		    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
@@ -3589,13 +3597,16 @@
 		return;
 	}
 
-	if (IS_QLA82XX(ha))
-		qla82xx_watchdog(vha);
-
 	/* Hardware read to raise pending EEH errors during mailbox waits. */
 	if (!pci_channel_offline(ha->pdev))
 		pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
 
+	if (IS_QLA82XX(ha)) {
+		if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags))
+			start_dpc++;
+		qla82xx_watchdog(vha);
+	}
+
 	/* Loop down handler. */
 	if (atomic_read(&vha->loop_down_timer) > 0 &&
 	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 76de957..2207062 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -669,6 +669,13 @@
 		def = 1;
 	else if (IS_QLA81XX(ha))
 		def = 2;
+
+	/* Assign FCP prio region since older adapters may not have FLT, or
+	   FCP prio region in it's FLT.
+	 */
+	ha->flt_region_fcp_prio = ha->flags.port0 ?
+	    fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
+
 	ha->flt_region_flt = flt_addr;
 	wptr = (uint16_t *)req->ring;
 	flt = (struct qla_flt_header *)req->ring;
@@ -696,10 +703,6 @@
 		goto no_flash_data;
 	}
 
-	/* Assign FCP prio region since older FLT's may not have it */
-	ha->flt_region_fcp_prio = ha->flags.port0 ?
-	    fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
-
 	loc = locations[1];
 	cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region);
 	for ( ; cnt; cnt--, region++) {
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c
index edcf048..af62c3c 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.c
+++ b/drivers/scsi/qla4xxx/ql4_dbg.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h
index d861c3b..abd8360 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.h
+++ b/drivers/scsi/qla4xxx/ql4_dbg.h
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 0f3bfc3..2fc0045 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
@@ -175,7 +175,7 @@
 struct srb {
 	struct list_head list;	/* (8)	 */
 	struct scsi_qla_host *ha;	/* HA the SP is queued on */
-	struct ddb_entry	*ddb;
+	struct ddb_entry *ddb;
 	uint16_t flags;		/* (1) Status flags. */
 
 #define SRB_DMA_VALID		BIT_3	/* DMA Buffer mapped. */
@@ -191,7 +191,6 @@
 	struct scsi_cmnd *cmd;	/* (4) SCSI command block */
 	dma_addr_t dma_handle;	/* (4) for unmap of single transfers */
 	struct kref srb_ref;	/* reference count for this srb */
-	uint32_t fw_ddb_index;
 	uint8_t err_id;		/* error id */
 #define SRB_ERR_PORT	   1	/* Request failed because "port down" */
 #define SRB_ERR_LOOP	   2	/* Request failed because "loop down" */
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 5e757d7..c198579 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 6575a47..8fad99b 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index dc01fa3..1629c48 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h
index 9471ac7..62f90bd 100644
--- a/drivers/scsi/qla4xxx/ql4_inline.h
+++ b/drivers/scsi/qla4xxx/ql4_inline.h
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 5ae49fd..75fcd82 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 7c33fd5..6ffbe97 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
@@ -554,7 +554,8 @@
 			/* mbox_sts[2] = Old ACB state
 			 * mbox_sts[3] = new ACB state */
 			if ((mbox_sts[3] == ACB_STATE_VALID) &&
-			    (mbox_sts[2] == ACB_STATE_TENTATIVE))
+			    ((mbox_sts[2] == ACB_STATE_TENTATIVE) ||
+			    (mbox_sts[2] == ACB_STATE_ACQUIRING)))
 				set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
 			else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
 			    (mbox_sts[2] == ACB_STATE_VALID))
@@ -1077,7 +1078,7 @@
 	ret = pci_enable_msi(ha->pdev);
 	if (!ret) {
 		ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler,
-			IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha);
+			0, DRIVER_NAME, ha);
 		if (!ret) {
 			DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
 			set_bit(AF_MSI_ENABLED, &ha->flags);
@@ -1095,7 +1096,7 @@
 try_intx:
 	/* Trying INTx */
 	ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
-	    IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha);
+	    IRQF_SHARED, DRIVER_NAME, ha);
 	if (!ret) {
 		DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n"));
 		set_bit(AF_INTx_ENABLED, &ha->flags);
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 2d2f9c8..f65626a 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
@@ -81,23 +81,7 @@
 	 */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
-	if (is_qla8022(ha)) {
-		intr_status = readl(&ha->qla4_8xxx_reg->host_int);
-		if (intr_status & ISRX_82XX_RISC_INT) {
-			/* Service existing interrupt */
-			DEBUG2(printk("scsi%ld: %s: "
-			    "servicing existing interrupt\n",
-			    ha->host_no, __func__));
-			intr_status = readl(&ha->qla4_8xxx_reg->host_status);
-			ha->isp_ops->interrupt_service_routine(ha, intr_status);
-			clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
-			if (test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
-			    test_bit(AF_INTx_ENABLED, &ha->flags))
-				qla4_8xxx_wr_32(ha,
-				    ha->nx_legacy_intr.tgt_mask_reg,
-				    0xfbff);
-		}
-	} else {
+	if (!is_qla8022(ha)) {
 		intr_status = readl(&ha->reg->ctrl_status);
 		if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
 			/* Service existing interrupt */
@@ -934,7 +918,7 @@
 		return status;
 
 	mbox_cmd[0] = MBOX_CMD_ABORT_TASK;
-	mbox_cmd[1] = srb->fw_ddb_index;
+	mbox_cmd[1] = srb->ddb->fw_ddb_index;
 	mbox_cmd[2] = index;
 	/* Immediate Command Enable */
 	mbox_cmd[5] = 0x01;
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index f0d0fbf..b4b859b 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h
index 7a8fc66..b3831bd2 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.h
+++ b/drivers/scsi/qla4xxx/ql4_nvram.h
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 474b10d..3d5ef2d 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2009 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
@@ -942,12 +942,55 @@
 
 	/* Halt all the indiviual PEGs and other blocks of the ISP */
 	qla4_8xxx_rom_lock(ha);
+
+	/* mask all niu interrupts */
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff);
+	/* disable xge rx/tx */
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00);
+	/* disable xg1 rx/tx */
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00);
+
+	/* halt sre */
+	val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1)));
+
+	/* halt epg */
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1);
+
+	/* halt timers */
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0);
+
+	/* halt pegs */
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1);
+
+	/* big hammer */
+	msleep(1000);
 	if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
 		/* don't reset CAM block on reset */
 		qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff);
 	else
 		qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff);
 
+	/* reset ms */
+	val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+	val |= (1 << 1);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+
+	msleep(20);
+	/* unreset ms */
+	val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
+	val &= ~(1 << 1);
+	qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
+	msleep(20);
+
 	qla4_8xxx_rom_unlock(ha);
 
 	/* Read the signature value from the flash.
@@ -1084,14 +1127,14 @@
 static int
 qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start)
 {
-	int  i;
+	int  i, rval = 0;
 	long size = 0;
 	long flashaddr, memaddr;
 	u64 data;
 	u32 high, low;
 
 	flashaddr = memaddr = ha->hw.flt_region_bootload;
-	size = (image_start - flashaddr)/8;
+	size = (image_start - flashaddr) / 8;
 
 	DEBUG2(printk("scsi%ld: %s: bootldr=0x%lx, fw_image=0x%x\n",
 	    ha->host_no, __func__, flashaddr, image_start));
@@ -1100,14 +1143,18 @@
 		if ((qla4_8xxx_rom_fast_read(ha, flashaddr, (int *)&low)) ||
 		    (qla4_8xxx_rom_fast_read(ha, flashaddr + 4,
 		    (int *)&high))) {
-			return -1;
+			rval = -1;
+			goto exit_load_from_flash;
 		}
 		data = ((u64)high << 32) | low ;
-		qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8);
+		rval = qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8);
+		if (rval)
+			goto exit_load_from_flash;
+
 		flashaddr += 8;
 		memaddr   += 8;
 
-		if (i%0x1000 == 0)
+		if (i % 0x1000 == 0)
 			msleep(1);
 
 	}
@@ -1119,7 +1166,8 @@
 	qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e);
 	read_unlock(&ha->hw_lock);
 
-	return 0;
+exit_load_from_flash:
+	return rval;
 }
 
 static int qla4_8xxx_load_fw(struct scsi_qla_host *ha, uint32_t image_start)
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h
index ff689bf..35376a1 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.h
+++ b/drivers/scsi/qla4xxx/ql4_nx.h
@@ -1,8 +1,8 @@
 /*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2008 QLogic Corporation
+ * QLogic iSCSI HBA Driver
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
- * See LICENSE.qla2xxx for copyright and licensing details.
+ * See LICENSE.qla4xxx for copyright and licensing details.
  */
 #ifndef __QLA_NX_H
 #define __QLA_NX_H
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 0d48fb4..3fc1d25 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -1,6 +1,6 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
@@ -706,18 +706,22 @@
 	dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
 
 	/* don't poll if reset is going on */
-	if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags)) {
+	if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
+	    test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
+	    test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags))) {
 		if (dev_state == QLA82XX_DEV_NEED_RESET &&
 		    !test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
-			printk("scsi%ld: %s: HW State: NEED RESET!\n",
-			    ha->host_no, __func__);
-			set_bit(DPC_RESET_HA, &ha->dpc_flags);
-			qla4xxx_wake_dpc(ha);
-			qla4xxx_mailbox_premature_completion(ha);
+			if (!ql4xdontresethba) {
+				ql4_printk(KERN_INFO, ha, "%s: HW State: "
+				    "NEED RESET!\n", __func__);
+				set_bit(DPC_RESET_HA, &ha->dpc_flags);
+				qla4xxx_wake_dpc(ha);
+				qla4xxx_mailbox_premature_completion(ha);
+			}
 		} else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
 		    !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
-			printk("scsi%ld: %s: HW State: NEED QUIES!\n",
-			    ha->host_no, __func__);
+			ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n",
+			    __func__);
 			set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags);
 			qla4xxx_wake_dpc(ha);
 		} else  {
@@ -1721,6 +1725,14 @@
 	if (!test_bit(AF_ONLINE, &ha->flags)) {
 		ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n");
 
+		if (is_qla8022(ha) && ql4xdontresethba) {
+			/* Put the device in failed state. */
+			DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n"));
+			qla4_8xxx_idc_lock(ha);
+			qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+			    QLA82XX_DEV_FAILED);
+			qla4_8xxx_idc_unlock(ha);
+		}
 		ret = -ENODEV;
 		goto probe_failed;
 	}
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 9bfacf4..8475b30 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -1,8 +1,8 @@
 /*
  * QLogic iSCSI HBA Driver
- * Copyright (c)  2003-2006 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION	"5.02.00-k4"
+#define QLA4XXX_DRIVER_VERSION	"5.02.00-k5"
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 2f1f9b0..7b31093 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1805,6 +1805,7 @@
 			devip->sense_buff[5] = (ret >> 8) & 0xff;
 			devip->sense_buff[6] = ret & 0xff;
 		}
+	        scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
 		return check_condition_result;
 	}
 
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 30ac116..45c7564 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1124,51 +1124,40 @@
 				struct list_head *work_q,
 				struct list_head *done_q)
 {
-	struct scsi_cmnd *scmd, *tgtr_scmd, *next;
-	unsigned int id = 0;
-	int rtn;
+	LIST_HEAD(tmp_list);
 
-	do {
-		tgtr_scmd = NULL;
-		list_for_each_entry(scmd, work_q, eh_entry) {
-			if (id == scmd_id(scmd)) {
-				tgtr_scmd = scmd;
-				break;
-			}
-		}
-		if (!tgtr_scmd) {
-			/* not one exactly equal; find the next highest */
-			list_for_each_entry(scmd, work_q, eh_entry) {
-				if (scmd_id(scmd) > id &&
-				    (!tgtr_scmd ||
-				     scmd_id(tgtr_scmd) > scmd_id(scmd)))
-						tgtr_scmd = scmd;
-			}
-		}
-		if (!tgtr_scmd)
-			/* no more commands, that's it */
-			break;
+	list_splice_init(work_q, &tmp_list);
+
+	while (!list_empty(&tmp_list)) {
+		struct scsi_cmnd *next, *scmd;
+		int rtn;
+		unsigned int id;
+
+		scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
+		id = scmd_id(scmd);
 
 		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
 						  "to target %d\n",
 						  current->comm, id));
-		rtn = scsi_try_target_reset(tgtr_scmd);
-		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
-			list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
-				if (id == scmd_id(scmd))
-					if (!scsi_device_online(scmd->device) ||
-					    rtn == FAST_IO_FAIL ||
-					    !scsi_eh_tur(tgtr_scmd))
-						scsi_eh_finish_cmd(scmd,
-								   done_q);
-			}
-		} else
+		rtn = scsi_try_target_reset(scmd);
+		if (rtn != SUCCESS && rtn != FAST_IO_FAIL)
 			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset"
 							  " failed target: "
 							  "%d\n",
 							  current->comm, id));
-		id++;
-	} while(id != 0);
+		list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) {
+			if (scmd_id(scmd) != id)
+				continue;
+
+			if ((rtn == SUCCESS || rtn == FAST_IO_FAIL)
+			    && (!scsi_device_online(scmd->device) ||
+				 rtn == FAST_IO_FAIL || !scsi_eh_tur(scmd)))
+				scsi_eh_finish_cmd(scmd, done_q);
+			else
+				/* push back on work queue for further processing */
+				list_move(&scmd->eh_entry, work_q);
+		}
+	}
 
 	return list_empty(work_q);
 }
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4a38422..501f67b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1278,11 +1278,10 @@
 	}
 
 	if (scsi_target_is_busy(starget)) {
-		if (list_empty(&sdev->starved_entry)) {
+		if (list_empty(&sdev->starved_entry))
 			list_add_tail(&sdev->starved_entry,
 				      &shost->starved_list);
-			return 0;
-		}
+		return 0;
 	}
 
 	/* We're OK to process the command, so we can't be starved */
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 76ee2e7..4c68d36 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -993,16 +993,14 @@
  */
 void scsi_remove_target(struct device *dev)
 {
-	struct device *rdev;
-
 	if (scsi_is_target_device(dev)) {
 		__scsi_remove_target(to_scsi_target(dev));
 		return;
 	}
 
-	rdev = get_device(dev);
+	get_device(dev);
 	device_for_each_child(dev, NULL, __remove_child);
-	put_device(rdev);
+	put_device(dev);
 }
 EXPORT_SYMBOL(scsi_remove_target);
 
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 332387a..f905ecb 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -2200,3 +2200,4 @@
 MODULE_DESCRIPTION("iSCSI Transport Interface");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 9564961..365024b0 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -583,7 +583,7 @@
 		 * quietly refuse to do anything to a changed disc until 
 		 * the changed bit has been reset
 		 */
-		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
+		/* printk("SCSI disk has been changed or is not present. Prohibiting further I/O.\n"); */
 		goto out;
 	}
 
@@ -1023,7 +1023,6 @@
 	 */
 	if (!scsi_device_online(sdp)) {
 		set_media_not_present(sdkp);
-		retval = 1;
 		goto out;
 	}
 
@@ -1054,7 +1053,6 @@
 		       /* 0x3a is medium not present */
 		       sshdr->asc == 0x3a)) {
 		set_media_not_present(sdkp);
-		retval = 1;
 		goto out;
 	}
 
@@ -1065,12 +1063,27 @@
 	 */
 	sdkp->media_present = 1;
 
-	retval = sdp->changed;
-	sdp->changed = 0;
 out:
-	if (retval != sdkp->previous_state)
+	/*
+	 * Report a media change under the following conditions:
+	 *
+	 *	Medium is present now and wasn't present before.
+	 *	Medium wasn't present before and is present now.
+	 *	Medium was present at all times, but it changed while
+	 *		we weren't looking (sdp->changed is set).
+	 *
+	 * If there was no medium before and there is no medium now then
+	 * don't report a change, even if a medium was inserted and removed
+	 * while we weren't looking.
+	 */
+	retval = (sdkp->media_present != sdkp->previous_state ||
+			(sdkp->media_present && sdp->changed));
+	if (retval)
 		sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL);
-	sdkp->previous_state = retval;
+	sdkp->previous_state = sdkp->media_present;
+
+	/* sdp->changed indicates medium was changed or is not present */
+	sdp->changed = !sdkp->media_present;
 	kfree(sshdr);
 	return retval;
 }
@@ -1175,6 +1188,12 @@
 	u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512);
 	u64 bad_lba;
 	int info_valid;
+	/*
+	 * resid is optional but mostly filled in.  When it's unused,
+	 * its value is zero, so we assume the whole buffer transferred
+	 */
+	unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd);
+	unsigned int good_bytes;
 
 	if (scmd->request->cmd_type != REQ_TYPE_FS)
 		return 0;
@@ -1208,7 +1227,8 @@
 	/* This computation should always be done in terms of
 	 * the resolution of the device's medium.
 	 */
-	return (bad_lba - start_lba) * scmd->device->sector_size;
+	good_bytes = (bad_lba - start_lba) * scmd->device->sector_size;
+	return min(good_bytes, transferred);
 }
 
 /**
@@ -1902,10 +1922,14 @@
 	int old_rcd = sdkp->RCD;
 	int old_dpofua = sdkp->DPOFUA;
 
-	if (sdp->skip_ms_page_8)
-		goto defaults;
-
-	if (sdp->type == TYPE_RBC) {
+	if (sdp->skip_ms_page_8) {
+		if (sdp->type == TYPE_RBC)
+			goto defaults;
+		else {
+			modepage = 0x3F;
+			dbd = 0;
+		}
+	} else if (sdp->type == TYPE_RBC) {
 		modepage = 6;
 		dbd = 8;
 	} else {
@@ -1933,13 +1957,11 @@
 	 */
 	if (len < 3)
 		goto bad_sense;
-	if (len > 20)
-		len = 20;
-
-	/* Take headers and block descriptors into account */
-	len += data.header_length + data.block_descriptor_length;
-	if (len > SD_BUF_SIZE)
-		goto bad_sense;
+	else if (len > SD_BUF_SIZE) {
+		sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
+			  "data from %d to %d bytes\n", len, SD_BUF_SIZE);
+		len = SD_BUF_SIZE;
+	}
 
 	/* Get the data */
 	res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
@@ -1947,16 +1969,45 @@
 	if (scsi_status_is_good(res)) {
 		int offset = data.header_length + data.block_descriptor_length;
 
-		if (offset >= SD_BUF_SIZE - 2) {
-			sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
-			goto defaults;
+		while (offset < len) {
+			u8 page_code = buffer[offset] & 0x3F;
+			u8 spf       = buffer[offset] & 0x40;
+
+			if (page_code == 8 || page_code == 6) {
+				/* We're interested only in the first 3 bytes.
+				 */
+				if (len - offset <= 2) {
+					sd_printk(KERN_ERR, sdkp, "Incomplete "
+						  "mode parameter data\n");
+					goto defaults;
+				} else {
+					modepage = page_code;
+					goto Page_found;
+				}
+			} else {
+				/* Go to the next page */
+				if (spf && len - offset > 3)
+					offset += 4 + (buffer[offset+2] << 8) +
+						buffer[offset+3];
+				else if (!spf && len - offset > 1)
+					offset += 2 + buffer[offset+1];
+				else {
+					sd_printk(KERN_ERR, sdkp, "Incomplete "
+						  "mode parameter data\n");
+					goto defaults;
+				}
+			}
 		}
 
-		if ((buffer[offset] & 0x3f) != modepage) {
+		if (modepage == 0x3F) {
+			sd_printk(KERN_ERR, sdkp, "No Caching mode page "
+				  "present\n");
+			goto defaults;
+		} else if ((buffer[offset] & 0x3f) != modepage) {
 			sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
 			goto defaults;
 		}
-
+	Page_found:
 		if (modepage == 8) {
 			sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
 			sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 5b7388f..1871b8a 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20100829";
+static const char *verstr = "20101219";
 
 #include <linux/module.h>
 
@@ -3729,9 +3729,11 @@
 		b_size = PAGE_SIZE << order;
 	} else {
 		for (b_size = PAGE_SIZE, order = 0;
-		     order < ST_MAX_ORDER && b_size < new_size;
+		     order < ST_MAX_ORDER &&
+			     max_segs * (PAGE_SIZE << order) < new_size;
 		     order++, b_size *= 2)
 			;  /* empty */
+		STbuffer->reserved_page_order = order;
 	}
 	if (max_segs * (PAGE_SIZE << order) < new_size) {
 		if (order == ST_MAX_ORDER)
@@ -3758,7 +3760,6 @@
 		segs++;
 	}
 	STbuffer->b_data = page_address(STbuffer->reserved_pages[0]);
-	STbuffer->reserved_page_order = order;
 
 	return 1;
 }
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 09a5508..b25e6e4 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -454,21 +454,40 @@
 		writeb(value, p->membase + offset);
 }
 
+/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */
+static inline void dwapb_save_out_value(struct uart_port *p, int offset,
+					int value)
+{
+	struct uart_8250_port *up =
+		container_of(p, struct uart_8250_port, port);
+
+	if (offset == UART_LCR)
+		up->lcr = value;
+}
+
+/* Read the IER to ensure any interrupt is cleared before returning from ISR. */
+static inline void dwapb_check_clear_ier(struct uart_port *p, int offset)
+{
+	if (offset == UART_TX || offset == UART_IER)
+		p->serial_in(p, UART_IER);
+}
+
 static void dwapb_serial_out(struct uart_port *p, int offset, int value)
 {
 	int save_offset = offset;
 	offset = map_8250_out_reg(p, offset) << p->regshift;
-	/* Save the LCR value so it can be re-written when a
-	 * Busy Detect interrupt occurs. */
-	if (save_offset == UART_LCR) {
-		struct uart_8250_port *up = (struct uart_8250_port *)p;
-		up->lcr = value;
-	}
+	dwapb_save_out_value(p, save_offset, value);
 	writeb(value, p->membase + offset);
-	/* Read the IER to ensure any interrupt is cleared before
-	 * returning from ISR. */
-	if (save_offset == UART_TX || save_offset == UART_IER)
-		value = p->serial_in(p, UART_IER);
+	dwapb_check_clear_ier(p, save_offset);
+}
+
+static void dwapb32_serial_out(struct uart_port *p, int offset, int value)
+{
+	int save_offset = offset;
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	dwapb_save_out_value(p, save_offset, value);
+	writel(value, p->membase + offset);
+	dwapb_check_clear_ier(p, save_offset);
 }
 
 static unsigned int io_serial_in(struct uart_port *p, int offset)
@@ -485,7 +504,8 @@
 
 static void set_io_from_upio(struct uart_port *p)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)p;
+	struct uart_8250_port *up =
+		container_of(p, struct uart_8250_port, port);
 	switch (p->iotype) {
 	case UPIO_HUB6:
 		p->serial_in = hub6_serial_in;
@@ -518,6 +538,11 @@
 		p->serial_out = dwapb_serial_out;
 		break;
 
+	case UPIO_DWAPB32:
+		p->serial_in = mem32_serial_in;
+		p->serial_out = dwapb32_serial_out;
+		break;
+
 	default:
 		p->serial_in = io_serial_in;
 		p->serial_out = io_serial_out;
@@ -536,6 +561,7 @@
 	case UPIO_MEM32:
 	case UPIO_AU:
 	case UPIO_DWAPB:
+	case UPIO_DWAPB32:
 		p->serial_out(p, offset, value);
 		p->serial_in(p, UART_LCR);	/* safe, no side-effects */
 		break;
@@ -653,13 +679,13 @@
 {
 	if (p->capabilities & UART_CAP_SLEEP) {
 		if (p->capabilities & UART_CAP_EFR) {
-			serial_outp(p, UART_LCR, 0xBF);
+			serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
 			serial_outp(p, UART_EFR, UART_EFR_ECB);
 			serial_outp(p, UART_LCR, 0);
 		}
 		serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
 		if (p->capabilities & UART_CAP_EFR) {
-			serial_outp(p, UART_LCR, 0xBF);
+			serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
 			serial_outp(p, UART_EFR, 0);
 			serial_outp(p, UART_LCR, 0);
 		}
@@ -752,7 +778,7 @@
 	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
 		    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
 	serial_outp(up, UART_MCR, UART_MCR_LOOP);
-	serial_outp(up, UART_LCR, UART_LCR_DLAB);
+	serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	old_dl = serial_dl_read(up);
 	serial_dl_write(up, 0x0001);
 	serial_outp(up, UART_LCR, 0x03);
@@ -764,7 +790,7 @@
 		serial_inp(up, UART_RX);
 	serial_outp(up, UART_FCR, old_fcr);
 	serial_outp(up, UART_MCR, old_mcr);
-	serial_outp(up, UART_LCR, UART_LCR_DLAB);
+	serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_dl_write(up, old_dl);
 	serial_outp(up, UART_LCR, old_lcr);
 
@@ -782,7 +808,7 @@
 	unsigned int id;
 
 	old_lcr = serial_inp(p, UART_LCR);
-	serial_outp(p, UART_LCR, UART_LCR_DLAB);
+	serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);
 
 	old_dll = serial_inp(p, UART_DLL);
 	old_dlm = serial_inp(p, UART_DLM);
@@ -836,7 +862,7 @@
 	 * recommended for new designs).
 	 */
 	up->acr = 0;
-	serial_out(up, UART_LCR, 0xBF);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_EFR, UART_EFR_ECB);
 	serial_out(up, UART_LCR, 0x00);
 	id1 = serial_icr_read(up, UART_ID1);
@@ -945,7 +971,7 @@
 	 * Check for presence of the EFR when DLAB is set.
 	 * Only ST16C650V1 UARTs pass this test.
 	 */
-	serial_outp(up, UART_LCR, UART_LCR_DLAB);
+	serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	if (serial_in(up, UART_EFR) == 0) {
 		serial_outp(up, UART_EFR, 0xA8);
 		if (serial_in(up, UART_EFR) != 0) {
@@ -963,7 +989,7 @@
 	 * Maybe it requires 0xbf to be written to the LCR.
 	 * (other ST16C650V2 UARTs, TI16C752A, etc)
 	 */
-	serial_outp(up, UART_LCR, 0xBF);
+	serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
 		DEBUG_AUTOCONF("EFRv2 ");
 		autoconfig_has_efr(up);
@@ -1024,7 +1050,7 @@
 	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
 	status1 = serial_in(up, UART_IIR) >> 5;
 	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-	serial_outp(up, UART_LCR, UART_LCR_DLAB);
+	serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
 	status2 = serial_in(up, UART_IIR) >> 5;
 	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
@@ -1183,7 +1209,7 @@
 	 * We also initialise the EFR (if any) to zero for later.  The
 	 * EFR occupies the same register location as the FCR and IIR.
 	 */
-	serial_outp(up, UART_LCR, 0xBF);
+	serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_outp(up, UART_EFR, 0);
 	serial_outp(up, UART_LCR, 0);
 
@@ -1319,7 +1345,8 @@
 
 static void serial8250_stop_tx(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 
 	__stop_tx(up);
 
@@ -1336,7 +1363,8 @@
 
 static void serial8250_start_tx(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 
 	if (!(up->ier & UART_IER_THRI)) {
 		up->ier |= UART_IER_THRI;
@@ -1364,7 +1392,8 @@
 
 static void serial8250_stop_rx(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 
 	up->ier &= ~UART_IER_RLSI;
 	up->port.read_status_mask &= ~UART_LSR_DR;
@@ -1373,7 +1402,8 @@
 
 static void serial8250_enable_ms(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 
 	/* no MSR capabilities */
 	if (up->bugs & UART_BUG_NOMSR)
@@ -1581,7 +1611,8 @@
 			handled = 1;
 
 			end = NULL;
-		} else if (up->port.iotype == UPIO_DWAPB &&
+		} else if ((up->port.iotype == UPIO_DWAPB ||
+			    up->port.iotype == UPIO_DWAPB32) &&
 			  (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
 			/* The DesignWare APB UART has an Busy Detect (0x07)
 			 * interrupt meaning an LCR write attempt occured while the
@@ -1781,7 +1812,8 @@
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned long flags;
 	unsigned int lsr;
 
@@ -1795,7 +1827,8 @@
 
 static unsigned int serial8250_get_mctrl(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned int status;
 	unsigned int ret;
 
@@ -1815,7 +1848,8 @@
 
 static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned char mcr = 0;
 
 	if (mctrl & TIOCM_RTS)
@@ -1836,7 +1870,8 @@
 
 static void serial8250_break_ctl(struct uart_port *port, int break_state)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned long flags;
 
 	spin_lock_irqsave(&up->port.lock, flags);
@@ -1890,7 +1925,8 @@
 
 static int serial8250_get_poll_char(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned char lsr = serial_inp(up, UART_LSR);
 
 	if (!(lsr & UART_LSR_DR))
@@ -1904,7 +1940,8 @@
 			 unsigned char c)
 {
 	unsigned int ier;
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 
 	/*
 	 *	First save the IER then disable the interrupts
@@ -1938,11 +1975,14 @@
 
 static int serial8250_startup(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned long flags;
 	unsigned char lsr, iir;
 	int retval;
 
+	up->port.fifosize = uart_config[up->port.type].fifo_size;
+	up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
 	up->capabilities = uart_config[up->port.type].flags;
 	up->mcr = 0;
 
@@ -1952,7 +1992,7 @@
 	if (up->port.type == PORT_16C950) {
 		/* Wake up and initialize UART */
 		up->acr = 0;
-		serial_outp(up, UART_LCR, 0xBF);
+		serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
 		serial_outp(up, UART_EFR, UART_EFR_ECB);
 		serial_outp(up, UART_IER, 0);
 		serial_outp(up, UART_LCR, 0);
@@ -2002,7 +2042,7 @@
 	if (up->port.type == PORT_16850) {
 		unsigned char fctr;
 
-		serial_outp(up, UART_LCR, 0xbf);
+		serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 		fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
 		serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
@@ -2166,7 +2206,8 @@
 
 static void serial8250_shutdown(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned long flags;
 
 	/*
@@ -2235,7 +2276,8 @@
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 		          struct ktermios *old)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	unsigned char cval, fcr = 0;
 	unsigned long flags;
 	unsigned int baud, quot;
@@ -2363,7 +2405,7 @@
 		if (termios->c_cflag & CRTSCTS)
 			efr |= UART_EFR_CTS;
 
-		serial_outp(up, UART_LCR, 0xBF);
+		serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
 		serial_outp(up, UART_EFR, efr);
 	}
 
@@ -2435,7 +2477,8 @@
 void serial8250_do_pm(struct uart_port *port, unsigned int state,
 		      unsigned int oldstate)
 {
-	struct uart_8250_port *p = (struct uart_8250_port *)port;
+	struct uart_8250_port *p =
+		container_of(port, struct uart_8250_port, port);
 
 	serial8250_set_sleep(p, state != 0);
 }
@@ -2476,6 +2519,7 @@
 	case UPIO_MEM32:
 	case UPIO_MEM:
 	case UPIO_DWAPB:
+	case UPIO_DWAPB32:
 		if (!up->port.mapbase)
 			break;
 
@@ -2513,6 +2557,7 @@
 	case UPIO_MEM32:
 	case UPIO_MEM:
 	case UPIO_DWAPB:
+	case UPIO_DWAPB32:
 		if (!up->port.mapbase)
 			break;
 
@@ -2566,7 +2611,8 @@
 
 static void serial8250_release_port(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 
 	serial8250_release_std_resource(up);
 	if (up->port.type == PORT_RSA)
@@ -2575,7 +2621,8 @@
 
 static int serial8250_request_port(struct uart_port *port)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	int ret = 0;
 
 	ret = serial8250_request_std_resource(up);
@@ -2590,7 +2637,8 @@
 
 static void serial8250_config_port(struct uart_port *port, int flags)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 	int probeflags = PROBE_ANY;
 	int ret;
 
@@ -2771,7 +2819,8 @@
 
 static void serial8250_console_putchar(struct uart_port *port, int ch)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
+	struct uart_8250_port *up =
+		container_of(port, struct uart_8250_port, port);
 
 	wait_for_xmitr(up, UART_LSR_THRE);
 	serial_out(up, UART_TX, ch);
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 842e3b2..8b8930f 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -957,6 +957,22 @@
 	return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
+static int
+ce4100_serial_setup(struct serial_private *priv,
+		  const struct pciserial_board *board,
+		  struct uart_port *port, int idx)
+{
+	int ret;
+
+	ret = setup_port(priv, port, 0, 0, board->reg_shift);
+	port->iotype = UPIO_MEM32;
+	port->type = PORT_XSCALE;
+	port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+	port->regshift = 2;
+
+	return ret;
+}
+
 static int skip_tx_en_setup(struct serial_private *priv,
 			const struct pciserial_board *board,
 			struct uart_port *port, int idx)
@@ -981,6 +997,7 @@
 #define PCI_SUBDEVICE_ID_POCTAL232	0x0308
 #define PCI_SUBDEVICE_ID_POCTAL422	0x0408
 #define PCI_VENDOR_ID_ADVANTECH		0x13fe
+#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
 #define PCI_DEVICE_ID_ADVANTECH_PCI3620	0x3620
 #define PCI_DEVICE_ID_TITAN_200I	0x8028
 #define PCI_DEVICE_ID_TITAN_400I	0x8048
@@ -1072,6 +1089,13 @@
 		.subdevice	= PCI_ANY_ID,
 		.setup		= skip_tx_en_setup,
 	},
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_CE4100_UART,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= ce4100_serial_setup,
+	},
 	/*
 	 * ITE
 	 */
@@ -1592,6 +1616,7 @@
 	pbn_ADDIDATA_PCIe_2_3906250,
 	pbn_ADDIDATA_PCIe_4_3906250,
 	pbn_ADDIDATA_PCIe_8_3906250,
+	pbn_ce4100_1_115200,
 };
 
 /*
@@ -2281,6 +2306,12 @@
 		.uart_offset	= 0x200,
 		.first_offset	= 0x1000,
 	},
+	[pbn_ce4100_1_115200] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 921600,
+		.reg_shift      = 2,
+	},
 };
 
 static const struct pci_device_id softmodem_blacklist[] = {
@@ -3765,6 +3796,11 @@
 	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
 		0xA000, 0x3004,
 		0, 0, pbn_b0_bt_4_115200 },
+	/* Intel CE4100 */
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
+		PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
+		pbn_ce4100_1_115200 },
+
 
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index aff9dcd..ec3c214 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1381,6 +1381,16 @@
 	depends on SERIAL_MSM=y
 	select SERIAL_CORE_CONSOLE
 
+config SERIAL_VT8500
+	bool "VIA VT8500 on-chip serial port support"
+	depends on ARM && ARCH_VT8500
+	select SERIAL_CORE
+
+config SERIAL_VT8500_CONSOLE
+	bool "VIA VT8500 serial console support"
+	depends on SERIAL_VT8500=y
+	select SERIAL_CORE_CONSOLE
+
 config SERIAL_NETX
 	tristate "NetX serial port support"
 	depends on ARM && ARCH_NETX
@@ -1632,4 +1642,19 @@
 	help
 	  Enable a Altera UART port to be the system console.
 
+config SERIAL_IFX6X60
+        tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
+	depends on GPIOLIB && SPI && EXPERIMENTAL
+	help
+	  Support for the IFX6x60 modem devices on Intel MID platforms.
+
+config SERIAL_PCH_UART
+	tristate "Intel EG20T PCH UART"
+	depends on PCI && DMADEVICES
+	select SERIAL_CORE
+	select PCH_DMA
+	help
+	  This driver is for PCH(Platform controller Hub) UART of Intel EG20T
+	  which is an IOH(Input/Output Hub) for x86 embedded processor.
+	  Enabling PCH_DMA, this PCH UART works as DMA mode.
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index c570576..8ea92e9 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -80,12 +80,15 @@
 obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
+obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
 obj-$(CONFIG_SERIAL_TIMBERDALE)	+= timbuart.o
 obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
 obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
+obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
 obj-$(CONFIG_SERIAL_MRST_MAX3110)	+= mrst_max3110.o
 obj-$(CONFIG_SERIAL_MFD_HSU)	+= mfd.o
-obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
+obj-$(CONFIG_SERIAL_IFX6X60)  	+= ifx6x60.o
+obj-$(CONFIG_SERIAL_PCH_UART)	+= pch_uart.o
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 6ca7a44..e76d7d0 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -7,6 +7,7 @@
  *
  *  Copyright 1999 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *  Copyright (C) 2010 ST-Ericsson SA
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -48,6 +49,9 @@
 #include <linux/amba/serial.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
 
 #include <asm/io.h>
 #include <asm/sizes.h>
@@ -63,21 +67,6 @@
 #define UART_DR_ERROR		(UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
 #define UART_DUMMY_DR_RX	(1 << 16)
 
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct uart_amba_port {
-	struct uart_port	port;
-	struct clk		*clk;
-	unsigned int		im;		/* interrupt mask */
-	unsigned int		old_status;
-	unsigned int		ifls;		/* vendor-specific */
-	unsigned int		lcrh_tx;	/* vendor-specific */
-	unsigned int		lcrh_rx;	/* vendor-specific */
-	bool			oversampling;   /* vendor-specific */
-	bool			autorts;
-};
-
 /* There is by now at least one vendor with differing details, so handle it */
 struct vendor_data {
 	unsigned int		ifls;
@@ -85,6 +74,7 @@
 	unsigned int		lcrh_tx;
 	unsigned int		lcrh_rx;
 	bool			oversampling;
+	bool			dma_threshold;
 };
 
 static struct vendor_data vendor_arm = {
@@ -93,6 +83,7 @@
 	.lcrh_tx		= UART011_LCRH,
 	.lcrh_rx		= UART011_LCRH,
 	.oversampling		= false,
+	.dma_threshold		= false,
 };
 
 static struct vendor_data vendor_st = {
@@ -101,22 +92,535 @@
 	.lcrh_tx		= ST_UART011_LCRH_TX,
 	.lcrh_rx		= ST_UART011_LCRH_RX,
 	.oversampling		= true,
+	.dma_threshold		= true,
 };
 
+/* Deals with DMA transactions */
+struct pl011_dmatx_data {
+	struct dma_chan		*chan;
+	struct scatterlist	sg;
+	char			*buf;
+	bool			queued;
+};
+
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct uart_amba_port {
+	struct uart_port	port;
+	struct clk		*clk;
+	const struct vendor_data *vendor;
+	unsigned int		dmacr;		/* dma control reg */
+	unsigned int		im;		/* interrupt mask */
+	unsigned int		old_status;
+	unsigned int		fifosize;	/* vendor-specific */
+	unsigned int		lcrh_tx;	/* vendor-specific */
+	unsigned int		lcrh_rx;	/* vendor-specific */
+	bool			autorts;
+	char			type[12];
+#ifdef CONFIG_DMA_ENGINE
+	/* DMA stuff */
+	bool			using_dma;
+	struct pl011_dmatx_data	dmatx;
+#endif
+};
+
+/*
+ * All the DMA operation mode stuff goes inside this ifdef.
+ * This assumes that you have a generic DMA device interface,
+ * no custom DMA interfaces are supported.
+ */
+#ifdef CONFIG_DMA_ENGINE
+
+#define PL011_DMA_BUFFER_SIZE PAGE_SIZE
+
+static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
+{
+	/* DMA is the sole user of the platform data right now */
+	struct amba_pl011_data *plat = uap->port.dev->platform_data;
+	struct dma_slave_config tx_conf = {
+		.dst_addr = uap->port.mapbase + UART01x_DR,
+		.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+		.direction = DMA_TO_DEVICE,
+		.dst_maxburst = uap->fifosize >> 1,
+	};
+	struct dma_chan *chan;
+	dma_cap_mask_t mask;
+
+	/* We need platform data */
+	if (!plat || !plat->dma_filter) {
+		dev_info(uap->port.dev, "no DMA platform data\n");
+		return;
+	}
+
+	/* Try to acquire a generic DMA engine slave channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
+	if (!chan) {
+		dev_err(uap->port.dev, "no TX DMA channel!\n");
+		return;
+	}
+
+	dmaengine_slave_config(chan, &tx_conf);
+	uap->dmatx.chan = chan;
+
+	dev_info(uap->port.dev, "DMA channel TX %s\n",
+		 dma_chan_name(uap->dmatx.chan));
+}
+
+#ifndef MODULE
+/*
+ * Stack up the UARTs and let the above initcall be done at device
+ * initcall time, because the serial driver is called as an arch
+ * initcall, and at this time the DMA subsystem is not yet registered.
+ * At this point the driver will switch over to using DMA where desired.
+ */
+struct dma_uap {
+	struct list_head node;
+	struct uart_amba_port *uap;
+};
+
+static LIST_HEAD(pl011_dma_uarts);
+
+static int __init pl011_dma_initcall(void)
+{
+	struct list_head *node, *tmp;
+
+	list_for_each_safe(node, tmp, &pl011_dma_uarts) {
+		struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
+		pl011_dma_probe_initcall(dmau->uap);
+		list_del(node);
+		kfree(dmau);
+	}
+	return 0;
+}
+
+device_initcall(pl011_dma_initcall);
+
+static void pl011_dma_probe(struct uart_amba_port *uap)
+{
+	struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
+	if (dmau) {
+		dmau->uap = uap;
+		list_add_tail(&dmau->node, &pl011_dma_uarts);
+	}
+}
+#else
+static void pl011_dma_probe(struct uart_amba_port *uap)
+{
+	pl011_dma_probe_initcall(uap);
+}
+#endif
+
+static void pl011_dma_remove(struct uart_amba_port *uap)
+{
+	/* TODO: remove the initcall if it has not yet executed */
+	if (uap->dmatx.chan)
+		dma_release_channel(uap->dmatx.chan);
+}
+
+
+/* Forward declare this for the refill routine */
+static int pl011_dma_tx_refill(struct uart_amba_port *uap);
+
+/*
+ * The current DMA TX buffer has been sent.
+ * Try to queue up another DMA buffer.
+ */
+static void pl011_dma_tx_callback(void *data)
+{
+	struct uart_amba_port *uap = data;
+	struct pl011_dmatx_data *dmatx = &uap->dmatx;
+	unsigned long flags;
+	u16 dmacr;
+
+	spin_lock_irqsave(&uap->port.lock, flags);
+	if (uap->dmatx.queued)
+		dma_unmap_sg(dmatx->chan->device->dev, &dmatx->sg, 1,
+			     DMA_TO_DEVICE);
+
+	dmacr = uap->dmacr;
+	uap->dmacr = dmacr & ~UART011_TXDMAE;
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+
+	/*
+	 * If TX DMA was disabled, it means that we've stopped the DMA for
+	 * some reason (eg, XOFF received, or we want to send an X-char.)
+	 *
+	 * Note: we need to be careful here of a potential race between DMA
+	 * and the rest of the driver - if the driver disables TX DMA while
+	 * a TX buffer completing, we must update the tx queued status to
+	 * get further refills (hence we check dmacr).
+	 */
+	if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) ||
+	    uart_circ_empty(&uap->port.state->xmit)) {
+		uap->dmatx.queued = false;
+		spin_unlock_irqrestore(&uap->port.lock, flags);
+		return;
+	}
+
+	if (pl011_dma_tx_refill(uap) <= 0) {
+		/*
+		 * We didn't queue a DMA buffer for some reason, but we
+		 * have data pending to be sent.  Re-enable the TX IRQ.
+		 */
+		uap->im |= UART011_TXIM;
+		writew(uap->im, uap->port.membase + UART011_IMSC);
+	}
+	spin_unlock_irqrestore(&uap->port.lock, flags);
+}
+
+/*
+ * Try to refill the TX DMA buffer.
+ * Locking: called with port lock held and IRQs disabled.
+ * Returns:
+ *   1 if we queued up a TX DMA buffer.
+ *   0 if we didn't want to handle this by DMA
+ *  <0 on error
+ */
+static int pl011_dma_tx_refill(struct uart_amba_port *uap)
+{
+	struct pl011_dmatx_data *dmatx = &uap->dmatx;
+	struct dma_chan *chan = dmatx->chan;
+	struct dma_device *dma_dev = chan->device;
+	struct dma_async_tx_descriptor *desc;
+	struct circ_buf *xmit = &uap->port.state->xmit;
+	unsigned int count;
+
+	/*
+	 * Try to avoid the overhead involved in using DMA if the
+	 * transaction fits in the first half of the FIFO, by using
+	 * the standard interrupt handling.  This ensures that we
+	 * issue a uart_write_wakeup() at the appropriate time.
+	 */
+	count = uart_circ_chars_pending(xmit);
+	if (count < (uap->fifosize >> 1)) {
+		uap->dmatx.queued = false;
+		return 0;
+	}
+
+	/*
+	 * Bodge: don't send the last character by DMA, as this
+	 * will prevent XON from notifying us to restart DMA.
+	 */
+	count -= 1;
+
+	/* Else proceed to copy the TX chars to the DMA buffer and fire DMA */
+	if (count > PL011_DMA_BUFFER_SIZE)
+		count = PL011_DMA_BUFFER_SIZE;
+
+	if (xmit->tail < xmit->head)
+		memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], count);
+	else {
+		size_t first = UART_XMIT_SIZE - xmit->tail;
+		size_t second = xmit->head;
+
+		memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], first);
+		if (second)
+			memcpy(&dmatx->buf[first], &xmit->buf[0], second);
+	}
+
+	dmatx->sg.length = count;
+
+	if (dma_map_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE) != 1) {
+		uap->dmatx.queued = false;
+		dev_dbg(uap->port.dev, "unable to map TX DMA\n");
+		return -EBUSY;
+	}
+
+	desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_TO_DEVICE,
+					     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE);
+		uap->dmatx.queued = false;
+		/*
+		 * If DMA cannot be used right now, we complete this
+		 * transaction via IRQ and let the TTY layer retry.
+		 */
+		dev_dbg(uap->port.dev, "TX DMA busy\n");
+		return -EBUSY;
+	}
+
+	/* Some data to go along to the callback */
+	desc->callback = pl011_dma_tx_callback;
+	desc->callback_param = uap;
+
+	/* All errors should happen at prepare time */
+	dmaengine_submit(desc);
+
+	/* Fire the DMA transaction */
+	dma_dev->device_issue_pending(chan);
+
+	uap->dmacr |= UART011_TXDMAE;
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+	uap->dmatx.queued = true;
+
+	/*
+	 * Now we know that DMA will fire, so advance the ring buffer
+	 * with the stuff we just dispatched.
+	 */
+	xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
+	uap->port.icount.tx += count;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&uap->port);
+
+	return 1;
+}
+
+/*
+ * We received a transmit interrupt without a pending X-char but with
+ * pending characters.
+ * Locking: called with port lock held and IRQs disabled.
+ * Returns:
+ *   false if we want to use PIO to transmit
+ *   true if we queued a DMA buffer
+ */
+static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
+{
+	if (!uap->using_dma)
+		return false;
+
+	/*
+	 * If we already have a TX buffer queued, but received a
+	 * TX interrupt, it will be because we've just sent an X-char.
+	 * Ensure the TX DMA is enabled and the TX IRQ is disabled.
+	 */
+	if (uap->dmatx.queued) {
+		uap->dmacr |= UART011_TXDMAE;
+		writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+		uap->im &= ~UART011_TXIM;
+		writew(uap->im, uap->port.membase + UART011_IMSC);
+		return true;
+	}
+
+	/*
+	 * We don't have a TX buffer queued, so try to queue one.
+	 * If we succesfully queued a buffer, mask the TX IRQ.
+	 */
+	if (pl011_dma_tx_refill(uap) > 0) {
+		uap->im &= ~UART011_TXIM;
+		writew(uap->im, uap->port.membase + UART011_IMSC);
+		return true;
+	}
+	return false;
+}
+
+/*
+ * Stop the DMA transmit (eg, due to received XOFF).
+ * Locking: called with port lock held and IRQs disabled.
+ */
+static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
+{
+	if (uap->dmatx.queued) {
+		uap->dmacr &= ~UART011_TXDMAE;
+		writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+	}
+}
+
+/*
+ * Try to start a DMA transmit, or in the case of an XON/OFF
+ * character queued for send, try to get that character out ASAP.
+ * Locking: called with port lock held and IRQs disabled.
+ * Returns:
+ *   false if we want the TX IRQ to be enabled
+ *   true if we have a buffer queued
+ */
+static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
+{
+	u16 dmacr;
+
+	if (!uap->using_dma)
+		return false;
+
+	if (!uap->port.x_char) {
+		/* no X-char, try to push chars out in DMA mode */
+		bool ret = true;
+
+		if (!uap->dmatx.queued) {
+			if (pl011_dma_tx_refill(uap) > 0) {
+				uap->im &= ~UART011_TXIM;
+				ret = true;
+			} else {
+				uap->im |= UART011_TXIM;
+				ret = false;
+			}
+			writew(uap->im, uap->port.membase + UART011_IMSC);
+		} else if (!(uap->dmacr & UART011_TXDMAE)) {
+			uap->dmacr |= UART011_TXDMAE;
+			writew(uap->dmacr,
+				       uap->port.membase + UART011_DMACR);
+		}
+		return ret;
+	}
+
+	/*
+	 * We have an X-char to send.  Disable DMA to prevent it loading
+	 * the TX fifo, and then see if we can stuff it into the FIFO.
+	 */
+	dmacr = uap->dmacr;
+	uap->dmacr &= ~UART011_TXDMAE;
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+
+	if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+		/*
+		 * No space in the FIFO, so enable the transmit interrupt
+		 * so we know when there is space.  Note that once we've
+		 * loaded the character, we should just re-enable DMA.
+		 */
+		return false;
+	}
+
+	writew(uap->port.x_char, uap->port.membase + UART01x_DR);
+	uap->port.icount.tx++;
+	uap->port.x_char = 0;
+
+	/* Success - restore the DMA state */
+	uap->dmacr = dmacr;
+	writew(dmacr, uap->port.membase + UART011_DMACR);
+
+	return true;
+}
+
+/*
+ * Flush the transmit buffer.
+ * Locking: called with port lock held and IRQs disabled.
+ */
+static void pl011_dma_flush_buffer(struct uart_port *port)
+{
+	struct uart_amba_port *uap = (struct uart_amba_port *)port;
+
+	if (!uap->using_dma)
+		return;
+
+	/* Avoid deadlock with the DMA engine callback */
+	spin_unlock(&uap->port.lock);
+	dmaengine_terminate_all(uap->dmatx.chan);
+	spin_lock(&uap->port.lock);
+	if (uap->dmatx.queued) {
+		dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
+			     DMA_TO_DEVICE);
+		uap->dmatx.queued = false;
+		uap->dmacr &= ~UART011_TXDMAE;
+		writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+	}
+}
+
+
+static void pl011_dma_startup(struct uart_amba_port *uap)
+{
+	if (!uap->dmatx.chan)
+		return;
+
+	uap->dmatx.buf = kmalloc(PL011_DMA_BUFFER_SIZE, GFP_KERNEL);
+	if (!uap->dmatx.buf) {
+		dev_err(uap->port.dev, "no memory for DMA TX buffer\n");
+		uap->port.fifosize = uap->fifosize;
+		return;
+	}
+
+	sg_init_one(&uap->dmatx.sg, uap->dmatx.buf, PL011_DMA_BUFFER_SIZE);
+
+	/* The DMA buffer is now the FIFO the TTY subsystem can use */
+	uap->port.fifosize = PL011_DMA_BUFFER_SIZE;
+	uap->using_dma = true;
+
+	/* Turn on DMA error (RX/TX will be enabled on demand) */
+	uap->dmacr |= UART011_DMAONERR;
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+
+	/*
+	 * ST Micro variants has some specific dma burst threshold
+	 * compensation. Set this to 16 bytes, so burst will only
+	 * be issued above/below 16 bytes.
+	 */
+	if (uap->vendor->dma_threshold)
+		writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
+			       uap->port.membase + ST_UART011_DMAWM);
+}
+
+static void pl011_dma_shutdown(struct uart_amba_port *uap)
+{
+	if (!uap->using_dma)
+		return;
+
+	/* Disable RX and TX DMA */
+	while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
+		barrier();
+
+	spin_lock_irq(&uap->port.lock);
+	uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+	spin_unlock_irq(&uap->port.lock);
+
+	/* In theory, this should already be done by pl011_dma_flush_buffer */
+	dmaengine_terminate_all(uap->dmatx.chan);
+	if (uap->dmatx.queued) {
+		dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
+			     DMA_TO_DEVICE);
+		uap->dmatx.queued = false;
+	}
+
+	kfree(uap->dmatx.buf);
+
+	uap->using_dma = false;
+}
+
+#else
+/* Blank functions if the DMA engine is not available */
+static inline void pl011_dma_probe(struct uart_amba_port *uap)
+{
+}
+
+static inline void pl011_dma_remove(struct uart_amba_port *uap)
+{
+}
+
+static inline void pl011_dma_startup(struct uart_amba_port *uap)
+{
+}
+
+static inline void pl011_dma_shutdown(struct uart_amba_port *uap)
+{
+}
+
+static inline bool pl011_dma_tx_irq(struct uart_amba_port *uap)
+{
+	return false;
+}
+
+static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
+{
+}
+
+static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
+{
+	return false;
+}
+
+#define pl011_dma_flush_buffer	NULL
+#endif
+
+
 static void pl011_stop_tx(struct uart_port *port)
 {
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 
 	uap->im &= ~UART011_TXIM;
 	writew(uap->im, uap->port.membase + UART011_IMSC);
+	pl011_dma_tx_stop(uap);
 }
 
 static void pl011_start_tx(struct uart_port *port)
 {
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 
-	uap->im |= UART011_TXIM;
-	writew(uap->im, uap->port.membase + UART011_IMSC);
+	if (!pl011_dma_tx_start(uap)) {
+		uap->im |= UART011_TXIM;
+		writew(uap->im, uap->port.membase + UART011_IMSC);
+	}
 }
 
 static void pl011_stop_rx(struct uart_port *port)
@@ -203,7 +707,11 @@
 		return;
 	}
 
-	count = uap->port.fifosize >> 1;
+	/* If we are using DMA mode, try to send some characters. */
+	if (pl011_dma_tx_irq(uap))
+		return;
+
+	count = uap->fifosize >> 1;
 	do {
 		writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -246,10 +754,11 @@
 static irqreturn_t pl011_int(int irq, void *dev_id)
 {
 	struct uart_amba_port *uap = dev_id;
+	unsigned long flags;
 	unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
 	int handled = 0;
 
-	spin_lock(&uap->port.lock);
+	spin_lock_irqsave(&uap->port.lock, flags);
 
 	status = readw(uap->port.membase + UART011_MIS);
 	if (status) {
@@ -274,7 +783,7 @@
 		handled = 1;
 	}
 
-	spin_unlock(&uap->port.lock);
+	spin_unlock_irqrestore(&uap->port.lock, flags);
 
 	return IRQ_RETVAL(handled);
 }
@@ -396,7 +905,7 @@
 	if (retval)
 		goto clk_dis;
 
-	writew(uap->ifls, uap->port.membase + UART011_IFLS);
+	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
 
 	/*
 	 * Provoke TX FIFO interrupt into asserting.
@@ -423,11 +932,18 @@
 	cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
 	writew(cr, uap->port.membase + UART011_CR);
 
+	/* Clear pending error interrupts */
+	writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
+	       uap->port.membase + UART011_ICR);
+
 	/*
 	 * initialise the old status of the modem signals
 	 */
 	uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
 
+	/* Startup DMA */
+	pl011_dma_startup(uap);
+
 	/*
 	 * Finally, enable interrupts
 	 */
@@ -467,6 +983,8 @@
 	writew(0xffff, uap->port.membase + UART011_ICR);
 	spin_unlock_irq(&uap->port.lock);
 
+	pl011_dma_shutdown(uap);
+
 	/*
 	 * Free the interrupt
 	 */
@@ -498,13 +1016,18 @@
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 	unsigned int lcr_h, old_cr;
 	unsigned long flags;
-	unsigned int baud, quot;
+	unsigned int baud, quot, clkdiv;
+
+	if (uap->vendor->oversampling)
+		clkdiv = 8;
+	else
+		clkdiv = 16;
 
 	/*
 	 * Ask the core to calculate the divisor for us.
 	 */
 	baud = uart_get_baud_rate(port, termios, old, 0,
-				  port->uartclk/(uap->oversampling ? 8 : 16));
+				  port->uartclk / clkdiv);
 
 	if (baud > port->uartclk/16)
 		quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
@@ -532,7 +1055,7 @@
 		if (!(termios->c_cflag & PARODD))
 			lcr_h |= UART01x_LCRH_EPS;
 	}
-	if (port->fifosize > 1)
+	if (uap->fifosize > 1)
 		lcr_h |= UART01x_LCRH_FEN;
 
 	spin_lock_irqsave(&port->lock, flags);
@@ -588,8 +1111,8 @@
 		uap->autorts = false;
 	}
 
-	if (uap->oversampling) {
-		if (baud > port->uartclk/16)
+	if (uap->vendor->oversampling) {
+		if (baud > port->uartclk / 16)
 			old_cr |= ST_UART011_CR_OVSFACT;
 		else
 			old_cr &= ~ST_UART011_CR_OVSFACT;
@@ -622,7 +1145,8 @@
 
 static const char *pl011_type(struct uart_port *port)
 {
-	return port->type == PORT_AMBA ? "AMBA/PL011" : NULL;
+	struct uart_amba_port *uap = (struct uart_amba_port *)port;
+	return uap->port.type == PORT_AMBA ? uap->type : NULL;
 }
 
 /*
@@ -679,6 +1203,7 @@
 	.break_ctl	= pl011_break_ctl,
 	.startup	= pl011_startup,
 	.shutdown	= pl011_shutdown,
+	.flush_buffer	= pl011_dma_flush_buffer,
 	.set_termios	= pl011_set_termios,
 	.type		= pl011_type,
 	.release_port	= pl010_release_port,
@@ -761,7 +1286,7 @@
 
 		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
-		if (uap->oversampling) {
+		if (uap->vendor->oversampling) {
 			if (readw(uap->port.membase + UART011_CR)
 				  & ST_UART011_CR_OVSFACT)
 				*baud *= 2;
@@ -858,19 +1383,22 @@
 		goto unmap;
 	}
 
-	uap->ifls = vendor->ifls;
+	uap->vendor = vendor;
 	uap->lcrh_rx = vendor->lcrh_rx;
 	uap->lcrh_tx = vendor->lcrh_tx;
-	uap->oversampling = vendor->oversampling;
+	uap->fifosize = vendor->fifosize;
 	uap->port.dev = &dev->dev;
 	uap->port.mapbase = dev->res.start;
 	uap->port.membase = base;
 	uap->port.iotype = UPIO_MEM;
 	uap->port.irq = dev->irq[0];
-	uap->port.fifosize = vendor->fifosize;
+	uap->port.fifosize = uap->fifosize;
 	uap->port.ops = &amba_pl011_pops;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
 	uap->port.line = i;
+	pl011_dma_probe(uap);
+
+	snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
 
 	amba_ports[i] = uap;
 
@@ -879,6 +1407,7 @@
 	if (ret) {
 		amba_set_drvdata(dev, NULL);
 		amba_ports[i] = NULL;
+		pl011_dma_remove(uap);
 		clk_put(uap->clk);
  unmap:
 		iounmap(base);
@@ -902,6 +1431,7 @@
 		if (amba_ports[i] == uap)
 			amba_ports[i] = NULL;
 
+	pl011_dma_remove(uap);
 	iounmap(uap->port.membase);
 	clk_put(uap->clk);
 	kfree(uap);
diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c
index cc01c65..095a5d5 100644
--- a/drivers/serial/apbuart.c
+++ b/drivers/serial/apbuart.c
@@ -26,6 +26,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/serial_core.h>
@@ -520,11 +521,12 @@
 };
 
 
-static void grlib_apbuart_configure(void);
+static int grlib_apbuart_configure(void);
 
 static int __init apbuart_console_init(void)
 {
-	grlib_apbuart_configure();
+	if (grlib_apbuart_configure())
+		return -ENODEV;
 	register_console(&grlib_apbuart_console);
 	return 0;
 }
@@ -573,13 +575,15 @@
 	printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n",
 	       (unsigned long long) port->mapbase, port->irq);
 	return 0;
-
 }
 
 static struct of_device_id __initdata apbuart_match[] = {
 	{
 	 .name = "GAISLER_APBUART",
 	 },
+	{
+	 .name = "01_00c",
+	 },
 	{},
 };
 
@@ -593,54 +597,49 @@
 };
 
 
-static void grlib_apbuart_configure(void)
+static int grlib_apbuart_configure(void)
 {
-	static int enum_done;
 	struct device_node *np, *rp;
-	struct uart_port *port = NULL;
 	const u32 *prop;
-	int freq_khz;
-	int v = 0, d = 0;
-	unsigned int addr;
-	int irq, line;
-	struct amba_prom_registers *regs;
-
-	if (enum_done)
-		return;
+	int freq_khz, line = 0;
 
 	/* Get bus frequency */
 	rp = of_find_node_by_path("/");
+	if (!rp)
+		return -ENODEV;
 	rp = of_get_next_child(rp, NULL);
+	if (!rp)
+		return -ENODEV;
 	prop = of_get_property(rp, "clock-frequency", NULL);
+	if (!prop)
+		return -ENODEV;
 	freq_khz = *prop;
 
-	line = 0;
 	for_each_matching_node(np, apbuart_match) {
+		const int *irqs, *ampopts;
+		const struct amba_prom_registers *regs;
+		struct uart_port *port;
+		unsigned long addr;
 
-		int *vendor = (int *) of_get_property(np, "vendor", NULL);
-		int *device = (int *) of_get_property(np, "device", NULL);
-		int *irqs = (int *) of_get_property(np, "interrupts", NULL);
-		regs = (struct amba_prom_registers *)
-		    of_get_property(np, "reg", NULL);
+		ampopts = of_get_property(np, "ampopts", NULL);
+		if (ampopts && (*ampopts == 0))
+			continue; /* Ignore if used by another OS instance */
 
-		if (vendor)
-			v = *vendor;
-		if (device)
-			d = *device;
+		irqs = of_get_property(np, "interrupts", NULL);
+		regs = of_get_property(np, "reg", NULL);
 
 		if (!irqs || !regs)
-			return;
+			continue;
 
 		grlib_apbuart_nodes[line] = np;
 
 		addr = regs->phys_addr;
-		irq = *irqs;
 
 		port = &grlib_apbuart_ports[line];
 
 		port->mapbase = addr;
 		port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map));
-		port->irq = irq;
+		port->irq = *irqs;
 		port->iotype = UPIO_MEM;
 		port->ops = &grlib_apbuart_ops;
 		port->flags = UPF_BOOT_AUTOCONF;
@@ -652,12 +651,10 @@
 		/* We support maximum UART_NR uarts ... */
 		if (line == UART_NR)
 			break;
-
 	}
 
-	enum_done = 1;
-
 	grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line;
+	return line ? 0 : -ENODEV;
 }
 
 static int __init grlib_apbuart_init(void)
@@ -665,7 +662,9 @@
 	int ret;
 
 	/* Find all APBUARTS in device the tree and initialize their ports */
-	grlib_apbuart_configure();
+	ret = grlib_apbuart_configure();
+	if (ret)
+		return ret;
 
 	printk(KERN_INFO "Serial: GRLIB APBUART driver\n");
 
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 7274b52..b754dcf 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -76,18 +76,12 @@
 	unsigned char		*tx_buf;
 	unsigned char		*rx_buf;
 	u32			flags;
-	void			(*set_lineif)(struct uart_cpm_port *);
 	struct clk		*clk;
 	u8			brg;
 	uint			 dp_addr;
 	void			*mem_addr;
 	dma_addr_t		 dma_addr;
 	u32			mem_size;
-	/* helpers */
-	int			 baud;
-	int			 bits;
-	/* Keep track of 'odd' SMC2 wirings */
-	int			is_portb;
 	/* wait on close if needed */
 	int			wait_closing;
 	/* value to combine with opcode to form cpm command */
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index f2b8adc..8692ff9 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -72,6 +72,8 @@
 
 /**************************************************************/
 
+#define HW_BUF_SPD_THRESHOLD    9600
+
 /*
  * Check, if transmit buffers are processed
 */
@@ -503,6 +505,11 @@
 	pr_debug("CPM uart[%d]:set_termios\n", port->line);
 
 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+	if (baud <= HW_BUF_SPD_THRESHOLD ||
+	    (pinfo->port.state && pinfo->port.state->port.tty->low_latency))
+		pinfo->rx_fifosize = 1;
+	else
+		pinfo->rx_fifosize = RX_BUF_SIZE;
 
 	/* Character length programmed into the mode register is the
 	 * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
@@ -594,6 +601,17 @@
 	 */
 	bits++;
 	if (IS_SMC(pinfo)) {
+		/*
+		 * MRBLR can be changed while an SMC/SCC is operating only
+		 * if it is done in a single bus cycle with one 16-bit move
+		 * (not two 8-bit bus cycles back-to-back). This occurs when
+		 * the cp shifts control to the next RxBD, so the change does
+		 * not take effect immediately. To guarantee the exact RxBD
+		 * on which the change occurs, change MRBLR only while the
+		 * SMC/SCC receiver is disabled.
+		 */
+		out_be16(&pinfo->smcup->smc_mrblr, pinfo->rx_fifosize);
+
 		/* Set the mode register.  We want to keep a copy of the
 		 * enables, because we want to put them back if they were
 		 * present.
@@ -604,6 +622,7 @@
 		out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval |
 		    SMCMR_SM_UART | prev_mode);
 	} else {
+		out_be16(&pinfo->sccup->scc_genscc.scc_mrblr, pinfo->rx_fifosize);
 		out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
 	}
 
diff --git a/drivers/serial/ifx6x60.c b/drivers/serial/ifx6x60.c
new file mode 100644
index 0000000..ab93763
--- /dev/null
+++ b/drivers/serial/ifx6x60.c
@@ -0,0 +1,1406 @@
+/****************************************************************************
+ *
+ * Driver for the IFX 6x60 spi modem.
+ *
+ * Copyright (C) 2008 Option International
+ * Copyright (C) 2008 Filip Aben <f.aben@option.com>
+ *		      Denis Joseph Barrow <d.barow@option.com>
+ *		      Jan Dumon <j.dumon@option.com>
+ *
+ * Copyright (C) 2009, 2010 Intel Corp
+ * Russ Gorby <richardx.r.gorby@intel.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 Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA
+ *
+ * Driver modified by Intel from Option gtm501l_spi.c
+ *
+ * Notes
+ * o	The driver currently assumes a single device only. If you need to
+ *	change this then look for saved_ifx_dev and add a device lookup
+ * o	The driver is intended to be big-endian safe but has never been
+ *	tested that way (no suitable hardware). There are a couple of FIXME
+ *	notes by areas that may need addressing
+ * o	Some of the GPIO naming/setup assumptions may need revisiting if
+ *	you need to use this driver for another platform.
+ *
+ *****************************************************************************/
+#include <linux/module.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/tty.h>
+#include <linux/kfifo.h>
+#include <linux/tty_flip.h>
+#include <linux/timer.h>
+#include <linux/serial.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/rfkill.h>
+#include <linux/fs.h>
+#include <linux/ip.h>
+#include <linux/dmapool.h>
+#include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/tty.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/spi/ifx_modem.h>
+#include <linux/delay.h>
+
+#include "ifx6x60.h"
+
+#define IFX_SPI_MORE_MASK		0x10
+#define IFX_SPI_MORE_BIT		12	/* bit position in u16 */
+#define IFX_SPI_CTS_BIT			13	/* bit position in u16 */
+#define IFX_SPI_TTY_ID			0
+#define IFX_SPI_TIMEOUT_SEC		2
+#define IFX_SPI_HEADER_0		(-1)
+#define IFX_SPI_HEADER_F		(-2)
+
+/* forward reference */
+static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
+
+/* local variables */
+static int spi_b16 = 1;			/* 8 or 16 bit word length */
+static struct tty_driver *tty_drv;
+static struct ifx_spi_device *saved_ifx_dev;
+static struct lock_class_key ifx_spi_key;
+
+/* GPIO/GPE settings */
+
+/**
+ *	mrdy_set_high		-	set MRDY GPIO
+ *	@ifx: device we are controlling
+ *
+ */
+static inline void mrdy_set_high(struct ifx_spi_device *ifx)
+{
+	gpio_set_value(ifx->gpio.mrdy, 1);
+}
+
+/**
+ *	mrdy_set_low		-	clear MRDY GPIO
+ *	@ifx: device we are controlling
+ *
+ */
+static inline void mrdy_set_low(struct ifx_spi_device *ifx)
+{
+	gpio_set_value(ifx->gpio.mrdy, 0);
+}
+
+/**
+ *	ifx_spi_power_state_set
+ *	@ifx_dev: our SPI device
+ *	@val: bits to set
+ *
+ *	Set bit in power status and signal power system if status becomes non-0
+ */
+static void
+ifx_spi_power_state_set(struct ifx_spi_device *ifx_dev, unsigned char val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ifx_dev->power_lock, flags);
+
+	/*
+	 * if power status is already non-0, just update, else
+	 * tell power system
+	 */
+	if (!ifx_dev->power_status)
+		pm_runtime_get(&ifx_dev->spi_dev->dev);
+	ifx_dev->power_status |= val;
+
+	spin_unlock_irqrestore(&ifx_dev->power_lock, flags);
+}
+
+/**
+ *	ifx_spi_power_state_clear	-	clear power bit
+ *	@ifx_dev: our SPI device
+ *	@val: bits to clear
+ *
+ *	clear bit in power status and signal power system if status becomes 0
+ */
+static void
+ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ifx_dev->power_lock, flags);
+
+	if (ifx_dev->power_status) {
+		ifx_dev->power_status &= ~val;
+		if (!ifx_dev->power_status)
+			pm_runtime_put(&ifx_dev->spi_dev->dev);
+	}
+
+	spin_unlock_irqrestore(&ifx_dev->power_lock, flags);
+}
+
+/**
+ *	swap_buf
+ *	@buf: our buffer
+ *	@len : number of bytes (not words) in the buffer
+ *	@end: end of buffer
+ *
+ *	Swap the contents of a buffer into big endian format
+ */
+static inline void swap_buf(u16 *buf, int len, void *end)
+{
+	int n;
+
+	len = ((len + 1) >> 1);
+	if ((void *)&buf[len] > end) {
+		pr_err("swap_buf: swap exceeds boundary (%p > %p)!",
+		       &buf[len], end);
+		return;
+	}
+	for (n = 0; n < len; n++) {
+		*buf = cpu_to_be16(*buf);
+		buf++;
+	}
+}
+
+/**
+ *	mrdy_assert		-	assert MRDY line
+ *	@ifx_dev: our SPI device
+ *
+ *	Assert mrdy and set timer to wait for SRDY interrupt, if SRDY is low
+ *	now.
+ *
+ *	FIXME: Can SRDY even go high as we are running this code ?
+ */
+static void mrdy_assert(struct ifx_spi_device *ifx_dev)
+{
+	int val = gpio_get_value(ifx_dev->gpio.srdy);
+	if (!val) {
+		if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
+				      &ifx_dev->flags)) {
+			ifx_dev->spi_timer.expires =
+				jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
+			add_timer(&ifx_dev->spi_timer);
+
+		}
+	}
+	ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_DATA_PENDING);
+	mrdy_set_high(ifx_dev);
+}
+
+/**
+ *	ifx_spi_hangup		-	hang up an IFX device
+ *	@ifx_dev: our SPI device
+ *
+ *	Hang up the tty attached to the IFX device if one is currently
+ *	open. If not take no action
+ */
+static void ifx_spi_ttyhangup(struct ifx_spi_device *ifx_dev)
+{
+	struct tty_port *pport = &ifx_dev->tty_port;
+	struct tty_struct *tty = tty_port_tty_get(pport);
+	if (tty) {
+		tty_hangup(tty);
+		tty_kref_put(tty);
+	}
+}
+
+/**
+ *	ifx_spi_timeout		-	SPI timeout
+ *	@arg: our SPI device
+ *
+ *	The SPI has timed out: hang up the tty. Users will then see a hangup
+ *	and error events.
+ */
+static void ifx_spi_timeout(unsigned long arg)
+{
+	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
+
+	dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
+	ifx_spi_ttyhangup(ifx_dev);
+	mrdy_set_low(ifx_dev);
+	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
+}
+
+/* char/tty operations */
+
+/**
+ *	ifx_spi_tiocmget	-	get modem lines
+ *	@tty: our tty device
+ *	@filp: file handle issuing the request
+ *
+ *	Map the signal state into Linux modem flags and report the value
+ *	in Linux terms
+ */
+static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp)
+{
+	unsigned int value;
+	struct ifx_spi_device *ifx_dev = tty->driver_data;
+
+	value =
+	(test_bit(IFX_SPI_RTS, &ifx_dev->signal_state) ? TIOCM_RTS : 0) |
+	(test_bit(IFX_SPI_DTR, &ifx_dev->signal_state) ? TIOCM_DTR : 0) |
+	(test_bit(IFX_SPI_CTS, &ifx_dev->signal_state) ? TIOCM_CTS : 0) |
+	(test_bit(IFX_SPI_DSR, &ifx_dev->signal_state) ? TIOCM_DSR : 0) |
+	(test_bit(IFX_SPI_DCD, &ifx_dev->signal_state) ? TIOCM_CAR : 0) |
+	(test_bit(IFX_SPI_RI, &ifx_dev->signal_state) ? TIOCM_RNG : 0);
+	return value;
+}
+
+/**
+ *	ifx_spi_tiocmset	-	set modem bits
+ *	@tty: the tty structure
+ *	@filp: file handle issuing the request
+ *	@set: bits to set
+ *	@clear: bits to clear
+ *
+ *	The IFX6x60 only supports DTR and RTS. Set them accordingly
+ *	and flag that an update to the modem is needed.
+ *
+ *	FIXME: do we need to kick the tranfers when we do this ?
+ */
+static int ifx_spi_tiocmset(struct tty_struct *tty, struct file *filp,
+			    unsigned int set, unsigned int clear)
+{
+	struct ifx_spi_device *ifx_dev = tty->driver_data;
+
+	if (set & TIOCM_RTS)
+		set_bit(IFX_SPI_RTS, &ifx_dev->signal_state);
+	if (set & TIOCM_DTR)
+		set_bit(IFX_SPI_DTR, &ifx_dev->signal_state);
+	if (clear & TIOCM_RTS)
+		clear_bit(IFX_SPI_RTS, &ifx_dev->signal_state);
+	if (clear & TIOCM_DTR)
+		clear_bit(IFX_SPI_DTR, &ifx_dev->signal_state);
+
+	set_bit(IFX_SPI_UPDATE, &ifx_dev->signal_state);
+	return 0;
+}
+
+/**
+ *	ifx_spi_open	-	called on tty open
+ *	@tty: our tty device
+ *	@filp: file handle being associated with the tty
+ *
+ *	Open the tty interface. We let the tty_port layer do all the work
+ *	for us.
+ *
+ *	FIXME: Remove single device assumption and saved_ifx_dev
+ */
+static int ifx_spi_open(struct tty_struct *tty, struct file *filp)
+{
+	return tty_port_open(&saved_ifx_dev->tty_port, tty, filp);
+}
+
+/**
+ *	ifx_spi_close	-	called when our tty closes
+ *	@tty: the tty being closed
+ *	@filp: the file handle being closed
+ *
+ *	Perform the close of the tty. We use the tty_port layer to do all
+ *	our hard work.
+ */
+static void ifx_spi_close(struct tty_struct *tty, struct file *filp)
+{
+	struct ifx_spi_device *ifx_dev = tty->driver_data;
+	tty_port_close(&ifx_dev->tty_port, tty, filp);
+	/* FIXME: should we do an ifx_spi_reset here ? */
+}
+
+/**
+ *	ifx_decode_spi_header	-	decode received header
+ *	@buffer: the received data
+ *	@length: decoded length
+ *	@more: decoded more flag
+ *	@received_cts: status of cts we received
+ *
+ *	Note how received_cts is handled -- if header is all F it is left
+ *	the same as it was, if header is all 0 it is set to 0 otherwise it is
+ *	taken from the incoming header.
+ *
+ *	FIXME: endianness
+ */
+static int ifx_spi_decode_spi_header(unsigned char *buffer, int *length,
+			unsigned char *more, unsigned char *received_cts)
+{
+	u16 h1;
+	u16 h2;
+	u16 *in_buffer = (u16 *)buffer;
+
+	h1 = *in_buffer;
+	h2 = *(in_buffer+1);
+
+	if (h1 == 0 && h2 == 0) {
+		*received_cts = 0;
+		return IFX_SPI_HEADER_0;
+	} else if (h1 == 0xffff && h2 == 0xffff) {
+		/* spi_slave_cts remains as it was */
+		return IFX_SPI_HEADER_F;
+	}
+
+	*length = h1 & 0xfff;	/* upper bits of byte are flags */
+	*more = (buffer[1] >> IFX_SPI_MORE_BIT) & 1;
+	*received_cts = (buffer[3] >> IFX_SPI_CTS_BIT) & 1;
+	return 0;
+}
+
+/**
+ *	ifx_setup_spi_header	-	set header fields
+ *	@txbuffer: pointer to start of SPI buffer
+ *	@tx_count: bytes
+ *	@more: indicate if more to follow
+ *
+ *	Format up an SPI header for a transfer
+ *
+ *	FIXME: endianness?
+ */
+static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count,
+					unsigned char more)
+{
+	*(u16 *)(txbuffer) = tx_count;
+	*(u16 *)(txbuffer+2) = IFX_SPI_PAYLOAD_SIZE;
+	txbuffer[1] |= (more << IFX_SPI_MORE_BIT) & IFX_SPI_MORE_MASK;
+}
+
+/**
+ *	ifx_spi_wakeup_serial	-	SPI space made
+ *	@port_data: our SPI device
+ *
+ *	We have emptied the FIFO enough that we want to get more data
+ *	queued into it. Poke the line discipline via tty_wakeup so that
+ *	it will feed us more bits
+ */
+static void ifx_spi_wakeup_serial(struct ifx_spi_device *ifx_dev)
+{
+	struct tty_struct *tty;
+
+	tty = tty_port_tty_get(&ifx_dev->tty_port);
+	if (!tty)
+		return;
+	tty_wakeup(tty);
+	tty_kref_put(tty);
+}
+
+/**
+ *	ifx_spi_prepare_tx_buffer	-	prepare transmit frame
+ *	@ifx_dev: our SPI device
+ *
+ *	The transmit buffr needs a header and various other bits of
+ *	information followed by as much data as we can pull from the FIFO
+ *	and transfer. This function formats up a suitable buffer in the
+ *	ifx_dev->tx_buffer
+ *
+ *	FIXME: performance - should we wake the tty when the queue is half
+ *			     empty ?
+ */
+static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
+{
+	int temp_count;
+	int queue_length;
+	int tx_count;
+	unsigned char *tx_buffer;
+
+	tx_buffer = ifx_dev->tx_buffer;
+	memset(tx_buffer, 0, IFX_SPI_TRANSFER_SIZE);
+
+	/* make room for required SPI header */
+	tx_buffer += IFX_SPI_HEADER_OVERHEAD;
+	tx_count = IFX_SPI_HEADER_OVERHEAD;
+
+	/* clear to signal no more data if this turns out to be the
+	 * last buffer sent in a sequence */
+	ifx_dev->spi_more = 0;
+
+	/* if modem cts is set, just send empty buffer */
+	if (!ifx_dev->spi_slave_cts) {
+		/* see if there's tx data */
+		queue_length = kfifo_len(&ifx_dev->tx_fifo);
+		if (queue_length != 0) {
+			/* data to mux -- see if there's room for it */
+			temp_count = min(queue_length, IFX_SPI_PAYLOAD_SIZE);
+			temp_count = kfifo_out_locked(&ifx_dev->tx_fifo,
+					tx_buffer, temp_count,
+					&ifx_dev->fifo_lock);
+
+			/* update buffer pointer and data count in message */
+			tx_buffer += temp_count;
+			tx_count += temp_count;
+			if (temp_count == queue_length)
+				/* poke port to get more data */
+				ifx_spi_wakeup_serial(ifx_dev);
+			else /* more data in port, use next SPI message */
+				ifx_dev->spi_more = 1;
+		}
+	}
+	/* have data and info for header -- set up SPI header in buffer */
+	/* spi header needs payload size, not entire buffer size */
+	ifx_spi_setup_spi_header(ifx_dev->tx_buffer,
+					tx_count-IFX_SPI_HEADER_OVERHEAD,
+					ifx_dev->spi_more);
+	/* swap actual data in the buffer */
+	swap_buf((u16 *)(ifx_dev->tx_buffer), tx_count,
+		&ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]);
+	return tx_count;
+}
+
+/**
+ *	ifx_spi_write		-	line discipline write
+ *	@tty: our tty device
+ *	@buf: pointer to buffer to write (kernel space)
+ *	@count: size of buffer
+ *
+ *	Write the characters we have been given into the FIFO. If the device
+ *	is not active then activate it, when the SRDY line is asserted back
+ *	this will commence I/O
+ */
+static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf,
+			 int count)
+{
+	struct ifx_spi_device *ifx_dev = tty->driver_data;
+	unsigned char *tmp_buf = (unsigned char *)buf;
+	int tx_count = kfifo_in_locked(&ifx_dev->tx_fifo, tmp_buf, count,
+				   &ifx_dev->fifo_lock);
+	mrdy_assert(ifx_dev);
+	return tx_count;
+}
+
+/**
+ *	ifx_spi_chars_in_buffer	-	line discipline helper
+ *	@tty: our tty device
+ *
+ *	Report how much data we can accept before we drop bytes. As we use
+ *	a simple FIFO this is nice and easy.
+ */
+static int ifx_spi_write_room(struct tty_struct *tty)
+{
+	struct ifx_spi_device *ifx_dev = tty->driver_data;
+	return IFX_SPI_FIFO_SIZE - kfifo_len(&ifx_dev->tx_fifo);
+}
+
+/**
+ *	ifx_spi_chars_in_buffer	-	line discipline helper
+ *	@tty: our tty device
+ *
+ *	Report how many characters we have buffered. In our case this is the
+ *	number of bytes sitting in our transmit FIFO.
+ */
+static int ifx_spi_chars_in_buffer(struct tty_struct *tty)
+{
+	struct ifx_spi_device *ifx_dev = tty->driver_data;
+	return kfifo_len(&ifx_dev->tx_fifo);
+}
+
+/**
+ *	ifx_port_hangup
+ *	@port: our tty port
+ *
+ *	tty port hang up. Called when tty_hangup processing is invoked either
+ *	by loss of carrier, or by software (eg vhangup). Serialized against
+ *	activate/shutdown by the tty layer.
+ */
+static void ifx_spi_hangup(struct tty_struct *tty)
+{
+	struct ifx_spi_device *ifx_dev = tty->driver_data;
+	tty_port_hangup(&ifx_dev->tty_port);
+}
+
+/**
+ *	ifx_port_activate
+ *	@port: our tty port
+ *
+ *	tty port activate method - called for first open. Serialized
+ *	with hangup and shutdown by the tty layer.
+ */
+static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct ifx_spi_device *ifx_dev =
+		container_of(port, struct ifx_spi_device, tty_port);
+
+	/* clear any old data; can't do this in 'close' */
+	kfifo_reset(&ifx_dev->tx_fifo);
+
+	/* put port data into this tty */
+	tty->driver_data = ifx_dev;
+
+	/* allows flip string push from int context */
+	tty->low_latency = 1;
+
+	return 0;
+}
+
+/**
+ *	ifx_port_shutdown
+ *	@port: our tty port
+ *
+ *	tty port shutdown method - called for last port close. Serialized
+ *	with hangup and activate by the tty layer.
+ */
+static void ifx_port_shutdown(struct tty_port *port)
+{
+	struct ifx_spi_device *ifx_dev =
+		container_of(port, struct ifx_spi_device, tty_port);
+
+	mrdy_set_low(ifx_dev);
+	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
+	tasklet_kill(&ifx_dev->io_work_tasklet);
+}
+
+static const struct tty_port_operations ifx_tty_port_ops = {
+	.activate = ifx_port_activate,
+	.shutdown = ifx_port_shutdown,
+};
+
+static const struct tty_operations ifx_spi_serial_ops = {
+	.open = ifx_spi_open,
+	.close = ifx_spi_close,
+	.write = ifx_spi_write,
+	.hangup = ifx_spi_hangup,
+	.write_room = ifx_spi_write_room,
+	.chars_in_buffer = ifx_spi_chars_in_buffer,
+	.tiocmget = ifx_spi_tiocmget,
+	.tiocmset = ifx_spi_tiocmset,
+};
+
+/**
+ *	ifx_spi_insert_fip_string	-	queue received data
+ *	@ifx_ser: our SPI device
+ *	@chars: buffer we have received
+ *	@size: number of chars reeived
+ *
+ *	Queue bytes to the tty assuming the tty side is currently open. If
+ *	not the discard the data.
+ */
+static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev,
+				    unsigned char *chars, size_t size)
+{
+	struct tty_struct *tty = tty_port_tty_get(&ifx_dev->tty_port);
+	if (!tty)
+		return;
+	tty_insert_flip_string(tty, chars, size);
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+/**
+ *	ifx_spi_complete	-	SPI transfer completed
+ *	@ctx: our SPI device
+ *
+ *	An SPI transfer has completed. Process any received data and kick off
+ *	any further transmits we can commence.
+ */
+static void ifx_spi_complete(void *ctx)
+{
+	struct ifx_spi_device *ifx_dev = ctx;
+	struct tty_struct *tty;
+	struct tty_ldisc *ldisc = NULL;
+	int length;
+	int actual_length;
+	unsigned char more;
+	unsigned char cts;
+	int local_write_pending = 0;
+	int queue_length;
+	int srdy;
+	int decode_result;
+
+	mrdy_set_low(ifx_dev);
+
+	if (!ifx_dev->spi_msg.status) {
+		/* check header validity, get comm flags */
+		swap_buf((u16 *)ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
+			&ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]);
+		decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer,
+				&length, &more, &cts);
+		if (decode_result == IFX_SPI_HEADER_0) {
+			dev_dbg(&ifx_dev->spi_dev->dev,
+				"ignore input: invalid header 0");
+			ifx_dev->spi_slave_cts = 0;
+			goto complete_exit;
+		} else if (decode_result == IFX_SPI_HEADER_F) {
+			dev_dbg(&ifx_dev->spi_dev->dev,
+				"ignore input: invalid header F");
+			goto complete_exit;
+		}
+
+		ifx_dev->spi_slave_cts = cts;
+
+		actual_length = min((unsigned int)length,
+					ifx_dev->spi_msg.actual_length);
+		swap_buf((u16 *)(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
+			 actual_length,
+			 &ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]);
+		ifx_spi_insert_flip_string(
+			ifx_dev,
+			ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD,
+			(size_t)actual_length);
+	} else {
+		dev_dbg(&ifx_dev->spi_dev->dev, "SPI transfer error %d",
+		       ifx_dev->spi_msg.status);
+	}
+
+complete_exit:
+	if (ifx_dev->write_pending) {
+		ifx_dev->write_pending = 0;
+		local_write_pending = 1;
+	}
+
+	clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &(ifx_dev->flags));
+
+	queue_length = kfifo_len(&ifx_dev->tx_fifo);
+	srdy = gpio_get_value(ifx_dev->gpio.srdy);
+	if (!srdy)
+		ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_SRDY);
+
+	/* schedule output if there is more to do */
+	if (test_and_clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags))
+		tasklet_schedule(&ifx_dev->io_work_tasklet);
+	else {
+		if (more || ifx_dev->spi_more || queue_length > 0 ||
+			local_write_pending) {
+			if (ifx_dev->spi_slave_cts) {
+				if (more)
+					mrdy_assert(ifx_dev);
+			} else
+				mrdy_assert(ifx_dev);
+		} else {
+			/*
+			 * poke line discipline driver if any for more data
+			 * may or may not get more data to write
+			 * for now, say not busy
+			 */
+			ifx_spi_power_state_clear(ifx_dev,
+						  IFX_SPI_POWER_DATA_PENDING);
+			tty = tty_port_tty_get(&ifx_dev->tty_port);
+			if (tty) {
+				ldisc = tty_ldisc_ref(tty);
+				if (ldisc) {
+					ldisc->ops->write_wakeup(tty);
+					tty_ldisc_deref(ldisc);
+				}
+				tty_kref_put(tty);
+			}
+		}
+	}
+}
+
+/**
+ *	ifx_spio_io		-	I/O tasklet
+ *	@data: our SPI device
+ *
+ *	Queue data for transmission if possible and then kick off the
+ *	transfer.
+ */
+static void ifx_spi_io(unsigned long data)
+{
+	int retval;
+	struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
+
+	if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) {
+		if (ifx_dev->gpio.unack_srdy_int_nb > 0)
+			ifx_dev->gpio.unack_srdy_int_nb--;
+
+		ifx_spi_prepare_tx_buffer(ifx_dev);
+
+		spi_message_init(&ifx_dev->spi_msg);
+		INIT_LIST_HEAD(&ifx_dev->spi_msg.queue);
+
+		ifx_dev->spi_msg.context = ifx_dev;
+		ifx_dev->spi_msg.complete = ifx_spi_complete;
+
+		/* set up our spi transfer */
+		/* note len is BYTES, not transfers */
+		ifx_dev->spi_xfer.len = IFX_SPI_TRANSFER_SIZE;
+		ifx_dev->spi_xfer.cs_change = 0;
+		ifx_dev->spi_xfer.speed_hz = 12500000;
+		/* ifx_dev->spi_xfer.speed_hz = 390625; */
+		ifx_dev->spi_xfer.bits_per_word = spi_b16 ? 16 : 8;
+
+		ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer;
+		ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer;
+
+		/*
+		 * setup dma pointers
+		 */
+		if (ifx_dev->is_6160) {
+			ifx_dev->spi_msg.is_dma_mapped = 1;
+			ifx_dev->tx_dma = ifx_dev->tx_bus;
+			ifx_dev->rx_dma = ifx_dev->rx_bus;
+			ifx_dev->spi_xfer.tx_dma = ifx_dev->tx_dma;
+			ifx_dev->spi_xfer.rx_dma = ifx_dev->rx_dma;
+		} else {
+			ifx_dev->spi_msg.is_dma_mapped = 0;
+			ifx_dev->tx_dma = (dma_addr_t)0;
+			ifx_dev->rx_dma = (dma_addr_t)0;
+			ifx_dev->spi_xfer.tx_dma = (dma_addr_t)0;
+			ifx_dev->spi_xfer.rx_dma = (dma_addr_t)0;
+		}
+
+		spi_message_add_tail(&ifx_dev->spi_xfer, &ifx_dev->spi_msg);
+
+		/* Assert MRDY. This may have already been done by the write
+		 * routine.
+		 */
+		mrdy_assert(ifx_dev);
+
+		retval = spi_async(ifx_dev->spi_dev, &ifx_dev->spi_msg);
+		if (retval) {
+			clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS,
+				  &ifx_dev->flags);
+			tasklet_schedule(&ifx_dev->io_work_tasklet);
+			return;
+		}
+	} else
+		ifx_dev->write_pending = 1;
+}
+
+/**
+ *	ifx_spi_free_port	-	free up the tty side
+ *	@ifx_dev: IFX device going away
+ *
+ *	Unregister and free up a port when the device goes away
+ */
+static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev)
+{
+	if (ifx_dev->tty_dev)
+		tty_unregister_device(tty_drv, ifx_dev->minor);
+	kfifo_free(&ifx_dev->tx_fifo);
+}
+
+/**
+ *	ifx_spi_create_port	-	create a new port
+ *	@ifx_dev: our spi device
+ *
+ *	Allocate and initialise the tty port that goes with this interface
+ *	and add it to the tty layer so that it can be opened.
+ */
+static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
+{
+	int ret = 0;
+	struct tty_port *pport = &ifx_dev->tty_port;
+
+	spin_lock_init(&ifx_dev->fifo_lock);
+	lockdep_set_class_and_subclass(&ifx_dev->fifo_lock,
+		&ifx_spi_key, 0);
+
+	if (kfifo_alloc(&ifx_dev->tx_fifo, IFX_SPI_FIFO_SIZE, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	pport->ops = &ifx_tty_port_ops;
+	tty_port_init(pport);
+	ifx_dev->minor = IFX_SPI_TTY_ID;
+	ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor,
+					       &ifx_dev->spi_dev->dev);
+	if (IS_ERR(ifx_dev->tty_dev)) {
+		dev_dbg(&ifx_dev->spi_dev->dev,
+			"%s: registering tty device failed", __func__);
+		ret = PTR_ERR(ifx_dev->tty_dev);
+		goto error_ret;
+	}
+	return 0;
+
+error_ret:
+	ifx_spi_free_port(ifx_dev);
+	return ret;
+}
+
+/**
+ *	ifx_spi_handle_srdy		-	handle SRDY
+ *	@ifx_dev: device asserting SRDY
+ *
+ *	Check our device state and see what we need to kick off when SRDY
+ *	is asserted. This usually means killing the timer and firing off the
+ *	I/O processing.
+ */
+static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev)
+{
+	if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) {
+		del_timer_sync(&ifx_dev->spi_timer);
+		clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
+	}
+
+	ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_SRDY);
+
+	if (!test_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags))
+		tasklet_schedule(&ifx_dev->io_work_tasklet);
+	else
+		set_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
+}
+
+/**
+ *	ifx_spi_srdy_interrupt	-	SRDY asserted
+ *	@irq: our IRQ number
+ *	@dev: our ifx device
+ *
+ *	The modem asserted SRDY. Handle the srdy event
+ */
+static irqreturn_t ifx_spi_srdy_interrupt(int irq, void *dev)
+{
+	struct ifx_spi_device *ifx_dev = dev;
+	ifx_dev->gpio.unack_srdy_int_nb++;
+	ifx_spi_handle_srdy(ifx_dev);
+	return IRQ_HANDLED;
+}
+
+/**
+ *	ifx_spi_reset_interrupt	-	Modem has changed reset state
+ *	@irq: interrupt number
+ *	@dev: our device pointer
+ *
+ *	The modem has either entered or left reset state. Check the GPIO
+ *	line to see which.
+ *
+ *	FIXME: review locking on MR_INPROGRESS versus
+ *	parallel unsolicited reset/solicited reset
+ */
+static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
+{
+	struct ifx_spi_device *ifx_dev = dev;
+	int val = gpio_get_value(ifx_dev->gpio.reset_out);
+	int solreset = test_bit(MR_START, &ifx_dev->mdm_reset_state);
+
+	if (val == 0) {
+		/* entered reset */
+		set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
+		if (!solreset) {
+			/* unsolicited reset  */
+			ifx_spi_ttyhangup(ifx_dev);
+		}
+	} else {
+		/* exited reset */
+		clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
+		if (solreset) {
+			set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state);
+			wake_up(&ifx_dev->mdm_reset_wait);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+/**
+ *	ifx_spi_free_device - free device
+ *	@ifx_dev: device to free
+ *
+ *	Free the IFX device
+ */
+static void ifx_spi_free_device(struct ifx_spi_device *ifx_dev)
+{
+	ifx_spi_free_port(ifx_dev);
+	dma_free_coherent(&ifx_dev->spi_dev->dev,
+				IFX_SPI_TRANSFER_SIZE,
+				ifx_dev->tx_buffer,
+				ifx_dev->tx_bus);
+	dma_free_coherent(&ifx_dev->spi_dev->dev,
+				IFX_SPI_TRANSFER_SIZE,
+				ifx_dev->rx_buffer,
+				ifx_dev->rx_bus);
+}
+
+/**
+ *	ifx_spi_reset	-	reset modem
+ *	@ifx_dev: modem to reset
+ *
+ *	Perform a reset on the modem
+ */
+static int ifx_spi_reset(struct ifx_spi_device *ifx_dev)
+{
+	int ret;
+	/*
+	 * set up modem power, reset
+	 *
+	 * delays are required on some platforms for the modem
+	 * to reset properly
+	 */
+	set_bit(MR_START, &ifx_dev->mdm_reset_state);
+	gpio_set_value(ifx_dev->gpio.po, 0);
+	gpio_set_value(ifx_dev->gpio.reset, 0);
+	msleep(25);
+	gpio_set_value(ifx_dev->gpio.reset, 1);
+	msleep(1);
+	gpio_set_value(ifx_dev->gpio.po, 1);
+	msleep(1);
+	gpio_set_value(ifx_dev->gpio.po, 0);
+	ret = wait_event_timeout(ifx_dev->mdm_reset_wait,
+				 test_bit(MR_COMPLETE,
+					  &ifx_dev->mdm_reset_state),
+				 IFX_RESET_TIMEOUT);
+	if (!ret)
+		dev_warn(&ifx_dev->spi_dev->dev, "Modem reset timeout: (state:%lx)",
+			 ifx_dev->mdm_reset_state);
+
+	ifx_dev->mdm_reset_state = 0;
+	return ret;
+}
+
+/**
+ *	ifx_spi_spi_probe	-	probe callback
+ *	@spi: our possible matching SPI device
+ *
+ *	Probe for a 6x60 modem on SPI bus. Perform any needed device and
+ *	GPIO setup.
+ *
+ *	FIXME:
+ *	-	Support for multiple devices
+ *	-	Split out MID specific GPIO handling eventually
+ */
+
+static int ifx_spi_spi_probe(struct spi_device *spi)
+{
+	int ret;
+	int srdy;
+	struct ifx_modem_platform_data *pl_data = NULL;
+	struct ifx_spi_device *ifx_dev;
+
+	if (saved_ifx_dev) {
+		dev_dbg(&spi->dev, "ignoring subsequent detection");
+		return -ENODEV;
+	}
+
+	/* initialize structure to hold our device variables */
+	ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL);
+	if (!ifx_dev) {
+		dev_err(&spi->dev, "spi device allocation failed");
+		return -ENOMEM;
+	}
+	saved_ifx_dev = ifx_dev;
+	ifx_dev->spi_dev = spi;
+	clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
+	spin_lock_init(&ifx_dev->write_lock);
+	spin_lock_init(&ifx_dev->power_lock);
+	ifx_dev->power_status = 0;
+	init_timer(&ifx_dev->spi_timer);
+	ifx_dev->spi_timer.function = ifx_spi_timeout;
+	ifx_dev->spi_timer.data = (unsigned long)ifx_dev;
+	ifx_dev->is_6160 = pl_data->is_6160;
+
+	/* ensure SPI protocol flags are initialized to enable transfer */
+	ifx_dev->spi_more = 0;
+	ifx_dev->spi_slave_cts = 0;
+
+	/*initialize transfer and dma buffers */
+	ifx_dev->tx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev,
+				IFX_SPI_TRANSFER_SIZE,
+				&ifx_dev->tx_bus,
+				GFP_KERNEL);
+	if (!ifx_dev->tx_buffer) {
+		dev_err(&spi->dev, "DMA-TX buffer allocation failed");
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	ifx_dev->rx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev,
+				IFX_SPI_TRANSFER_SIZE,
+				&ifx_dev->rx_bus,
+				GFP_KERNEL);
+	if (!ifx_dev->rx_buffer) {
+		dev_err(&spi->dev, "DMA-RX buffer allocation failed");
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	/* initialize waitq for modem reset */
+	init_waitqueue_head(&ifx_dev->mdm_reset_wait);
+
+	spi_set_drvdata(spi, ifx_dev);
+	tasklet_init(&ifx_dev->io_work_tasklet, ifx_spi_io,
+						(unsigned long)ifx_dev);
+
+	set_bit(IFX_SPI_STATE_PRESENT, &ifx_dev->flags);
+
+	/* create our tty port */
+	ret = ifx_spi_create_port(ifx_dev);
+	if (ret != 0) {
+		dev_err(&spi->dev, "create default tty port failed");
+		goto error_ret;
+	}
+
+	pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data;
+	if (pl_data) {
+		ifx_dev->gpio.reset = pl_data->rst_pmu;
+		ifx_dev->gpio.po = pl_data->pwr_on;
+		ifx_dev->gpio.mrdy = pl_data->mrdy;
+		ifx_dev->gpio.srdy = pl_data->srdy;
+		ifx_dev->gpio.reset_out = pl_data->rst_out;
+	} else {
+		dev_err(&spi->dev, "missing platform data!");
+		ret = -ENODEV;
+		goto error_ret;
+	}
+
+	dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d",
+		 ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy,
+		 ifx_dev->gpio.srdy, ifx_dev->gpio.reset_out);
+
+	/* Configure gpios */
+	ret = gpio_request(ifx_dev->gpio.reset, "ifxModem");
+	if (ret < 0) {
+		dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET)",
+			ifx_dev->gpio.reset);
+		goto error_ret;
+	}
+	ret += gpio_direction_output(ifx_dev->gpio.reset, 0);
+	ret += gpio_export(ifx_dev->gpio.reset, 1);
+	if (ret) {
+		dev_err(&spi->dev, "Unable to configure GPIO%d (RESET)",
+			ifx_dev->gpio.reset);
+		ret = -EBUSY;
+		goto error_ret2;
+	}
+
+	ret = gpio_request(ifx_dev->gpio.po, "ifxModem");
+	ret += gpio_direction_output(ifx_dev->gpio.po, 0);
+	ret += gpio_export(ifx_dev->gpio.po, 1);
+	if (ret) {
+		dev_err(&spi->dev, "Unable to configure GPIO%d (ON)",
+			ifx_dev->gpio.po);
+		ret = -EBUSY;
+		goto error_ret3;
+	}
+
+	ret = gpio_request(ifx_dev->gpio.mrdy, "ifxModem");
+	if (ret < 0) {
+		dev_err(&spi->dev, "Unable to allocate GPIO%d (MRDY)",
+			ifx_dev->gpio.mrdy);
+		goto error_ret3;
+	}
+	ret += gpio_export(ifx_dev->gpio.mrdy, 1);
+	ret += gpio_direction_output(ifx_dev->gpio.mrdy, 0);
+	if (ret) {
+		dev_err(&spi->dev, "Unable to configure GPIO%d (MRDY)",
+			ifx_dev->gpio.mrdy);
+		ret = -EBUSY;
+		goto error_ret4;
+	}
+
+	ret = gpio_request(ifx_dev->gpio.srdy, "ifxModem");
+	if (ret < 0) {
+		dev_err(&spi->dev, "Unable to allocate GPIO%d (SRDY)",
+			ifx_dev->gpio.srdy);
+		ret = -EBUSY;
+		goto error_ret4;
+	}
+	ret += gpio_export(ifx_dev->gpio.srdy, 1);
+	ret += gpio_direction_input(ifx_dev->gpio.srdy);
+	if (ret) {
+		dev_err(&spi->dev, "Unable to configure GPIO%d (SRDY)",
+			ifx_dev->gpio.srdy);
+		ret = -EBUSY;
+		goto error_ret5;
+	}
+
+	ret = gpio_request(ifx_dev->gpio.reset_out, "ifxModem");
+	if (ret < 0) {
+		dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET_OUT)",
+			ifx_dev->gpio.reset_out);
+		goto error_ret5;
+	}
+	ret += gpio_export(ifx_dev->gpio.reset_out, 1);
+	ret += gpio_direction_input(ifx_dev->gpio.reset_out);
+	if (ret) {
+		dev_err(&spi->dev, "Unable to configure GPIO%d (RESET_OUT)",
+			ifx_dev->gpio.reset_out);
+		ret = -EBUSY;
+		goto error_ret6;
+	}
+
+	ret = request_irq(gpio_to_irq(ifx_dev->gpio.reset_out),
+			  ifx_spi_reset_interrupt,
+			  IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME,
+		(void *)ifx_dev);
+	if (ret) {
+		dev_err(&spi->dev, "Unable to get irq %x\n",
+			gpio_to_irq(ifx_dev->gpio.reset_out));
+		goto error_ret6;
+	}
+
+	ret = ifx_spi_reset(ifx_dev);
+
+	ret = request_irq(gpio_to_irq(ifx_dev->gpio.srdy),
+			  ifx_spi_srdy_interrupt,
+			  IRQF_TRIGGER_RISING, DRVNAME,
+			  (void *)ifx_dev);
+	if (ret) {
+		dev_err(&spi->dev, "Unable to get irq %x",
+			gpio_to_irq(ifx_dev->gpio.srdy));
+		goto error_ret7;
+	}
+
+	/* set pm runtime power state and register with power system */
+	pm_runtime_set_active(&spi->dev);
+	pm_runtime_enable(&spi->dev);
+
+	/* handle case that modem is already signaling SRDY */
+	/* no outgoing tty open at this point, this just satisfies the
+	 * modem's read and should reset communication properly
+	 */
+	srdy = gpio_get_value(ifx_dev->gpio.srdy);
+
+	if (srdy) {
+		mrdy_assert(ifx_dev);
+		ifx_spi_handle_srdy(ifx_dev);
+	} else
+		mrdy_set_low(ifx_dev);
+	return 0;
+
+error_ret7:
+	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), (void *)ifx_dev);
+error_ret6:
+	gpio_free(ifx_dev->gpio.srdy);
+error_ret5:
+	gpio_free(ifx_dev->gpio.mrdy);
+error_ret4:
+	gpio_free(ifx_dev->gpio.reset);
+error_ret3:
+	gpio_free(ifx_dev->gpio.po);
+error_ret2:
+	gpio_free(ifx_dev->gpio.reset_out);
+error_ret:
+	ifx_spi_free_device(ifx_dev);
+	saved_ifx_dev = NULL;
+	return ret;
+}
+
+/**
+ *	ifx_spi_spi_remove	-	SPI device was removed
+ *	@spi: SPI device
+ *
+ *	FIXME: We should be shutting the device down here not in
+ *	the module unload path.
+ */
+
+static int ifx_spi_spi_remove(struct spi_device *spi)
+{
+	struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
+	/* stop activity */
+	tasklet_kill(&ifx_dev->io_work_tasklet);
+	/* free irq */
+	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), (void *)ifx_dev);
+	free_irq(gpio_to_irq(ifx_dev->gpio.srdy), (void *)ifx_dev);
+
+	gpio_free(ifx_dev->gpio.srdy);
+	gpio_free(ifx_dev->gpio.mrdy);
+	gpio_free(ifx_dev->gpio.reset);
+	gpio_free(ifx_dev->gpio.po);
+	gpio_free(ifx_dev->gpio.reset_out);
+
+	/* free allocations */
+	ifx_spi_free_device(ifx_dev);
+
+	saved_ifx_dev = NULL;
+	return 0;
+}
+
+/**
+ *	ifx_spi_spi_shutdown	-	called on SPI shutdown
+ *	@spi: SPI device
+ *
+ *	No action needs to be taken here
+ */
+
+static void ifx_spi_spi_shutdown(struct spi_device *spi)
+{
+}
+
+/*
+ * various suspends and resumes have nothing to do
+ * no hardware to save state for
+ */
+
+/**
+ *	ifx_spi_spi_suspend	-	suspend SPI on system suspend
+ *	@dev: device being suspended
+ *
+ *	Suspend the SPI side. No action needed on Intel MID platforms, may
+ *	need extending for other systems.
+ */
+static int ifx_spi_spi_suspend(struct spi_device *spi, pm_message_t msg)
+{
+	return 0;
+}
+
+/**
+ *	ifx_spi_spi_resume	-	resume SPI side on system resume
+ *	@dev: device being suspended
+ *
+ *	Suspend the SPI side. No action needed on Intel MID platforms, may
+ *	need extending for other systems.
+ */
+static int ifx_spi_spi_resume(struct spi_device *spi)
+{
+	return 0;
+}
+
+/**
+ *	ifx_spi_pm_suspend	-	suspend modem on system suspend
+ *	@dev: device being suspended
+ *
+ *	Suspend the modem. No action needed on Intel MID platforms, may
+ *	need extending for other systems.
+ */
+static int ifx_spi_pm_suspend(struct device *dev)
+{
+	return 0;
+}
+
+/**
+ *	ifx_spi_pm_resume	-	resume modem on system resume
+ *	@dev: device being suspended
+ *
+ *	Allow the modem to resume. No action needed.
+ *
+ *	FIXME: do we need to reset anything here ?
+ */
+static int ifx_spi_pm_resume(struct device *dev)
+{
+	return 0;
+}
+
+/**
+ *	ifx_spi_pm_runtime_resume	-	suspend modem
+ *	@dev: device being suspended
+ *
+ *	Allow the modem to resume. No action needed.
+ */
+static int ifx_spi_pm_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+/**
+ *	ifx_spi_pm_runtime_suspend	-	suspend modem
+ *	@dev: device being suspended
+ *
+ *	Allow the modem to suspend and thus suspend to continue up the
+ *	device tree.
+ */
+static int ifx_spi_pm_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+/**
+ *	ifx_spi_pm_runtime_idle		-	check if modem idle
+ *	@dev: our device
+ *
+ *	Check conditions and queue runtime suspend if idle.
+ */
+static int ifx_spi_pm_runtime_idle(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
+
+	if (!ifx_dev->power_status)
+		pm_runtime_suspend(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops ifx_spi_pm = {
+	.resume = ifx_spi_pm_resume,
+	.suspend = ifx_spi_pm_suspend,
+	.runtime_resume = ifx_spi_pm_runtime_resume,
+	.runtime_suspend = ifx_spi_pm_runtime_suspend,
+	.runtime_idle = ifx_spi_pm_runtime_idle
+};
+
+static const struct spi_device_id ifx_id_table[] = {
+	{"ifx6160", 0},
+	{"ifx6260", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ifx_id_table);
+
+/* spi operations */
+static const struct spi_driver ifx_spi_driver_6160 = {
+	.driver = {
+		.name = "ifx6160",
+		.bus = &spi_bus_type,
+		.pm = &ifx_spi_pm,
+		.owner = THIS_MODULE},
+	.probe = ifx_spi_spi_probe,
+	.shutdown = ifx_spi_spi_shutdown,
+	.remove = __devexit_p(ifx_spi_spi_remove),
+	.suspend = ifx_spi_spi_suspend,
+	.resume = ifx_spi_spi_resume,
+	.id_table = ifx_id_table
+};
+
+/**
+ *	ifx_spi_exit	-	module exit
+ *
+ *	Unload the module.
+ */
+
+static void __exit ifx_spi_exit(void)
+{
+	/* unregister */
+	tty_unregister_driver(tty_drv);
+	spi_unregister_driver((void *)&ifx_spi_driver_6160);
+}
+
+/**
+ *	ifx_spi_init		-	module entry point
+ *
+ *	Initialise the SPI and tty interfaces for the IFX SPI driver
+ *	We need to initialize upper-edge spi driver after the tty
+ *	driver because otherwise the spi probe will race
+ */
+
+static int __init ifx_spi_init(void)
+{
+	int result;
+
+	tty_drv = alloc_tty_driver(1);
+	if (!tty_drv) {
+		pr_err("%s: alloc_tty_driver failed", DRVNAME);
+		return -ENOMEM;
+	}
+
+	tty_drv->magic = TTY_DRIVER_MAGIC;
+	tty_drv->owner = THIS_MODULE;
+	tty_drv->driver_name = DRVNAME;
+	tty_drv->name = TTYNAME;
+	tty_drv->minor_start = IFX_SPI_TTY_ID;
+	tty_drv->num = 1;
+	tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
+	tty_drv->subtype = SERIAL_TYPE_NORMAL;
+	tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_drv->init_termios = tty_std_termios;
+
+	tty_set_operations(tty_drv, &ifx_spi_serial_ops);
+
+	result = tty_register_driver(tty_drv);
+	if (result) {
+		pr_err("%s: tty_register_driver failed(%d)",
+			DRVNAME, result);
+		put_tty_driver(tty_drv);
+		return result;
+	}
+
+	result = spi_register_driver((void *)&ifx_spi_driver_6160);
+	if (result) {
+		pr_err("%s: spi_register_driver failed(%d)",
+			DRVNAME, result);
+		tty_unregister_driver(tty_drv);
+	}
+	return result;
+}
+
+module_init(ifx_spi_init);
+module_exit(ifx_spi_exit);
+
+MODULE_AUTHOR("Intel");
+MODULE_DESCRIPTION("IFX6x60 spi driver");
+MODULE_LICENSE("GPL");
+MODULE_INFO(Version, "0.1-IFX6x60");
diff --git a/drivers/serial/ifx6x60.h b/drivers/serial/ifx6x60.h
new file mode 100644
index 0000000..deb7b8d
--- /dev/null
+++ b/drivers/serial/ifx6x60.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+ *
+ * Driver for the IFX spi modem.
+ *
+ * Copyright (C) 2009, 2010 Intel Corp
+ * Jim Stanley <jim.stanley@intel.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 Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA
+ *
+ *
+ *
+ *****************************************************************************/
+#ifndef _IFX6X60_H
+#define _IFX6X60_H
+
+#define DRVNAME				"ifx6x60"
+#define TTYNAME				"ttyIFX"
+
+/* #define IFX_THROTTLE_CODE */
+
+#define IFX_SPI_MAX_MINORS		1
+#define IFX_SPI_TRANSFER_SIZE		2048
+#define IFX_SPI_FIFO_SIZE		4096
+
+#define IFX_SPI_HEADER_OVERHEAD		4
+#define IFX_RESET_TIMEOUT		msecs_to_jiffies(50)
+
+/* device flags bitfield definitions */
+#define IFX_SPI_STATE_PRESENT		0
+#define IFX_SPI_STATE_IO_IN_PROGRESS	1
+#define IFX_SPI_STATE_IO_READY		2
+#define IFX_SPI_STATE_TIMER_PENDING	3
+
+/* flow control bitfields */
+#define IFX_SPI_DCD			0
+#define IFX_SPI_CTS			1
+#define IFX_SPI_DSR			2
+#define IFX_SPI_RI			3
+#define IFX_SPI_DTR			4
+#define IFX_SPI_RTS			5
+#define IFX_SPI_TX_FC			6
+#define IFX_SPI_RX_FC			7
+#define IFX_SPI_UPDATE			8
+
+#define IFX_SPI_PAYLOAD_SIZE		(IFX_SPI_TRANSFER_SIZE - \
+						IFX_SPI_HEADER_OVERHEAD)
+
+#define IFX_SPI_IRQ_TYPE		DETECT_EDGE_RISING
+#define IFX_SPI_GPIO_TARGET		0
+#define IFX_SPI_GPIO0			0x105
+
+#define IFX_SPI_STATUS_TIMEOUT		(2000*HZ)
+
+/* values for bits in power status byte */
+#define IFX_SPI_POWER_DATA_PENDING	1
+#define IFX_SPI_POWER_SRDY		2
+
+struct ifx_spi_device {
+	/* Our SPI device */
+	struct spi_device *spi_dev;
+
+	/* Port specific data */
+	struct kfifo tx_fifo;
+	spinlock_t fifo_lock;
+	unsigned long signal_state;
+
+	/* TTY Layer logic */
+	struct tty_port tty_port;
+	struct device *tty_dev;
+	int minor;
+
+	/* Low level I/O work */
+	struct tasklet_struct io_work_tasklet;
+	unsigned long flags;
+	dma_addr_t rx_dma;
+	dma_addr_t tx_dma;
+
+	int is_6160;				/* Modem type */
+
+	spinlock_t write_lock;
+	int write_pending;
+	spinlock_t power_lock;
+	unsigned char power_status;
+
+	unsigned char *rx_buffer;
+	unsigned char *tx_buffer;
+	dma_addr_t rx_bus;
+	dma_addr_t tx_bus;
+	unsigned char spi_more;
+	unsigned char spi_slave_cts;
+
+	struct timer_list spi_timer;
+
+	struct spi_message spi_msg;
+	struct spi_transfer spi_xfer;
+
+	struct {
+		/* gpio lines */
+		unsigned short srdy;		/* slave-ready gpio */
+		unsigned short mrdy;		/* master-ready gpio */
+		unsigned short reset;		/* modem-reset gpio */
+		unsigned short po;		/* modem-on gpio */
+		unsigned short reset_out;	/* modem-in-reset gpio */
+		/* state/stats */
+		int unack_srdy_int_nb;
+	} gpio;
+
+	/* modem reset */
+	unsigned long mdm_reset_state;
+#define MR_START	0
+#define MR_INPROGRESS	1
+#define MR_COMPLETE	2
+	wait_queue_head_t mdm_reset_wait;
+};
+
+#endif /* _IFX6X60_H */
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index c4399e2..126ec7f 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -838,7 +838,11 @@
 static const char *
 mpc52xx_uart_type(struct uart_port *port)
 {
-	return port->type == PORT_MPC52xx ? "MPC52xx PSC" : NULL;
+	/*
+	 * We keep using PORT_MPC52xx for historic reasons although it applies
+	 * for MPC512x, too, but print "MPC5xxx" to not irritate users
+	 */
+	return port->type == PORT_MPC52xx ? "MPC5xxx PSC" : NULL;
 }
 
 static void
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c
index f8c816e..8e43a7b 100644
--- a/drivers/serial/msm_serial.c
+++ b/drivers/serial/msm_serial.c
@@ -686,7 +686,7 @@
 	msm_port = UART_TO_MSM(port);
 
 	msm_port->clk = clk_get(&pdev->dev, "uart_clk");
-	if (unlikely(IS_ERR(msm_port->clk)))
+	if (IS_ERR(msm_port->clk))
 		return PTR_ERR(msm_port->clk);
 	port->uartclk = clk_get_rate(msm_port->clk);
 	printk(KERN_INFO "uartclk = %d\n", port->uartclk);
diff --git a/drivers/serial/omap-serial.c b/drivers/serial/omap-serial.c
index 14365f7..7f2f010 100644
--- a/drivers/serial/omap-serial.c
+++ b/drivers/serial/omap-serial.c
@@ -570,7 +570,7 @@
 	unsigned char efr = 0;
 
 	up->lcr = serial_in(up, UART_LCR);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	up->efr = serial_in(up, UART_EFR);
 	serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
 
@@ -598,7 +598,7 @@
 		efr |= OMAP_UART_SW_RX;
 
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
-	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
 	up->mcr = serial_in(up, UART_MCR);
 
@@ -612,14 +612,14 @@
 		up->mcr |= UART_MCR_XONANY;
 
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
 	/* Enable special char function UARTi.EFR_REG[5] and
 	 * load the new software flow control mode IXON or IXOFF
 	 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
 	 */
 	serial_out(up, UART_EFR, efr | UART_EFR_SCD);
-	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
 	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
 	serial_out(up, UART_LCR, up->lcr);
@@ -724,22 +724,22 @@
 	 * baud clock is not running
 	 * DLL_REG and DLH_REG set to 0.
 	 */
-	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_out(up, UART_DLL, 0);
 	serial_out(up, UART_DLM, 0);
 	serial_out(up, UART_LCR, 0);
 
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	up->efr = serial_in(up, UART_EFR);
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
-	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	up->mcr = serial_in(up, UART_MCR);
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	/* FIFO ENABLE, DMA MODE */
 	serial_out(up, UART_FCR, up->fcr);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	if (up->use_dma) {
 		serial_out(up, UART_TI752_TLR, 0);
@@ -748,52 +748,52 @@
 	}
 
 	serial_out(up, UART_EFR, up->efr);
-	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 	serial_out(up, UART_MCR, up->mcr);
 
 	/* Protocol, Baud Rate, and Interrupt Settings */
 
-	serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_DISABLE);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	up->efr = serial_in(up, UART_EFR);
 	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
 	serial_out(up, UART_LCR, 0);
 	serial_out(up, UART_IER, 0);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
 	serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
 
 	serial_out(up, UART_LCR, 0);
 	serial_out(up, UART_IER, up->ier);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
 	serial_out(up, UART_EFR, up->efr);
 	serial_out(up, UART_LCR, cval);
 
 	if (baud > 230400 && baud != 3000000)
-		serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE13X);
+		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE);
 	else
-		serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE16X);
+		serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
 
 	/* Hardware Flow Control Configuration */
 
 	if (termios->c_cflag & CRTSCTS) {
 		efr |= (UART_EFR_CTS | UART_EFR_RTS);
-		serial_out(up, UART_LCR, UART_LCR_DLAB);
+		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
 		up->mcr = serial_in(up, UART_MCR);
 		serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 
-		serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 		up->efr = serial_in(up, UART_EFR);
 		serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
 		serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
 		serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
-		serial_out(up, UART_LCR, UART_LCR_DLAB);
+		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 		serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
 		serial_out(up, UART_LCR, cval);
 	}
@@ -815,13 +815,13 @@
 	unsigned char efr;
 
 	dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	efr = serial_in(up, UART_EFR);
 	serial_out(up, UART_EFR, efr | UART_EFR_ECB);
 	serial_out(up, UART_LCR, 0);
 
 	serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
-	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_EFR, efr);
 	serial_out(up, UART_LCR, 0);
 	/* Enable module level wake up */
@@ -866,12 +866,6 @@
 	return up->name;
 }
 
-#ifdef CONFIG_SERIAL_OMAP_CONSOLE
-
-static struct uart_omap_port *serial_omap_console_ports[4];
-
-static struct uart_driver serial_omap_reg;
-
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
 
 static inline void wait_for_xmitr(struct uart_omap_port *up)
@@ -905,6 +899,34 @@
 	}
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+
+static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	wait_for_xmitr(up);
+	serial_out(up, UART_TX, ch);
+}
+
+static int serial_omap_poll_get_char(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned int status = serial_in(up, UART_LSR);
+
+	if (!(status & UART_LSR_DR))
+		return NO_POLL_CHAR;
+
+	return serial_in(up, UART_RX);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+
+static struct uart_omap_port *serial_omap_console_ports[4];
+
+static struct uart_driver serial_omap_reg;
+
 static void serial_omap_console_putchar(struct uart_port *port, int ch)
 {
 	struct uart_omap_port *up = (struct uart_omap_port *)port;
@@ -1022,6 +1044,10 @@
 	.request_port	= serial_omap_request_port,
 	.config_port	= serial_omap_config_port,
 	.verify_port	= serial_omap_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_put_char  = serial_omap_poll_put_char,
+	.poll_get_char  = serial_omap_poll_get_char,
+#endif
 };
 
 static struct uart_driver serial_omap_reg = {
diff --git a/drivers/serial/pch_uart.c b/drivers/serial/pch_uart.c
new file mode 100644
index 0000000..70a6145
--- /dev/null
+++ b/drivers/serial/pch_uart.c
@@ -0,0 +1,1451 @@
+/*
+ *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/serial_reg.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/serial_core.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <linux/dmaengine.h>
+#include <linux/pch_dma.h>
+
+enum {
+	PCH_UART_HANDLED_RX_INT_SHIFT,
+	PCH_UART_HANDLED_TX_INT_SHIFT,
+	PCH_UART_HANDLED_RX_ERR_INT_SHIFT,
+	PCH_UART_HANDLED_RX_TRG_INT_SHIFT,
+	PCH_UART_HANDLED_MS_INT_SHIFT,
+};
+
+enum {
+	PCH_UART_8LINE,
+	PCH_UART_2LINE,
+};
+
+#define PCH_UART_DRIVER_DEVICE "ttyPCH"
+
+#define PCH_UART_NR_GE_256FIFO		1
+#define PCH_UART_NR_GE_64FIFO		3
+#define PCH_UART_NR_GE	(PCH_UART_NR_GE_256FIFO+PCH_UART_NR_GE_64FIFO)
+#define PCH_UART_NR	PCH_UART_NR_GE
+
+#define PCH_UART_HANDLED_RX_INT	(1<<((PCH_UART_HANDLED_RX_INT_SHIFT)<<1))
+#define PCH_UART_HANDLED_TX_INT	(1<<((PCH_UART_HANDLED_TX_INT_SHIFT)<<1))
+#define PCH_UART_HANDLED_RX_ERR_INT	(1<<((\
+					PCH_UART_HANDLED_RX_ERR_INT_SHIFT)<<1))
+#define PCH_UART_HANDLED_RX_TRG_INT	(1<<((\
+					PCH_UART_HANDLED_RX_TRG_INT_SHIFT)<<1))
+#define PCH_UART_HANDLED_MS_INT	(1<<((PCH_UART_HANDLED_MS_INT_SHIFT)<<1))
+
+#define PCH_UART_RBR		0x00
+#define PCH_UART_THR		0x00
+
+#define PCH_UART_IER_MASK	(PCH_UART_IER_ERBFI|PCH_UART_IER_ETBEI|\
+				PCH_UART_IER_ELSI|PCH_UART_IER_EDSSI)
+#define PCH_UART_IER_ERBFI	0x00000001
+#define PCH_UART_IER_ETBEI	0x00000002
+#define PCH_UART_IER_ELSI	0x00000004
+#define PCH_UART_IER_EDSSI	0x00000008
+
+#define PCH_UART_IIR_IP			0x00000001
+#define PCH_UART_IIR_IID		0x00000006
+#define PCH_UART_IIR_MSI		0x00000000
+#define PCH_UART_IIR_TRI		0x00000002
+#define PCH_UART_IIR_RRI		0x00000004
+#define PCH_UART_IIR_REI		0x00000006
+#define PCH_UART_IIR_TOI		0x00000008
+#define PCH_UART_IIR_FIFO256		0x00000020
+#define PCH_UART_IIR_FIFO64		PCH_UART_IIR_FIFO256
+#define PCH_UART_IIR_FE			0x000000C0
+
+#define PCH_UART_FCR_FIFOE		0x00000001
+#define PCH_UART_FCR_RFR		0x00000002
+#define PCH_UART_FCR_TFR		0x00000004
+#define PCH_UART_FCR_DMS		0x00000008
+#define PCH_UART_FCR_FIFO256		0x00000020
+#define PCH_UART_FCR_RFTL		0x000000C0
+
+#define PCH_UART_FCR_RFTL1		0x00000000
+#define PCH_UART_FCR_RFTL64		0x00000040
+#define PCH_UART_FCR_RFTL128		0x00000080
+#define PCH_UART_FCR_RFTL224		0x000000C0
+#define PCH_UART_FCR_RFTL16		PCH_UART_FCR_RFTL64
+#define PCH_UART_FCR_RFTL32		PCH_UART_FCR_RFTL128
+#define PCH_UART_FCR_RFTL56		PCH_UART_FCR_RFTL224
+#define PCH_UART_FCR_RFTL4		PCH_UART_FCR_RFTL64
+#define PCH_UART_FCR_RFTL8		PCH_UART_FCR_RFTL128
+#define PCH_UART_FCR_RFTL14		PCH_UART_FCR_RFTL224
+#define PCH_UART_FCR_RFTL_SHIFT		6
+
+#define PCH_UART_LCR_WLS	0x00000003
+#define PCH_UART_LCR_STB	0x00000004
+#define PCH_UART_LCR_PEN	0x00000008
+#define PCH_UART_LCR_EPS	0x00000010
+#define PCH_UART_LCR_SP		0x00000020
+#define PCH_UART_LCR_SB		0x00000040
+#define PCH_UART_LCR_DLAB	0x00000080
+#define PCH_UART_LCR_NP		0x00000000
+#define PCH_UART_LCR_OP		PCH_UART_LCR_PEN
+#define PCH_UART_LCR_EP		(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS)
+#define PCH_UART_LCR_1P		(PCH_UART_LCR_PEN | PCH_UART_LCR_SP)
+#define PCH_UART_LCR_0P		(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS |\
+				PCH_UART_LCR_SP)
+
+#define PCH_UART_LCR_5BIT	0x00000000
+#define PCH_UART_LCR_6BIT	0x00000001
+#define PCH_UART_LCR_7BIT	0x00000002
+#define PCH_UART_LCR_8BIT	0x00000003
+
+#define PCH_UART_MCR_DTR	0x00000001
+#define PCH_UART_MCR_RTS	0x00000002
+#define PCH_UART_MCR_OUT	0x0000000C
+#define PCH_UART_MCR_LOOP	0x00000010
+#define PCH_UART_MCR_AFE	0x00000020
+
+#define PCH_UART_LSR_DR		0x00000001
+#define PCH_UART_LSR_ERR	(1<<7)
+
+#define PCH_UART_MSR_DCTS	0x00000001
+#define PCH_UART_MSR_DDSR	0x00000002
+#define PCH_UART_MSR_TERI	0x00000004
+#define PCH_UART_MSR_DDCD	0x00000008
+#define PCH_UART_MSR_CTS	0x00000010
+#define PCH_UART_MSR_DSR	0x00000020
+#define PCH_UART_MSR_RI		0x00000040
+#define PCH_UART_MSR_DCD	0x00000080
+#define PCH_UART_MSR_DELTA	(PCH_UART_MSR_DCTS | PCH_UART_MSR_DDSR |\
+				PCH_UART_MSR_TERI | PCH_UART_MSR_DDCD)
+
+#define PCH_UART_DLL		0x00
+#define PCH_UART_DLM		0x01
+
+#define DIV_ROUND(a, b)	(((a) + ((b)/2)) / (b))
+
+#define PCH_UART_IID_RLS	(PCH_UART_IIR_REI)
+#define PCH_UART_IID_RDR	(PCH_UART_IIR_RRI)
+#define PCH_UART_IID_RDR_TO	(PCH_UART_IIR_RRI | PCH_UART_IIR_TOI)
+#define PCH_UART_IID_THRE	(PCH_UART_IIR_TRI)
+#define PCH_UART_IID_MS		(PCH_UART_IIR_MSI)
+
+#define PCH_UART_HAL_PARITY_NONE	(PCH_UART_LCR_NP)
+#define PCH_UART_HAL_PARITY_ODD		(PCH_UART_LCR_OP)
+#define PCH_UART_HAL_PARITY_EVEN	(PCH_UART_LCR_EP)
+#define PCH_UART_HAL_PARITY_FIX1	(PCH_UART_LCR_1P)
+#define PCH_UART_HAL_PARITY_FIX0	(PCH_UART_LCR_0P)
+#define PCH_UART_HAL_5BIT		(PCH_UART_LCR_5BIT)
+#define PCH_UART_HAL_6BIT		(PCH_UART_LCR_6BIT)
+#define PCH_UART_HAL_7BIT		(PCH_UART_LCR_7BIT)
+#define PCH_UART_HAL_8BIT		(PCH_UART_LCR_8BIT)
+#define PCH_UART_HAL_STB1		0
+#define PCH_UART_HAL_STB2		(PCH_UART_LCR_STB)
+
+#define PCH_UART_HAL_CLR_TX_FIFO	(PCH_UART_FCR_TFR)
+#define PCH_UART_HAL_CLR_RX_FIFO	(PCH_UART_FCR_RFR)
+#define PCH_UART_HAL_CLR_ALL_FIFO	(PCH_UART_HAL_CLR_TX_FIFO | \
+					PCH_UART_HAL_CLR_RX_FIFO)
+
+#define PCH_UART_HAL_DMA_MODE0		0
+#define PCH_UART_HAL_FIFO_DIS		0
+#define PCH_UART_HAL_FIFO16		(PCH_UART_FCR_FIFOE)
+#define PCH_UART_HAL_FIFO256		(PCH_UART_FCR_FIFOE | \
+					PCH_UART_FCR_FIFO256)
+#define PCH_UART_HAL_FIFO64		(PCH_UART_HAL_FIFO256)
+#define PCH_UART_HAL_TRIGGER1		(PCH_UART_FCR_RFTL1)
+#define PCH_UART_HAL_TRIGGER64		(PCH_UART_FCR_RFTL64)
+#define PCH_UART_HAL_TRIGGER128		(PCH_UART_FCR_RFTL128)
+#define PCH_UART_HAL_TRIGGER224		(PCH_UART_FCR_RFTL224)
+#define PCH_UART_HAL_TRIGGER16		(PCH_UART_FCR_RFTL16)
+#define PCH_UART_HAL_TRIGGER32		(PCH_UART_FCR_RFTL32)
+#define PCH_UART_HAL_TRIGGER56		(PCH_UART_FCR_RFTL56)
+#define PCH_UART_HAL_TRIGGER4		(PCH_UART_FCR_RFTL4)
+#define PCH_UART_HAL_TRIGGER8		(PCH_UART_FCR_RFTL8)
+#define PCH_UART_HAL_TRIGGER14		(PCH_UART_FCR_RFTL14)
+#define PCH_UART_HAL_TRIGGER_L		(PCH_UART_FCR_RFTL64)
+#define PCH_UART_HAL_TRIGGER_M		(PCH_UART_FCR_RFTL128)
+#define PCH_UART_HAL_TRIGGER_H		(PCH_UART_FCR_RFTL224)
+
+#define PCH_UART_HAL_RX_INT		(PCH_UART_IER_ERBFI)
+#define PCH_UART_HAL_TX_INT		(PCH_UART_IER_ETBEI)
+#define PCH_UART_HAL_RX_ERR_INT		(PCH_UART_IER_ELSI)
+#define PCH_UART_HAL_MS_INT		(PCH_UART_IER_EDSSI)
+#define PCH_UART_HAL_ALL_INT		(PCH_UART_IER_MASK)
+
+#define PCH_UART_HAL_DTR		(PCH_UART_MCR_DTR)
+#define PCH_UART_HAL_RTS		(PCH_UART_MCR_RTS)
+#define PCH_UART_HAL_OUT		(PCH_UART_MCR_OUT)
+#define PCH_UART_HAL_LOOP		(PCH_UART_MCR_LOOP)
+#define PCH_UART_HAL_AFE		(PCH_UART_MCR_AFE)
+
+struct pch_uart_buffer {
+	unsigned char *buf;
+	int size;
+};
+
+struct eg20t_port {
+	struct uart_port port;
+	int port_type;
+	void __iomem *membase;
+	resource_size_t mapbase;
+	unsigned int iobase;
+	struct pci_dev *pdev;
+	int fifo_size;
+	int base_baud;
+	int start_tx;
+	int start_rx;
+	int tx_empty;
+	int int_dis_flag;
+	int trigger;
+	int trigger_level;
+	struct pch_uart_buffer rxbuf;
+	unsigned int dmsr;
+	unsigned int fcr;
+	unsigned int use_dma;
+	unsigned int use_dma_flag;
+	struct dma_async_tx_descriptor	*desc_tx;
+	struct dma_async_tx_descriptor	*desc_rx;
+	struct pch_dma_slave		param_tx;
+	struct pch_dma_slave		param_rx;
+	struct dma_chan			*chan_tx;
+	struct dma_chan			*chan_rx;
+	struct scatterlist		sg_tx;
+	struct scatterlist		sg_rx;
+	int				tx_dma_use;
+	void				*rx_buf_virt;
+	dma_addr_t			rx_buf_dma;
+};
+
+static unsigned int default_baud = 9600;
+static const int trigger_level_256[4] = { 1, 64, 128, 224 };
+static const int trigger_level_64[4] = { 1, 16, 32, 56 };
+static const int trigger_level_16[4] = { 1, 4, 8, 14 };
+static const int trigger_level_1[4] = { 1, 1, 1, 1 };
+
+static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize,
+				 int base_baud)
+{
+	struct eg20t_port *priv = pci_get_drvdata(pdev);
+
+	priv->trigger_level = 1;
+	priv->fcr = 0;
+}
+
+static unsigned int get_msr(struct eg20t_port *priv, void __iomem *base)
+{
+	unsigned int msr = ioread8(base + UART_MSR);
+	priv->dmsr |= msr & PCH_UART_MSR_DELTA;
+
+	return msr;
+}
+
+static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv,
+					  unsigned int flag)
+{
+	u8 ier = ioread8(priv->membase + UART_IER);
+	ier |= flag & PCH_UART_IER_MASK;
+	iowrite8(ier, priv->membase + UART_IER);
+}
+
+static void pch_uart_hal_disable_interrupt(struct eg20t_port *priv,
+					   unsigned int flag)
+{
+	u8 ier = ioread8(priv->membase + UART_IER);
+	ier &= ~(flag & PCH_UART_IER_MASK);
+	iowrite8(ier, priv->membase + UART_IER);
+}
+
+static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
+				 unsigned int parity, unsigned int bits,
+				 unsigned int stb)
+{
+	unsigned int dll, dlm, lcr;
+	int div;
+
+	div = DIV_ROUND(priv->base_baud / 16, baud);
+	if (div < 0 || USHRT_MAX <= div) {
+		pr_err("Invalid Baud(div=0x%x)\n", div);
+		return -EINVAL;
+	}
+
+	dll = (unsigned int)div & 0x00FFU;
+	dlm = ((unsigned int)div >> 8) & 0x00FFU;
+
+	if (parity & ~(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS | PCH_UART_LCR_SP)) {
+		pr_err("Invalid parity(0x%x)\n", parity);
+		return -EINVAL;
+	}
+
+	if (bits & ~PCH_UART_LCR_WLS) {
+		pr_err("Invalid bits(0x%x)\n", bits);
+		return -EINVAL;
+	}
+
+	if (stb & ~PCH_UART_LCR_STB) {
+		pr_err("Invalid STB(0x%x)\n", stb);
+		return -EINVAL;
+	}
+
+	lcr = parity;
+	lcr |= bits;
+	lcr |= stb;
+
+	pr_debug("%s:baud = %d, div = %04x, lcr = %02x (%lu)\n",
+		 __func__, baud, div, lcr, jiffies);
+	iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
+	iowrite8(dll, priv->membase + PCH_UART_DLL);
+	iowrite8(dlm, priv->membase + PCH_UART_DLM);
+	iowrite8(lcr, priv->membase + UART_LCR);
+
+	return 0;
+}
+
+static int pch_uart_hal_fifo_reset(struct eg20t_port *priv,
+				    unsigned int flag)
+{
+	if (flag & ~(PCH_UART_FCR_TFR | PCH_UART_FCR_RFR)) {
+		pr_err("%s:Invalid flag(0x%x)\n", __func__, flag);
+		return -EINVAL;
+	}
+
+	iowrite8(PCH_UART_FCR_FIFOE | priv->fcr, priv->membase + UART_FCR);
+	iowrite8(PCH_UART_FCR_FIFOE | priv->fcr | flag,
+		 priv->membase + UART_FCR);
+	iowrite8(priv->fcr, priv->membase + UART_FCR);
+
+	return 0;
+}
+
+static int pch_uart_hal_set_fifo(struct eg20t_port *priv,
+				 unsigned int dmamode,
+				 unsigned int fifo_size, unsigned int trigger)
+{
+	u8 fcr;
+
+	if (dmamode & ~PCH_UART_FCR_DMS) {
+		pr_err("%s:Invalid DMA Mode(0x%x)\n", __func__, dmamode);
+		return -EINVAL;
+	}
+
+	if (fifo_size & ~(PCH_UART_FCR_FIFOE | PCH_UART_FCR_FIFO256)) {
+		pr_err("%s:Invalid FIFO SIZE(0x%x)\n", __func__, fifo_size);
+		return -EINVAL;
+	}
+
+	if (trigger & ~PCH_UART_FCR_RFTL) {
+		pr_err("%s:Invalid TRIGGER(0x%x)\n", __func__, trigger);
+		return -EINVAL;
+	}
+
+	switch (priv->fifo_size) {
+	case 256:
+		priv->trigger_level =
+		    trigger_level_256[trigger >> PCH_UART_FCR_RFTL_SHIFT];
+		break;
+	case 64:
+		priv->trigger_level =
+		    trigger_level_64[trigger >> PCH_UART_FCR_RFTL_SHIFT];
+		break;
+	case 16:
+		priv->trigger_level =
+		    trigger_level_16[trigger >> PCH_UART_FCR_RFTL_SHIFT];
+		break;
+	default:
+		priv->trigger_level =
+		    trigger_level_1[trigger >> PCH_UART_FCR_RFTL_SHIFT];
+		break;
+	}
+	fcr =
+	    dmamode | fifo_size | trigger | PCH_UART_FCR_RFR | PCH_UART_FCR_TFR;
+	iowrite8(PCH_UART_FCR_FIFOE, priv->membase + UART_FCR);
+	iowrite8(PCH_UART_FCR_FIFOE | PCH_UART_FCR_RFR | PCH_UART_FCR_TFR,
+		 priv->membase + UART_FCR);
+	iowrite8(fcr, priv->membase + UART_FCR);
+	priv->fcr = fcr;
+
+	return 0;
+}
+
+static u8 pch_uart_hal_get_modem(struct eg20t_port *priv)
+{
+	priv->dmsr = 0;
+	return get_msr(priv, priv->membase);
+}
+
+static int pch_uart_hal_write(struct eg20t_port *priv,
+			      const unsigned char *buf, int tx_size)
+{
+	int i;
+	unsigned int thr;
+
+	for (i = 0; i < tx_size;) {
+		thr = buf[i++];
+		iowrite8(thr, priv->membase + PCH_UART_THR);
+	}
+	return i;
+}
+
+static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
+			     int rx_size)
+{
+	int i;
+	u8 rbr, lsr;
+
+	lsr = ioread8(priv->membase + UART_LSR);
+	for (i = 0, lsr = ioread8(priv->membase + UART_LSR);
+	     i < rx_size && lsr & UART_LSR_DR;
+	     lsr = ioread8(priv->membase + UART_LSR)) {
+		rbr = ioread8(priv->membase + PCH_UART_RBR);
+		buf[i++] = rbr;
+	}
+	return i;
+}
+
+static unsigned int pch_uart_hal_get_iid(struct eg20t_port *priv)
+{
+	unsigned int iir;
+	int ret;
+
+	iir = ioread8(priv->membase + UART_IIR);
+	ret = (iir & (PCH_UART_IIR_IID | PCH_UART_IIR_TOI | PCH_UART_IIR_IP));
+	return ret;
+}
+
+static u8 pch_uart_hal_get_line_status(struct eg20t_port *priv)
+{
+	return ioread8(priv->membase + UART_LSR);
+}
+
+static void pch_uart_hal_set_break(struct eg20t_port *priv, int on)
+{
+	unsigned int lcr;
+
+	lcr = ioread8(priv->membase + UART_LCR);
+	if (on)
+		lcr |= PCH_UART_LCR_SB;
+	else
+		lcr &= ~PCH_UART_LCR_SB;
+
+	iowrite8(lcr, priv->membase + UART_LCR);
+}
+
+static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
+		   int size)
+{
+	struct uart_port *port;
+	struct tty_struct *tty;
+
+	port = &priv->port;
+	tty = tty_port_tty_get(&port->state->port);
+	if (!tty) {
+		pr_debug("%s:tty is busy now", __func__);
+		return -EBUSY;
+	}
+
+	tty_insert_flip_string(tty, buf, size);
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+
+	return 0;
+}
+
+static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
+{
+	int ret;
+	struct uart_port *port = &priv->port;
+
+	if (port->x_char) {
+		pr_debug("%s:X character send %02x (%lu)\n", __func__,
+			port->x_char, jiffies);
+		buf[0] = port->x_char;
+		port->x_char = 0;
+		ret = 1;
+	} else {
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int dma_push_rx(struct eg20t_port *priv, int size)
+{
+	struct tty_struct *tty;
+	int room;
+	struct uart_port *port = &priv->port;
+
+	port = &priv->port;
+	tty = tty_port_tty_get(&port->state->port);
+	if (!tty) {
+		pr_debug("%s:tty is busy now", __func__);
+		return 0;
+	}
+
+	room = tty_buffer_request_room(tty, size);
+
+	if (room < size)
+		dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
+			 size - room);
+	if (!room)
+		return room;
+
+	tty_insert_flip_string(tty, sg_virt(&priv->sg_rx), size);
+
+	port->icount.rx += room;
+	tty_kref_put(tty);
+
+	return room;
+}
+
+static void pch_free_dma(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	priv = container_of(port, struct eg20t_port, port);
+
+	if (priv->chan_tx) {
+		dma_release_channel(priv->chan_tx);
+		priv->chan_tx = NULL;
+	}
+	if (priv->chan_rx) {
+		dma_release_channel(priv->chan_rx);
+		priv->chan_rx = NULL;
+	}
+	if (sg_dma_address(&priv->sg_rx))
+		dma_free_coherent(port->dev, port->fifosize,
+				  sg_virt(&priv->sg_rx),
+				  sg_dma_address(&priv->sg_rx));
+
+	return;
+}
+
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	struct pch_dma_slave *param = slave;
+
+	if ((chan->chan_id == param->chan_id) && (param->dma_dev ==
+						  chan->device->dev)) {
+		chan->private = param;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static void pch_request_dma(struct uart_port *port)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct pci_dev *dma_dev;
+	struct pch_dma_slave *param;
+	struct eg20t_port *priv =
+				container_of(port, struct eg20t_port, port);
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(0xa, 0)); /* Get DMA's dev
+								information */
+	/* Set Tx DMA */
+	param = &priv->param_tx;
+	param->dma_dev = &dma_dev->dev;
+	param->chan_id = priv->port.line;
+	param->tx_reg = port->mapbase + UART_TX;
+	chan = dma_request_channel(mask, filter, param);
+	if (!chan) {
+		pr_err("%s:dma_request_channel FAILS(Tx)\n", __func__);
+		return;
+	}
+	priv->chan_tx = chan;
+
+	/* Set Rx DMA */
+	param = &priv->param_rx;
+	param->dma_dev = &dma_dev->dev;
+	param->chan_id = priv->port.line + 1; /* Rx = Tx + 1 */
+	param->rx_reg = port->mapbase + UART_RX;
+	chan = dma_request_channel(mask, filter, param);
+	if (!chan) {
+		pr_err("%s:dma_request_channel FAILS(Rx)\n", __func__);
+		dma_release_channel(priv->chan_tx);
+		return;
+	}
+
+	/* Get Consistent memory for DMA */
+	priv->rx_buf_virt = dma_alloc_coherent(port->dev, port->fifosize,
+				    &priv->rx_buf_dma, GFP_KERNEL);
+	priv->chan_rx = chan;
+}
+
+static void pch_dma_rx_complete(void *arg)
+{
+	struct eg20t_port *priv = arg;
+	struct uart_port *port = &priv->port;
+	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+
+	if (!tty) {
+		pr_debug("%s:tty is busy now", __func__);
+		return;
+	}
+
+	if (dma_push_rx(priv, priv->trigger_level))
+		tty_flip_buffer_push(tty);
+
+	tty_kref_put(tty);
+}
+
+static void pch_dma_tx_complete(void *arg)
+{
+	struct eg20t_port *priv = arg;
+	struct uart_port *port = &priv->port;
+	struct circ_buf *xmit = &port->state->xmit;
+
+	xmit->tail += sg_dma_len(&priv->sg_tx);
+	xmit->tail &= UART_XMIT_SIZE - 1;
+	port->icount.tx += sg_dma_len(&priv->sg_tx);
+
+	async_tx_ack(priv->desc_tx);
+	priv->tx_dma_use = 0;
+}
+
+static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size)
+{
+	int count = 0;
+	struct uart_port *port = &priv->port;
+	struct circ_buf *xmit = &port->state->xmit;
+
+	if (uart_tx_stopped(port) || uart_circ_empty(xmit) || count >= size)
+		goto pop_tx_end;
+
+	do {
+		int cnt_to_end =
+		    CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+		int sz = min(size - count, cnt_to_end);
+		memcpy(&buf[count], &xmit->buf[xmit->tail], sz);
+		xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1);
+		count += sz;
+	} while (!uart_circ_empty(xmit) && count < size);
+
+pop_tx_end:
+	pr_debug("%d characters. Remained %d characters. (%lu)\n",
+		 count, size - count, jiffies);
+
+	return count;
+}
+
+static int handle_rx_to(struct eg20t_port *priv)
+{
+	struct pch_uart_buffer *buf;
+	int rx_size;
+	int ret;
+	if (!priv->start_rx) {
+		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
+		return 0;
+	}
+	buf = &priv->rxbuf;
+	do {
+		rx_size = pch_uart_hal_read(priv, buf->buf, buf->size);
+		ret = push_rx(priv, buf->buf, rx_size);
+		if (ret)
+			return 0;
+	} while (rx_size == buf->size);
+
+	return PCH_UART_HANDLED_RX_INT;
+}
+
+static int handle_rx(struct eg20t_port *priv)
+{
+	return handle_rx_to(priv);
+}
+
+static int dma_handle_rx(struct eg20t_port *priv)
+{
+	struct uart_port *port = &priv->port;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sg;
+
+	priv = container_of(port, struct eg20t_port, port);
+	sg = &priv->sg_rx;
+
+	sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */
+
+	sg_dma_len(sg) = priv->fifo_size;
+
+	sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt),
+		     sg_dma_len(sg), (unsigned long)priv->rx_buf_virt &
+		     ~PAGE_MASK);
+
+	sg_dma_address(sg) = priv->rx_buf_dma;
+
+	desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx,
+			sg, 1, DMA_FROM_DEVICE,
+			DMA_PREP_INTERRUPT);
+	if (!desc)
+		return 0;
+
+	priv->desc_rx = desc;
+	desc->callback = pch_dma_rx_complete;
+	desc->callback_param = priv;
+	desc->tx_submit(desc);
+	dma_async_issue_pending(priv->chan_rx);
+
+	return PCH_UART_HANDLED_RX_INT;
+}
+
+static unsigned int handle_tx(struct eg20t_port *priv)
+{
+	struct uart_port *port = &priv->port;
+	struct circ_buf *xmit = &port->state->xmit;
+	int ret;
+	int fifo_size;
+	int tx_size;
+	int size;
+	int tx_empty;
+
+	if (!priv->start_tx) {
+		pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies);
+		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+		priv->tx_empty = 1;
+		return 0;
+	}
+
+	fifo_size = max(priv->fifo_size, 1);
+	tx_empty = 1;
+	if (pop_tx_x(priv, xmit->buf)) {
+		pch_uart_hal_write(priv, xmit->buf, 1);
+		port->icount.tx++;
+		tx_empty = 0;
+		fifo_size--;
+	}
+	size = min(xmit->head - xmit->tail, fifo_size);
+	tx_size = pop_tx(priv, xmit->buf, size);
+	if (tx_size > 0) {
+		ret = pch_uart_hal_write(priv, xmit->buf, tx_size);
+		port->icount.tx += ret;
+		tx_empty = 0;
+	}
+
+	priv->tx_empty = tx_empty;
+
+	if (tx_empty)
+		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+
+	return PCH_UART_HANDLED_TX_INT;
+}
+
+static unsigned int dma_handle_tx(struct eg20t_port *priv)
+{
+	struct uart_port *port = &priv->port;
+	struct circ_buf *xmit = &port->state->xmit;
+	struct scatterlist *sg = &priv->sg_tx;
+	int nent;
+	int fifo_size;
+	int tx_empty;
+	struct dma_async_tx_descriptor *desc;
+
+	if (!priv->start_tx) {
+		pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies);
+		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+		priv->tx_empty = 1;
+		return 0;
+	}
+
+	fifo_size = max(priv->fifo_size, 1);
+	tx_empty = 1;
+	if (pop_tx_x(priv, xmit->buf)) {
+		pch_uart_hal_write(priv, xmit->buf, 1);
+		port->icount.tx++;
+		tx_empty = 0;
+		fifo_size--;
+	}
+
+	pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+
+	priv->tx_dma_use = 1;
+
+	sg_init_table(&priv->sg_tx, 1); /* Initialize SG table */
+
+	sg_set_page(&priv->sg_tx, virt_to_page(xmit->buf),
+		    UART_XMIT_SIZE, (int)xmit->buf & ~PAGE_MASK);
+
+	nent = dma_map_sg(port->dev, &priv->sg_tx, 1, DMA_TO_DEVICE);
+	if (!nent) {
+		pr_err("%s:dma_map_sg Failed\n", __func__);
+		return 0;
+	}
+
+	sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
+	sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
+			      sg->offset;
+	sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail,
+			     UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
+			     xmit->tail, UART_XMIT_SIZE));
+
+	desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx,
+		sg, nent, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		pr_err("%s:device_prep_slave_sg Failed\n", __func__);
+		return 0;
+	}
+
+	dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+
+	priv->desc_tx = desc;
+	desc->callback = pch_dma_tx_complete;
+	desc->callback_param = priv;
+
+	desc->tx_submit(desc);
+
+	dma_async_issue_pending(priv->chan_tx);
+
+	return PCH_UART_HANDLED_TX_INT;
+}
+
+static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
+{
+	u8 fcr = ioread8(priv->membase + UART_FCR);
+
+	/* Reset FIFO */
+	fcr |= UART_FCR_CLEAR_RCVR;
+	iowrite8(fcr, priv->membase + UART_FCR);
+
+	if (lsr & PCH_UART_LSR_ERR)
+		dev_err(&priv->pdev->dev, "Error data in FIFO\n");
+
+	if (lsr & UART_LSR_FE)
+		dev_err(&priv->pdev->dev, "Framing Error\n");
+
+	if (lsr & UART_LSR_PE)
+		dev_err(&priv->pdev->dev, "Parity Error\n");
+
+	if (lsr & UART_LSR_OE)
+		dev_err(&priv->pdev->dev, "Overrun Error\n");
+}
+
+static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
+{
+	struct eg20t_port *priv = dev_id;
+	unsigned int handled;
+	u8 lsr;
+	int ret = 0;
+	unsigned int iid;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->port.lock, flags);
+	handled = 0;
+	while ((iid = pch_uart_hal_get_iid(priv)) > 1) {
+		switch (iid) {
+		case PCH_UART_IID_RLS:	/* Receiver Line Status */
+			lsr = pch_uart_hal_get_line_status(priv);
+			if (lsr & (PCH_UART_LSR_ERR | UART_LSR_FE |
+						UART_LSR_PE | UART_LSR_OE)) {
+				pch_uart_err_ir(priv, lsr);
+				ret = PCH_UART_HANDLED_RX_ERR_INT;
+			}
+			break;
+		case PCH_UART_IID_RDR:	/* Received Data Ready */
+			if (priv->use_dma)
+				ret = dma_handle_rx(priv);
+			else
+				ret = handle_rx(priv);
+			break;
+		case PCH_UART_IID_RDR_TO:	/* Received Data Ready
+						   (FIFO Timeout) */
+			ret = handle_rx_to(priv);
+			break;
+		case PCH_UART_IID_THRE:	/* Transmitter Holding Register
+						   Empty */
+			if (priv->use_dma)
+				ret = dma_handle_tx(priv);
+			else
+				ret = handle_tx(priv);
+			break;
+		case PCH_UART_IID_MS:	/* Modem Status */
+			ret = PCH_UART_HANDLED_MS_INT;
+			break;
+		default:	/* Never junp to this label */
+			pr_err("%s:iid=%d (%lu)\n", __func__, iid, jiffies);
+			ret = -1;
+			break;
+		}
+		handled |= (unsigned int)ret;
+	}
+	if (handled == 0 && iid <= 1) {
+		if (priv->int_dis_flag)
+			priv->int_dis_flag = 0;
+	}
+
+	spin_unlock_irqrestore(&priv->port.lock, flags);
+	return IRQ_RETVAL(handled);
+}
+
+/* This function tests whether the transmitter fifo and shifter for the port
+						described by 'port' is empty. */
+static unsigned int pch_uart_tx_empty(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	int ret;
+	priv = container_of(port, struct eg20t_port, port);
+	if (priv->tx_empty)
+		ret = TIOCSER_TEMT;
+	else
+		ret = 0;
+
+	return ret;
+}
+
+/* Returns the current state of modem control inputs. */
+static unsigned int pch_uart_get_mctrl(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	u8 modem;
+	unsigned int ret = 0;
+
+	priv = container_of(port, struct eg20t_port, port);
+	modem = pch_uart_hal_get_modem(priv);
+
+	if (modem & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+
+	if (modem & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+
+	if (modem & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+
+	if (modem & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+
+	return ret;
+}
+
+static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	u32 mcr = 0;
+	unsigned int dat;
+	struct eg20t_port *priv = container_of(port, struct eg20t_port, port);
+
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+	if (mctrl) {
+		dat = pch_uart_get_mctrl(port);
+		dat |= mcr;
+		iowrite8(dat, priv->membase + UART_MCR);
+	}
+}
+
+static void pch_uart_stop_tx(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	priv = container_of(port, struct eg20t_port, port);
+	priv->start_tx = 0;
+	priv->tx_dma_use = 0;
+}
+
+static void pch_uart_start_tx(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+
+	priv = container_of(port, struct eg20t_port, port);
+
+	if (priv->use_dma)
+		if (priv->tx_dma_use)
+			return;
+
+	priv->start_tx = 1;
+	pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
+}
+
+static void pch_uart_stop_rx(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	priv = container_of(port, struct eg20t_port, port);
+	priv->start_rx = 0;
+	pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
+	priv->int_dis_flag = 1;
+}
+
+/* Enable the modem status interrupts. */
+static void pch_uart_enable_ms(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	priv = container_of(port, struct eg20t_port, port);
+	pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_MS_INT);
+}
+
+/* Control the transmission of a break signal. */
+static void pch_uart_break_ctl(struct uart_port *port, int ctl)
+{
+	struct eg20t_port *priv;
+	unsigned long flags;
+
+	priv = container_of(port, struct eg20t_port, port);
+	spin_lock_irqsave(&port->lock, flags);
+	pch_uart_hal_set_break(priv, ctl);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* Grab any interrupt resources and initialise any low level driver state. */
+static int pch_uart_startup(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	int ret;
+	int fifo_size;
+	int trigger_level;
+
+	priv = container_of(port, struct eg20t_port, port);
+	priv->tx_empty = 1;
+	port->uartclk = priv->base_baud;
+	pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
+	ret = pch_uart_hal_set_line(priv, default_baud,
+			      PCH_UART_HAL_PARITY_NONE, PCH_UART_HAL_8BIT,
+			      PCH_UART_HAL_STB1);
+	if (ret)
+		return ret;
+
+	switch (priv->fifo_size) {
+	case 256:
+		fifo_size = PCH_UART_HAL_FIFO256;
+		break;
+	case 64:
+		fifo_size = PCH_UART_HAL_FIFO64;
+		break;
+	case 16:
+		fifo_size = PCH_UART_HAL_FIFO16;
+	case 1:
+	default:
+		fifo_size = PCH_UART_HAL_FIFO_DIS;
+		break;
+	}
+
+	switch (priv->trigger) {
+	case PCH_UART_HAL_TRIGGER1:
+		trigger_level = 1;
+		break;
+	case PCH_UART_HAL_TRIGGER_L:
+		trigger_level = priv->fifo_size / 4;
+		break;
+	case PCH_UART_HAL_TRIGGER_M:
+		trigger_level = priv->fifo_size / 2;
+		break;
+	case PCH_UART_HAL_TRIGGER_H:
+	default:
+		trigger_level = priv->fifo_size - (priv->fifo_size / 8);
+		break;
+	}
+
+	priv->trigger_level = trigger_level;
+	ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0,
+				    fifo_size, priv->trigger);
+	if (ret < 0)
+		return ret;
+
+	ret = request_irq(priv->port.irq, pch_uart_interrupt, IRQF_SHARED,
+			KBUILD_MODNAME, priv);
+	if (ret < 0)
+		return ret;
+
+	if (priv->use_dma)
+		pch_request_dma(port);
+
+	priv->start_rx = 1;
+	pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT);
+	uart_update_timeout(port, CS8, default_baud);
+
+	return 0;
+}
+
+static void pch_uart_shutdown(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	int ret;
+
+	priv = container_of(port, struct eg20t_port, port);
+	pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
+	pch_uart_hal_fifo_reset(priv, PCH_UART_HAL_CLR_ALL_FIFO);
+	ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0,
+			      PCH_UART_HAL_FIFO_DIS, PCH_UART_HAL_TRIGGER1);
+	if (ret)
+		pr_err("pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
+
+	if (priv->use_dma_flag)
+		pch_free_dma(port);
+
+	free_irq(priv->port.irq, priv);
+}
+
+/* Change the port parameters, including word length, parity, stop
+ *bits.  Update read_status_mask and ignore_status_mask to indicate
+ *the types of events we are interested in receiving.  */
+static void pch_uart_set_termios(struct uart_port *port,
+				 struct ktermios *termios, struct ktermios *old)
+{
+	int baud;
+	int rtn;
+	unsigned int parity, bits, stb;
+	struct eg20t_port *priv;
+	unsigned long flags;
+
+	priv = container_of(port, struct eg20t_port, port);
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		bits = PCH_UART_HAL_5BIT;
+		break;
+	case CS6:
+		bits = PCH_UART_HAL_6BIT;
+		break;
+	case CS7:
+		bits = PCH_UART_HAL_7BIT;
+		break;
+	default:		/* CS8 */
+		bits = PCH_UART_HAL_8BIT;
+		break;
+	}
+	if (termios->c_cflag & CSTOPB)
+		stb = PCH_UART_HAL_STB2;
+	else
+		stb = PCH_UART_HAL_STB1;
+
+	if (termios->c_cflag & PARENB) {
+		if (!(termios->c_cflag & PARODD))
+			parity = PCH_UART_HAL_PARITY_ODD;
+		else
+			parity = PCH_UART_HAL_PARITY_EVEN;
+
+	} else {
+		parity = PCH_UART_HAL_PARITY_NONE;
+	}
+	termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	uart_update_timeout(port, termios->c_cflag, baud);
+	rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb);
+	if (rtn)
+		goto out;
+
+	/* Don't rewrite B0 */
+	if (tty_termios_baud_rate(termios))
+		tty_termios_encode_baud_rate(termios, baud, baud);
+
+out:
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *pch_uart_type(struct uart_port *port)
+{
+	return KBUILD_MODNAME;
+}
+
+static void pch_uart_release_port(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+
+	priv = container_of(port, struct eg20t_port, port);
+	pci_iounmap(priv->pdev, priv->membase);
+	pci_release_regions(priv->pdev);
+}
+
+static int pch_uart_request_port(struct uart_port *port)
+{
+	struct eg20t_port *priv;
+	int ret;
+	void __iomem *membase;
+
+	priv = container_of(port, struct eg20t_port, port);
+	ret = pci_request_regions(priv->pdev, KBUILD_MODNAME);
+	if (ret < 0)
+		return -EBUSY;
+
+	membase = pci_iomap(priv->pdev, 1, 0);
+	if (!membase) {
+		pci_release_regions(priv->pdev);
+		return -EBUSY;
+	}
+	priv->membase = port->membase = membase;
+
+	return 0;
+}
+
+static void pch_uart_config_port(struct uart_port *port, int type)
+{
+	struct eg20t_port *priv;
+
+	priv = container_of(port, struct eg20t_port, port);
+	if (type & UART_CONFIG_TYPE) {
+		port->type = priv->port_type;
+		pch_uart_request_port(port);
+	}
+}
+
+static int pch_uart_verify_port(struct uart_port *port,
+				struct serial_struct *serinfo)
+{
+	struct eg20t_port *priv;
+
+	priv = container_of(port, struct eg20t_port, port);
+	if (serinfo->flags & UPF_LOW_LATENCY) {
+		pr_info("PCH UART : Use PIO Mode (without DMA)\n");
+		priv->use_dma = 0;
+		serinfo->flags &= ~UPF_LOW_LATENCY;
+	} else {
+#ifndef CONFIG_PCH_DMA
+		pr_err("%s : PCH DMA is not Loaded.\n", __func__);
+		return -EOPNOTSUPP;
+#endif
+		priv->use_dma = 1;
+		priv->use_dma_flag = 1;
+		pr_info("PCH UART : Use DMA Mode\n");
+	}
+
+	return 0;
+}
+
+static struct uart_ops pch_uart_ops = {
+	.tx_empty = pch_uart_tx_empty,
+	.set_mctrl = pch_uart_set_mctrl,
+	.get_mctrl = pch_uart_get_mctrl,
+	.stop_tx = pch_uart_stop_tx,
+	.start_tx = pch_uart_start_tx,
+	.stop_rx = pch_uart_stop_rx,
+	.enable_ms = pch_uart_enable_ms,
+	.break_ctl = pch_uart_break_ctl,
+	.startup = pch_uart_startup,
+	.shutdown = pch_uart_shutdown,
+	.set_termios = pch_uart_set_termios,
+/*	.pm		= pch_uart_pm,		Not supported yet */
+/*	.set_wake	= pch_uart_set_wake,	Not supported yet */
+	.type = pch_uart_type,
+	.release_port = pch_uart_release_port,
+	.request_port = pch_uart_request_port,
+	.config_port = pch_uart_config_port,
+	.verify_port = pch_uart_verify_port
+};
+
+static struct uart_driver pch_uart_driver = {
+	.owner = THIS_MODULE,
+	.driver_name = KBUILD_MODNAME,
+	.dev_name = PCH_UART_DRIVER_DEVICE,
+	.major = 0,
+	.minor = 0,
+	.nr = PCH_UART_NR,
+};
+
+static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
+						int port_type)
+{
+	struct eg20t_port *priv;
+	int ret;
+	unsigned int iobase;
+	unsigned int mapbase;
+	unsigned char *rxbuf;
+	int fifosize, base_baud;
+	static int num;
+
+	priv = kzalloc(sizeof(struct eg20t_port), GFP_KERNEL);
+	if (priv == NULL)
+		goto init_port_alloc_err;
+
+	rxbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (!rxbuf)
+		goto init_port_free_txbuf;
+
+	switch (port_type) {
+	case PORT_UNKNOWN:
+		fifosize = 256; /* UART0 */
+		base_baud = 1843200; /* 1.8432MHz */
+		break;
+	case PORT_8250:
+		fifosize = 64; /* UART1~3 */
+		base_baud = 1843200; /* 1.8432MHz */
+		break;
+	default:
+		dev_err(&pdev->dev, "Invalid Port Type(=%d)\n", port_type);
+		goto init_port_hal_free;
+	}
+
+	iobase = pci_resource_start(pdev, 0);
+	mapbase = pci_resource_start(pdev, 1);
+	priv->mapbase = mapbase;
+	priv->iobase = iobase;
+	priv->pdev = pdev;
+	priv->tx_empty = 1;
+	priv->rxbuf.buf = rxbuf;
+	priv->rxbuf.size = PAGE_SIZE;
+
+	priv->fifo_size = fifosize;
+	priv->base_baud = base_baud;
+	priv->port_type = PORT_MAX_8250 + port_type + 1;
+	priv->port.dev = &pdev->dev;
+	priv->port.iobase = iobase;
+	priv->port.membase = NULL;
+	priv->port.mapbase = mapbase;
+	priv->port.irq = pdev->irq;
+	priv->port.iotype = UPIO_PORT;
+	priv->port.ops = &pch_uart_ops;
+	priv->port.flags = UPF_BOOT_AUTOCONF;
+	priv->port.fifosize = fifosize;
+	priv->port.line = num++;
+	priv->trigger = PCH_UART_HAL_TRIGGER_M;
+
+	pci_set_drvdata(pdev, priv);
+	pch_uart_hal_request(pdev, fifosize, base_baud);
+	ret = uart_add_one_port(&pch_uart_driver, &priv->port);
+	if (ret < 0)
+		goto init_port_hal_free;
+
+	return priv;
+
+init_port_hal_free:
+	free_page((unsigned long)rxbuf);
+init_port_free_txbuf:
+	kfree(priv);
+init_port_alloc_err:
+
+	return NULL;
+}
+
+static void pch_uart_exit_port(struct eg20t_port *priv)
+{
+	uart_remove_one_port(&pch_uart_driver, &priv->port);
+	pci_set_drvdata(priv->pdev, NULL);
+	free_page((unsigned long)priv->rxbuf.buf);
+}
+
+static void pch_uart_pci_remove(struct pci_dev *pdev)
+{
+	struct eg20t_port *priv;
+
+	priv = (struct eg20t_port *)pci_get_drvdata(pdev);
+	pch_uart_exit_port(priv);
+	pci_disable_device(pdev);
+	kfree(priv);
+	return;
+}
+#ifdef CONFIG_PM
+static int pch_uart_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct eg20t_port *priv = pci_get_drvdata(pdev);
+
+	uart_suspend_port(&pch_uart_driver, &priv->port);
+
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return 0;
+}
+
+static int pch_uart_pci_resume(struct pci_dev *pdev)
+{
+	struct eg20t_port *priv = pci_get_drvdata(pdev);
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s-pci_enable_device failed(ret=%d) ", __func__, ret);
+		return ret;
+	}
+
+	uart_resume_port(&pch_uart_driver, &priv->port);
+
+	return 0;
+}
+#else
+#define pch_uart_pci_suspend NULL
+#define pch_uart_pci_resume NULL
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
+	 .driver_data = PCH_UART_8LINE},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812),
+	 .driver_data = PCH_UART_2LINE},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8813),
+	 .driver_data = PCH_UART_2LINE},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8814),
+	 .driver_data = PCH_UART_2LINE},
+	{0,},
+};
+
+static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
+					const struct pci_device_id *id)
+{
+	int ret;
+	struct eg20t_port *priv;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0)
+		goto probe_error;
+
+	priv = pch_uart_init_port(pdev, id->driver_data);
+	if (!priv) {
+		ret = -EBUSY;
+		goto probe_disable_device;
+	}
+	pci_set_drvdata(pdev, priv);
+
+	return ret;
+
+probe_disable_device:
+	pci_disable_device(pdev);
+probe_error:
+	return ret;
+}
+
+static struct pci_driver pch_uart_pci_driver = {
+	.name = "pch_uart",
+	.id_table = pch_uart_pci_id,
+	.probe = pch_uart_pci_probe,
+	.remove = __devexit_p(pch_uart_pci_remove),
+	.suspend = pch_uart_pci_suspend,
+	.resume = pch_uart_pci_resume,
+};
+
+static int __init pch_uart_module_init(void)
+{
+	int ret;
+
+	/* register as UART driver */
+	ret = uart_register_driver(&pch_uart_driver);
+	if (ret < 0)
+		return ret;
+
+	/* register as PCI driver */
+	ret = pci_register_driver(&pch_uart_pci_driver);
+	if (ret < 0)
+		uart_unregister_driver(&pch_uart_driver);
+
+	return ret;
+}
+module_init(pch_uart_module_init);
+
+static void __exit pch_uart_module_exit(void)
+{
+	pci_unregister_driver(&pch_uart_pci_driver);
+	uart_unregister_driver(&pch_uart_driver);
+}
+module_exit(pch_uart_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver");
+module_param(default_baud, uint, S_IRUGO);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 9ffa5be..460a72d 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1985,7 +1985,8 @@
 
 	tty_dev = device_find_child(uport->dev, &match, serial_match_port);
 	if (device_may_wakeup(tty_dev)) {
-		enable_irq_wake(uport->irq);
+		if (!enable_irq_wake(uport->irq))
+			uport->irq_wake = 1;
 		put_device(tty_dev);
 		mutex_unlock(&port->mutex);
 		return 0;
@@ -2051,7 +2052,10 @@
 
 	tty_dev = device_find_child(uport->dev, &match, serial_match_port);
 	if (!uport->suspended && device_may_wakeup(tty_dev)) {
-		disable_irq_wake(uport->irq);
+		if (uport->irq_wake) {
+			disable_irq_wake(uport->irq);
+			uport->irq_wake = 0;
+		}
 		mutex_unlock(&port->mutex);
 		return 0;
 	}
@@ -2134,6 +2138,7 @@
 	case UPIO_AU:
 	case UPIO_TSI:
 	case UPIO_DWAPB:
+	case UPIO_DWAPB32:
 		snprintf(address, sizeof(address),
 			 "MMIO 0x%llx", (unsigned long long)port->mapbase);
 		break;
@@ -2554,6 +2559,7 @@
 	case UPIO_AU:
 	case UPIO_TSI:
 	case UPIO_DWAPB:
+	case UPIO_DWAPB32:
 		return (port1->mapbase == port2->mapbase);
 	}
 	return 0;
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index d2352ac..4bc614e 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -31,6 +31,7 @@
 # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
 #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
       defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+      defined(CONFIG_ARCH_SH73A0) || \
       defined(CONFIG_ARCH_SH7367) || \
       defined(CONFIG_ARCH_SH7377) || \
       defined(CONFIG_ARCH_SH7372)
@@ -244,6 +245,7 @@
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_ARCH_SH73A0) || \
     defined(CONFIG_ARCH_SH7367) || \
     defined(CONFIG_ARCH_SH7377) || \
     defined(CONFIG_ARCH_SH7372)
@@ -280,6 +282,7 @@
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_ARCH_SH73A0) || \
     defined(CONFIG_ARCH_SH7367) || \
     defined(CONFIG_ARCH_SH7377) || \
     defined(CONFIG_ARCH_SH7372)
@@ -378,6 +381,7 @@
   }
 
 #if defined(CONFIG_CPU_SH3) || \
+    defined(CONFIG_ARCH_SH73A0) || \
     defined(CONFIG_ARCH_SH7367) || \
     defined(CONFIG_ARCH_SH7377) || \
     defined(CONFIG_ARCH_SH7372)
@@ -391,6 +395,7 @@
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
       defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+      defined(CONFIG_ARCH_SH73A0) || \
       defined(CONFIG_ARCH_SH7367) || \
       defined(CONFIG_ARCH_SH7377)
 #define SCIF_FNS(name, scif_offset, scif_size) \
@@ -433,6 +438,7 @@
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_ARCH_SH73A0) || \
     defined(CONFIG_ARCH_SH7367) || \
     defined(CONFIG_ARCH_SH7377)
 
@@ -632,6 +638,7 @@
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
       defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+      defined(CONFIG_ARCH_SH73A0) || \
       defined(CONFIG_ARCH_SH7367) || \
       defined(CONFIG_ARCH_SH7377) || \
       defined(CONFIG_ARCH_SH7372)
diff --git a/drivers/serial/vt8500_serial.c b/drivers/serial/vt8500_serial.c
new file mode 100644
index 0000000..322bf56
--- /dev/null
+++ b/drivers/serial/vt8500_serial.c
@@ -0,0 +1,648 @@
+/*
+ * drivers/serial/vt8500_serial.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on msm_serial.c, which is:
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Robert Love <rlove@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#if defined(CONFIG_SERIAL_VT8500_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+# define SUPPORT_SYSRQ
+#endif
+
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/*
+ * UART Register offsets
+ */
+
+#define VT8500_URTDR		0x0000	/* Transmit data */
+#define VT8500_URRDR		0x0004	/* Receive data */
+#define VT8500_URDIV		0x0008	/* Clock/Baud rate divisor */
+#define VT8500_URLCR		0x000C	/* Line control */
+#define VT8500_URICR		0x0010	/* IrDA control */
+#define VT8500_URIER		0x0014	/* Interrupt enable */
+#define VT8500_URISR		0x0018	/* Interrupt status */
+#define VT8500_URUSR		0x001c	/* UART status */
+#define VT8500_URFCR		0x0020	/* FIFO control */
+#define VT8500_URFIDX		0x0024	/* FIFO index */
+#define VT8500_URBKR		0x0028	/* Break signal count */
+#define VT8500_URTOD		0x002c	/* Time out divisor */
+#define VT8500_TXFIFO		0x1000	/* Transmit FIFO (16x8) */
+#define VT8500_RXFIFO		0x1020	/* Receive FIFO (16x10) */
+
+/*
+ * Interrupt enable and status bits
+ */
+
+#define TXDE	(1 << 0)	/* Tx Data empty */
+#define RXDF	(1 << 1)	/* Rx Data full */
+#define TXFAE	(1 << 2)	/* Tx FIFO almost empty */
+#define TXFE	(1 << 3)	/* Tx FIFO empty */
+#define RXFAF	(1 << 4)	/* Rx FIFO almost full */
+#define RXFF	(1 << 5)	/* Rx FIFO full */
+#define TXUDR	(1 << 6)	/* Tx underrun */
+#define RXOVER	(1 << 7)	/* Rx overrun */
+#define PER	(1 << 8)	/* Parity error */
+#define FER	(1 << 9)	/* Frame error */
+#define TCTS	(1 << 10)	/* Toggle of CTS */
+#define RXTOUT	(1 << 11)	/* Rx timeout */
+#define BKDONE	(1 << 12)	/* Break signal done */
+#define ERR	(1 << 13)	/* AHB error response */
+
+#define RX_FIFO_INTS	(RXFAF | RXFF | RXOVER | PER | FER | RXTOUT)
+#define TX_FIFO_INTS	(TXFAE | TXFE | TXUDR)
+
+struct vt8500_port {
+	struct uart_port	uart;
+	char			name[16];
+	struct clk		*clk;
+	unsigned int		ier;
+};
+
+static inline void vt8500_write(struct uart_port *port, unsigned int val,
+			     unsigned int off)
+{
+	writel(val, port->membase + off);
+}
+
+static inline unsigned int vt8500_read(struct uart_port *port, unsigned int off)
+{
+	return readl(port->membase + off);
+}
+
+static void vt8500_stop_tx(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier &= ~TX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void vt8500_stop_rx(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier &= ~RX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void vt8500_enable_ms(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier |= TCTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void handle_rx(struct uart_port *port)
+{
+	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+	if (!tty) {
+		/* Discard data: no tty available */
+		int count = (vt8500_read(port, VT8500_URFIDX) & 0x1f00) >> 8;
+		u16 ch;
+		while (count--)
+			ch = readw(port->membase + VT8500_RXFIFO);
+		return;
+	}
+
+	/*
+	 * Handle overrun
+	 */
+	if ((vt8500_read(port, VT8500_URISR) & RXOVER)) {
+		port->icount.overrun++;
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+	}
+
+	/* and now the main RX loop */
+	while (vt8500_read(port, VT8500_URFIDX) & 0x1f00) {
+		unsigned int c;
+		char flag = TTY_NORMAL;
+
+		c = readw(port->membase + VT8500_RXFIFO) & 0x3ff;
+
+		/* Mask conditions we're ignorning. */
+		c &= ~port->read_status_mask;
+
+		if (c & FER) {
+			port->icount.frame++;
+			flag = TTY_FRAME;
+		} else if (c & PER) {
+			port->icount.parity++;
+			flag = TTY_PARITY;
+		}
+		port->icount.rx++;
+
+		if (!uart_handle_sysrq_char(port, c))
+			tty_insert_flip_char(tty, c, flag);
+	}
+
+	tty_flip_buffer_push(tty);
+	tty_kref_put(tty);
+}
+
+static void handle_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+
+	if (port->x_char) {
+		writeb(port->x_char, port->membase + VT8500_TXFIFO);
+		port->icount.tx++;
+		port->x_char = 0;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		vt8500_stop_tx(port);
+		return;
+	}
+
+	while ((vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16) {
+		if (uart_circ_empty(xmit))
+			break;
+
+		writeb(xmit->buf[xmit->tail], port->membase + VT8500_TXFIFO);
+
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		vt8500_stop_tx(port);
+}
+
+static void vt8500_start_tx(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier &= ~TX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+	handle_tx(port);
+	vt8500_port->ier |= TX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void handle_delta_cts(struct uart_port *port)
+{
+	port->icount.cts++;
+	wake_up_interruptible(&port->state->port.delta_msr_wait);
+}
+
+static irqreturn_t vt8500_irq(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	unsigned long isr;
+
+	spin_lock(&port->lock);
+	isr = vt8500_read(port, VT8500_URISR);
+
+	/* Acknowledge active status bits */
+	vt8500_write(port, isr, VT8500_URISR);
+
+	if (isr & RX_FIFO_INTS)
+		handle_rx(port);
+	if (isr & TX_FIFO_INTS)
+		handle_tx(port);
+	if (isr & TCTS)
+		handle_delta_cts(port);
+
+	spin_unlock(&port->lock);
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int vt8500_tx_empty(struct uart_port *port)
+{
+	return (vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16 ?
+						TIOCSER_TEMT : 0;
+}
+
+static unsigned int vt8500_get_mctrl(struct uart_port *port)
+{
+	unsigned int usr;
+
+	usr = vt8500_read(port, VT8500_URUSR);
+	if (usr & (1 << 4))
+		return TIOCM_CTS;
+	else
+		return 0;
+}
+
+static void vt8500_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static void vt8500_break_ctl(struct uart_port *port, int break_ctl)
+{
+	if (break_ctl)
+		vt8500_write(port, vt8500_read(port, VT8500_URLCR) | (1 << 9),
+			     VT8500_URLCR);
+}
+
+static int vt8500_set_baud_rate(struct uart_port *port, unsigned int baud)
+{
+	unsigned long div;
+	unsigned int loops = 1000;
+
+	div = vt8500_read(port, VT8500_URDIV) & ~(0x3ff);
+
+	if (unlikely((baud < 900) || (baud > 921600)))
+		div |= 7;
+	else
+		div |= (921600 / baud) - 1;
+
+	while ((vt8500_read(port, VT8500_URUSR) & (1 << 5)) && --loops)
+		cpu_relax();
+	vt8500_write(port, div, VT8500_URDIV);
+
+	return baud;
+}
+
+static int vt8500_startup(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+	int ret;
+
+	snprintf(vt8500_port->name, sizeof(vt8500_port->name),
+		 "vt8500_serial%d", port->line);
+
+	ret = request_irq(port->irq, vt8500_irq, IRQF_TRIGGER_HIGH,
+			  vt8500_port->name, port);
+	if (unlikely(ret))
+		return ret;
+
+	vt8500_write(port, 0x03, VT8500_URLCR);	/* enable TX & RX */
+
+	return 0;
+}
+
+static void vt8500_shutdown(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+
+	vt8500_port->ier = 0;
+
+	/* disable interrupts and FIFOs */
+	vt8500_write(&vt8500_port->uart, 0, VT8500_URIER);
+	vt8500_write(&vt8500_port->uart, 0x880, VT8500_URFCR);
+	free_irq(port->irq, port);
+}
+
+static void vt8500_set_termios(struct uart_port *port,
+			       struct ktermios *termios,
+			       struct ktermios *old)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+	unsigned long flags;
+	unsigned int baud, lcr;
+	unsigned int loops = 1000;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* calculate and set baud rate */
+	baud = uart_get_baud_rate(port, termios, old, 900, 921600);
+	baud = vt8500_set_baud_rate(port, baud);
+	if (tty_termios_baud_rate(termios))
+		tty_termios_encode_baud_rate(termios, baud, baud);
+
+	/* calculate parity */
+	lcr = vt8500_read(&vt8500_port->uart, VT8500_URLCR);
+	lcr &= ~((1 << 5) | (1 << 4));
+	if (termios->c_cflag & PARENB) {
+		lcr |= (1 << 4);
+		termios->c_cflag &= ~CMSPAR;
+		if (termios->c_cflag & PARODD)
+			lcr |= (1 << 5);
+	}
+
+	/* calculate bits per char */
+	lcr &= ~(1 << 2);
+	switch (termios->c_cflag & CSIZE) {
+	case CS7:
+		break;
+	case CS8:
+	default:
+		lcr |= (1 << 2);
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= CS8;
+		break;
+	}
+
+	/* calculate stop bits */
+	lcr &= ~(1 << 3);
+	if (termios->c_cflag & CSTOPB)
+		lcr |= (1 << 3);
+
+	/* set parity, bits per char, and stop bit */
+	vt8500_write(&vt8500_port->uart, lcr, VT8500_URLCR);
+
+	/* Configure status bits to ignore based on termio flags. */
+	port->read_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->read_status_mask = FER | PER;
+
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	/* Reset FIFOs */
+	vt8500_write(&vt8500_port->uart, 0x88c, VT8500_URFCR);
+	while ((vt8500_read(&vt8500_port->uart, VT8500_URFCR) & 0xc)
+							&& --loops)
+		cpu_relax();
+
+	/* Every possible FIFO-related interrupt */
+	vt8500_port->ier = RX_FIFO_INTS | TX_FIFO_INTS;
+
+	/*
+	 * CTS flow control
+	 */
+	if (UART_ENABLE_MS(&vt8500_port->uart, termios->c_cflag))
+		vt8500_port->ier |= TCTS;
+
+	vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR);
+	vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *vt8500_type(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+	return vt8500_port->name;
+}
+
+static void vt8500_release_port(struct uart_port *port)
+{
+}
+
+static int vt8500_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void vt8500_config_port(struct uart_port *port, int flags)
+{
+	port->type = PORT_VT8500;
+}
+
+static int vt8500_verify_port(struct uart_port *port,
+			      struct serial_struct *ser)
+{
+	if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_VT8500))
+		return -EINVAL;
+	if (unlikely(port->irq != ser->irq))
+		return -EINVAL;
+	return 0;
+}
+
+static struct vt8500_port *vt8500_uart_ports[4];
+static struct uart_driver vt8500_uart_driver;
+
+#ifdef CONFIG_SERIAL_VT8500_CONSOLE
+
+static inline void wait_for_xmitr(struct uart_port *port)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = vt8500_read(port, VT8500_URFIDX);
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while (status & 0x10);
+}
+
+static void vt8500_console_putchar(struct uart_port *port, int c)
+{
+	wait_for_xmitr(port);
+	writeb(c, port->membase + VT8500_TXFIFO);
+}
+
+static void vt8500_console_write(struct console *co, const char *s,
+			      unsigned int count)
+{
+	struct vt8500_port *vt8500_port = vt8500_uart_ports[co->index];
+	unsigned long ier;
+
+	BUG_ON(co->index < 0 || co->index >= vt8500_uart_driver.nr);
+
+	ier = vt8500_read(&vt8500_port->uart, VT8500_URIER);
+	vt8500_write(&vt8500_port->uart, VT8500_URIER, 0);
+
+	uart_console_write(&vt8500_port->uart, s, count,
+			   vt8500_console_putchar);
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and switch back to FIFO
+	 */
+	wait_for_xmitr(&vt8500_port->uart);
+	vt8500_write(&vt8500_port->uart, VT8500_URIER, ier);
+}
+
+static int __init vt8500_console_setup(struct console *co, char *options)
+{
+	struct vt8500_port *vt8500_port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (unlikely(co->index >= vt8500_uart_driver.nr || co->index < 0))
+		return -ENXIO;
+
+	vt8500_port = vt8500_uart_ports[co->index];
+
+	if (!vt8500_port)
+		return -ENODEV;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&vt8500_port->uart,
+				 co, baud, parity, bits, flow);
+}
+
+static struct console vt8500_console = {
+	.name = "ttyWMT",
+	.write = vt8500_console_write,
+	.device = uart_console_device,
+	.setup = vt8500_console_setup,
+	.flags = CON_PRINTBUFFER,
+	.index = -1,
+	.data = &vt8500_uart_driver,
+};
+
+#define VT8500_CONSOLE	(&vt8500_console)
+
+#else
+#define VT8500_CONSOLE	NULL
+#endif
+
+static struct uart_ops vt8500_uart_pops = {
+	.tx_empty	= vt8500_tx_empty,
+	.set_mctrl	= vt8500_set_mctrl,
+	.get_mctrl	= vt8500_get_mctrl,
+	.stop_tx	= vt8500_stop_tx,
+	.start_tx	= vt8500_start_tx,
+	.stop_rx	= vt8500_stop_rx,
+	.enable_ms	= vt8500_enable_ms,
+	.break_ctl	= vt8500_break_ctl,
+	.startup	= vt8500_startup,
+	.shutdown	= vt8500_shutdown,
+	.set_termios	= vt8500_set_termios,
+	.type		= vt8500_type,
+	.release_port	= vt8500_release_port,
+	.request_port	= vt8500_request_port,
+	.config_port	= vt8500_config_port,
+	.verify_port	= vt8500_verify_port,
+};
+
+static struct uart_driver vt8500_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "vt8500_serial",
+	.dev_name	= "ttyWMT",
+	.nr		= 6,
+	.cons		= VT8500_CONSOLE,
+};
+
+static int __init vt8500_serial_probe(struct platform_device *pdev)
+{
+	struct vt8500_port *vt8500_port;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
+	if (!vt8500_port)
+		return -ENOMEM;
+
+	vt8500_port->uart.type = PORT_VT8500;
+	vt8500_port->uart.iotype = UPIO_MEM;
+	vt8500_port->uart.mapbase = mmres->start;
+	vt8500_port->uart.irq = irqres->start;
+	vt8500_port->uart.fifosize = 16;
+	vt8500_port->uart.ops = &vt8500_uart_pops;
+	vt8500_port->uart.line = pdev->id;
+	vt8500_port->uart.dev = &pdev->dev;
+	vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
+	vt8500_port->uart.uartclk = 24000000;
+
+	snprintf(vt8500_port->name, sizeof(vt8500_port->name),
+		 "VT8500 UART%d", pdev->id);
+
+	vt8500_port->uart.membase = ioremap(mmres->start,
+					    mmres->end - mmres->start + 1);
+	if (!vt8500_port->uart.membase) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	vt8500_uart_ports[pdev->id] = vt8500_port;
+
+	uart_add_one_port(&vt8500_uart_driver, &vt8500_port->uart);
+
+	platform_set_drvdata(pdev, vt8500_port);
+
+	return 0;
+
+err:
+	kfree(vt8500_port);
+	return ret;
+}
+
+static int __devexit vt8500_serial_remove(struct platform_device *pdev)
+{
+	struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart);
+	kfree(vt8500_port);
+
+	return 0;
+}
+
+static struct platform_driver vt8500_platform_driver = {
+	.probe  = vt8500_serial_probe,
+	.remove = vt8500_serial_remove,
+	.driver = {
+		.name = "vt8500_serial",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init vt8500_serial_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&vt8500_uart_driver);
+	if (unlikely(ret))
+		return ret;
+
+	ret = platform_driver_register(&vt8500_platform_driver);
+
+	if (unlikely(ret))
+		uart_unregister_driver(&vt8500_uart_driver);
+
+	return ret;
+}
+
+static void __exit vt8500_serial_exit(void)
+{
+#ifdef CONFIG_SERIAL_VT8500_CONSOLE
+	unregister_console(&vt8500_console);
+#endif
+	platform_driver_unregister(&vt8500_platform_driver);
+	uart_unregister_driver(&vt8500_uart_driver);
+}
+
+module_init(vt8500_serial_init);
+module_exit(vt8500_serial_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("Driver for vt8500 serial device");
+MODULE_LICENSE("GPL");
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index e5e9e67..9739431 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -198,6 +198,7 @@
 	list_add_tail(&d->list, &intc_list);
 
 	raw_spin_lock_init(&d->lock);
+	INIT_RADIX_TREE(&d->tree, GFP_ATOMIC);
 
 	d->index = nr_intc_controllers;
 
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 78f9fd0..1906840 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -111,11 +111,14 @@
 	  will be called coldfire_qspi.
 
 config SPI_DAVINCI
-	tristate "SPI controller driver for DaVinci/DA8xx SoC's"
+	tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
 	depends on SPI_MASTER && ARCH_DAVINCI
 	select SPI_BITBANG
 	help
-	  SPI master controller for DaVinci and DA8xx SPI modules.
+	  SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
+
+	  This driver can also be built as a module. The module will be called
+	  davinci_spi.
 
 config SPI_EP93XX
 	tristate "Cirrus Logic EP93xx SPI controller"
@@ -267,12 +270,15 @@
 
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
-	depends on ARCH_PXA && EXPERIMENTAL
-	select PXA_SSP
+	depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
+	select PXA_SSP if ARCH_PXA
 	help
-	  This enables using a PXA2xx SSP port as a SPI master controller.
-	  The driver can be configured to use any SSP port and additional
-	  documentation can be found a Documentation/spi/pxa2xx.
+	  This enables using a PXA2xx or Sodaville SSP port as a SPI master
+	  controller. The driver can be configured to use any SSP port and
+	  additional documentation can be found a Documentation/spi/pxa2xx.
+
+config SPI_PXA2XX_PCI
+	def_bool SPI_PXA2XX && X86_32 && PCI
 
 config SPI_S3C24XX
 	tristate "Samsung S3C24XX series SPI"
@@ -353,7 +359,6 @@
 	tristate "Xilinx SPI controller common module"
 	depends on HAS_IOMEM && EXPERIMENTAL
 	select SPI_BITBANG
-	select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE)
 	help
 	  This exposes the SPI controller IP from the Xilinx EDK.
 
@@ -362,19 +367,6 @@
 
 	  Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
 
-config SPI_XILINX_OF
-	tristate "Xilinx SPI controller OF device"
-	depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE)
-	help
-	  This is the OF driver for the SPI controller IP from the Xilinx EDK.
-
-config SPI_XILINX_PLTFM
-	tristate "Xilinx SPI controller platform device"
-	depends on SPI_XILINX
-	help
-	  This is the platform driver for the SPI controller IP
-	  from the Xilinx EDK.
-
 config SPI_NUC900
 	tristate "Nuvoton NUC900 series SPI"
 	depends on ARCH_W90X900 && EXPERIMENTAL
@@ -396,6 +388,10 @@
 	tristate "PCI interface driver for DW SPI core"
 	depends on SPI_DESIGNWARE && PCI
 
+config SPI_DW_MID_DMA
+	bool "DMA support for DW SPI controller on Intel Moorestown platform"
+	depends on SPI_DW_PCI && INTEL_MID_DMAC
+
 config SPI_DW_MMIO
 	tristate "Memory-mapped io interface driver for DW SPI core"
 	depends on SPI_DESIGNWARE && HAVE_CLK
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8bc1a5a..3a42463 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,13 +17,15 @@
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)		+= coldfire_qspi.o
 obj-$(CONFIG_SPI_DAVINCI)		+= davinci_spi.o
 obj-$(CONFIG_SPI_DESIGNWARE)		+= dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_pci.o
+obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_midpci.o
+dw_spi_midpci-objs			:= dw_spi_pci.o dw_spi_mid.o
 obj-$(CONFIG_SPI_DW_MMIO)		+= dw_spi_mmio.o
 obj-$(CONFIG_SPI_EP93XX)		+= ep93xx_spi.o
 obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
+obj-$(CONFIG_SPI_PXA2XX_PCI)		+= pxa2xx_spi_pci.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
@@ -43,8 +45,6 @@
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
-obj-$(CONFIG_SPI_XILINX_OF)		+= xilinx_spi_of.o
-obj-$(CONFIG_SPI_XILINX_PLTFM)		+= xilinx_spi_pltfm.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c
index fb3d1b3..a2a5921 100644
--- a/drivers/spi/amba-pl022.c
+++ b/drivers/spi/amba-pl022.c
@@ -253,11 +253,6 @@
 #define STATE_ERROR			((void *) -1)
 
 /*
- * Queue State
- */
-#define QUEUE_RUNNING			(0)
-#define QUEUE_STOPPED			(1)
-/*
  * SSP State - Whether Enabled or Disabled
  */
 #define SSP_DISABLED			(0)
@@ -344,7 +339,7 @@
  * @lock: spinlock to syncronise access to driver data
  * @workqueue: a workqueue on which any spi_message request is queued
  * @busy: workqueue is busy
- * @run: workqueue is running
+ * @running: workqueue is running
  * @pump_transfers: Tasklet used in Interrupt Transfer mode
  * @cur_msg: Pointer to current spi_message being processed
  * @cur_transfer: Pointer to current spi_transfer
@@ -369,8 +364,8 @@
 	struct work_struct		pump_messages;
 	spinlock_t			queue_lock;
 	struct list_head		queue;
-	int				busy;
-	int				run;
+	bool				busy;
+	bool				running;
 	/* Message transfer pump */
 	struct tasklet_struct		pump_transfers;
 	struct spi_message		*cur_msg;
@@ -782,9 +777,9 @@
 static void unmap_free_dma_scatter(struct pl022 *pl022)
 {
 	/* Unmap and free the SG tables */
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+	dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl,
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+	dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl,
 		     pl022->sgt_rx.nents, DMA_FROM_DEVICE);
 	sg_free_table(&pl022->sgt_rx);
 	sg_free_table(&pl022->sgt_tx);
@@ -917,7 +912,7 @@
 	};
 	unsigned int pages;
 	int ret;
-	int sglen;
+	int rx_sglen, tx_sglen;
 	struct dma_chan *rxchan = pl022->dma_rx_channel;
 	struct dma_chan *txchan = pl022->dma_tx_channel;
 	struct dma_async_tx_descriptor *rxdesc;
@@ -956,7 +951,7 @@
 		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 		break;
 	case WRITING_U32:
-		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;;
+		tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		break;
 	}
 
@@ -991,20 +986,20 @@
 			  pl022->cur_transfer->len, &pl022->sgt_tx);
 
 	/* Map DMA buffers */
-	sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+	rx_sglen = dma_map_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
 			   pl022->sgt_rx.nents, DMA_FROM_DEVICE);
-	if (!sglen)
+	if (!rx_sglen)
 		goto err_rx_sgmap;
 
-	sglen = dma_map_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+	tx_sglen = dma_map_sg(txchan->device->dev, pl022->sgt_tx.sgl,
 			   pl022->sgt_tx.nents, DMA_TO_DEVICE);
-	if (!sglen)
+	if (!tx_sglen)
 		goto err_tx_sgmap;
 
 	/* Send both scatterlists */
 	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
 				      pl022->sgt_rx.sgl,
-				      pl022->sgt_rx.nents,
+				      rx_sglen,
 				      DMA_FROM_DEVICE,
 				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!rxdesc)
@@ -1012,7 +1007,7 @@
 
 	txdesc = txchan->device->device_prep_slave_sg(txchan,
 				      pl022->sgt_tx.sgl,
-				      pl022->sgt_tx.nents,
+				      tx_sglen,
 				      DMA_TO_DEVICE,
 				      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!txdesc)
@@ -1040,10 +1035,10 @@
 	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
 err_rxdesc:
 	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_tx.sgl,
+	dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
 err_tx_sgmap:
-	dma_unmap_sg(&pl022->adev->dev, pl022->sgt_rx.sgl,
+	dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
 		     pl022->sgt_tx.nents, DMA_FROM_DEVICE);
 err_rx_sgmap:
 	sg_free_table(&pl022->sgt_tx);
@@ -1460,8 +1455,8 @@
 
 	/* Lock queue and check for queue work */
 	spin_lock_irqsave(&pl022->queue_lock, flags);
-	if (list_empty(&pl022->queue) || pl022->run == QUEUE_STOPPED) {
-		pl022->busy = 0;
+	if (list_empty(&pl022->queue) || !pl022->running) {
+		pl022->busy = false;
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		return;
 	}
@@ -1475,7 +1470,7 @@
 	    list_entry(pl022->queue.next, struct spi_message, queue);
 
 	list_del_init(&pl022->cur_msg->queue);
-	pl022->busy = 1;
+	pl022->busy = true;
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 
 	/* Initial message state */
@@ -1507,8 +1502,8 @@
 	INIT_LIST_HEAD(&pl022->queue);
 	spin_lock_init(&pl022->queue_lock);
 
-	pl022->run = QUEUE_STOPPED;
-	pl022->busy = 0;
+	pl022->running = false;
+	pl022->busy = false;
 
 	tasklet_init(&pl022->pump_transfers,
 			pump_transfers,	(unsigned long)pl022);
@@ -1529,12 +1524,12 @@
 
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 
-	if (pl022->run == QUEUE_RUNNING || pl022->busy) {
+	if (pl022->running || pl022->busy) {
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		return -EBUSY;
 	}
 
-	pl022->run = QUEUE_RUNNING;
+	pl022->running = true;
 	pl022->cur_msg = NULL;
 	pl022->cur_transfer = NULL;
 	pl022->cur_chip = NULL;
@@ -1566,7 +1561,8 @@
 
 	if (!list_empty(&pl022->queue) || pl022->busy)
 		status = -EBUSY;
-	else pl022->run = QUEUE_STOPPED;
+	else
+		pl022->running = false;
 
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
 
@@ -1684,7 +1680,7 @@
 
 	spin_lock_irqsave(&pl022->queue_lock, flags);
 
-	if (pl022->run == QUEUE_STOPPED) {
+	if (!pl022->running) {
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		return -ESHUTDOWN;
 	}
@@ -1693,7 +1689,7 @@
 	msg->state = STATE_START;
 
 	list_add_tail(&msg->queue, &pl022->queue);
-	if (pl022->run == QUEUE_RUNNING && !pl022->busy)
+	if (pl022->running && !pl022->busy)
 		queue_work(pl022->workqueue, &pl022->pump_messages);
 
 	spin_unlock_irqrestore(&pl022->queue_lock, flags);
diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/coldfire_qspi.c
index 052b3c7..8856bcc 100644
--- a/drivers/spi/coldfire_qspi.c
+++ b/drivers/spi/coldfire_qspi.c
@@ -317,7 +317,7 @@
 		msg = container_of(mcfqspi->msgq.next, struct spi_message,
 				   queue);
 
-		list_del_init(&mcfqspi->msgq);
+		list_del_init(&msg->queue);
 		spin_unlock_irqrestore(&mcfqspi->lock, flags);
 
 		spi = msg->spi;
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index b85090c..6beab99 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2010 EF Johnson Technologies
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -38,11 +39,6 @@
 
 #define CS_DEFAULT	0xFF
 
-#define SPI_BUFSIZ	(SMP_CACHE_BYTES + 1)
-#define DAVINCI_DMA_DATA_TYPE_S8	0x01
-#define DAVINCI_DMA_DATA_TYPE_S16	0x02
-#define DAVINCI_DMA_DATA_TYPE_S32	0x04
-
 #define SPIFMT_PHASE_MASK	BIT(16)
 #define SPIFMT_POLARITY_MASK	BIT(17)
 #define SPIFMT_DISTIMER_MASK	BIT(18)
@@ -52,34 +48,43 @@
 #define SPIFMT_ODD_PARITY_MASK	BIT(23)
 #define SPIFMT_WDELAY_MASK	0x3f000000u
 #define SPIFMT_WDELAY_SHIFT	24
-#define SPIFMT_CHARLEN_MASK	0x0000001Fu
-
-/* SPIGCR1 */
-#define SPIGCR1_SPIENA_MASK	0x01000000u
+#define SPIFMT_PRESCALE_SHIFT	8
 
 /* SPIPC0 */
 #define SPIPC0_DIFUN_MASK	BIT(11)		/* MISO */
 #define SPIPC0_DOFUN_MASK	BIT(10)		/* MOSI */
 #define SPIPC0_CLKFUN_MASK	BIT(9)		/* CLK */
 #define SPIPC0_SPIENA_MASK	BIT(8)		/* nREADY */
-#define SPIPC0_EN1FUN_MASK	BIT(1)
-#define SPIPC0_EN0FUN_MASK	BIT(0)
 
 #define SPIINT_MASKALL		0x0101035F
-#define SPI_INTLVL_1		0x000001FFu
-#define SPI_INTLVL_0		0x00000000u
+#define SPIINT_MASKINT		0x0000015F
+#define SPI_INTLVL_1		0x000001FF
+#define SPI_INTLVL_0		0x00000000
 
-/* SPIDAT1 */
-#define SPIDAT1_CSHOLD_SHIFT	28
-#define SPIDAT1_CSNR_SHIFT	16
+/* SPIDAT1 (upper 16 bit defines) */
+#define SPIDAT1_CSHOLD_MASK	BIT(12)
+
+/* SPIGCR1 */
 #define SPIGCR1_CLKMOD_MASK	BIT(1)
 #define SPIGCR1_MASTER_MASK     BIT(0)
+#define SPIGCR1_POWERDOWN_MASK	BIT(8)
 #define SPIGCR1_LOOPBACK_MASK	BIT(16)
+#define SPIGCR1_SPIENA_MASK	BIT(24)
 
 /* SPIBUF */
 #define SPIBUF_TXFULL_MASK	BIT(29)
 #define SPIBUF_RXEMPTY_MASK	BIT(31)
 
+/* SPIDELAY */
+#define SPIDELAY_C2TDELAY_SHIFT 24
+#define SPIDELAY_C2TDELAY_MASK  (0xFF << SPIDELAY_C2TDELAY_SHIFT)
+#define SPIDELAY_T2CDELAY_SHIFT 16
+#define SPIDELAY_T2CDELAY_MASK  (0xFF << SPIDELAY_T2CDELAY_SHIFT)
+#define SPIDELAY_T2EDELAY_SHIFT 8
+#define SPIDELAY_T2EDELAY_MASK  (0xFF << SPIDELAY_T2EDELAY_SHIFT)
+#define SPIDELAY_C2EDELAY_SHIFT 0
+#define SPIDELAY_C2EDELAY_MASK  0xFF
+
 /* Error Masks */
 #define SPIFLG_DLEN_ERR_MASK		BIT(0)
 #define SPIFLG_TIMEOUT_MASK		BIT(1)
@@ -87,29 +92,13 @@
 #define SPIFLG_DESYNC_MASK		BIT(3)
 #define SPIFLG_BITERR_MASK		BIT(4)
 #define SPIFLG_OVRRUN_MASK		BIT(6)
-#define SPIFLG_RX_INTR_MASK		BIT(8)
-#define SPIFLG_TX_INTR_MASK		BIT(9)
 #define SPIFLG_BUF_INIT_ACTIVE_MASK	BIT(24)
-#define SPIFLG_MASK			(SPIFLG_DLEN_ERR_MASK \
+#define SPIFLG_ERROR_MASK		(SPIFLG_DLEN_ERR_MASK \
 				| SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \
 				| SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \
-				| SPIFLG_OVRRUN_MASK | SPIFLG_RX_INTR_MASK \
-				| SPIFLG_TX_INTR_MASK \
-				| SPIFLG_BUF_INIT_ACTIVE_MASK)
+				| SPIFLG_OVRRUN_MASK)
 
-#define SPIINT_DLEN_ERR_INTR	BIT(0)
-#define SPIINT_TIMEOUT_INTR	BIT(1)
-#define SPIINT_PARERR_INTR	BIT(2)
-#define SPIINT_DESYNC_INTR	BIT(3)
-#define SPIINT_BITERR_INTR	BIT(4)
-#define SPIINT_OVRRUN_INTR	BIT(6)
-#define SPIINT_RX_INTR		BIT(8)
-#define SPIINT_TX_INTR		BIT(9)
 #define SPIINT_DMA_REQ_EN	BIT(16)
-#define SPIINT_ENABLE_HIGHZ	BIT(24)
-
-#define SPI_T2CDELAY_SHIFT	16
-#define SPI_C2TDELAY_SHIFT	24
 
 /* SPI Controller registers */
 #define SPIGCR0		0x00
@@ -118,44 +107,18 @@
 #define SPILVL		0x0c
 #define SPIFLG		0x10
 #define SPIPC0		0x14
-#define SPIPC1		0x18
-#define SPIPC2		0x1c
-#define SPIPC3		0x20
-#define SPIPC4		0x24
-#define SPIPC5		0x28
-#define SPIPC6		0x2c
-#define SPIPC7		0x30
-#define SPIPC8		0x34
-#define SPIDAT0		0x38
 #define SPIDAT1		0x3c
 #define SPIBUF		0x40
-#define SPIEMU		0x44
 #define SPIDELAY	0x48
 #define SPIDEF		0x4c
 #define SPIFMT0		0x50
-#define SPIFMT1		0x54
-#define SPIFMT2		0x58
-#define SPIFMT3		0x5c
-#define TGINTVEC0	0x60
-#define TGINTVEC1	0x64
-
-struct davinci_spi_slave {
-	u32	cmd_to_write;
-	u32	clk_ctrl_to_write;
-	u32	bytes_per_word;
-	u8	active_cs;
-};
 
 /* We have 2 DMA channels per CS, one for RX and one for TX */
 struct davinci_spi_dma {
-	int			dma_tx_channel;
-	int			dma_rx_channel;
-	int			dma_tx_sync_dev;
-	int			dma_rx_sync_dev;
+	int			tx_channel;
+	int			rx_channel;
+	int			dummy_param_slot;
 	enum dma_event_q	eventq;
-
-	struct completion	dma_tx_completion;
-	struct completion	dma_rx_completion;
 };
 
 /* SPI Controller driver's private data. */
@@ -166,58 +129,63 @@
 	u8			version;
 	resource_size_t		pbase;
 	void __iomem		*base;
-	size_t			region_size;
 	u32			irq;
 	struct completion	done;
 
 	const void		*tx;
 	void			*rx;
-	u8			*tmp_buf;
-	int			count;
-	struct davinci_spi_dma	*dma_channels;
-	struct			davinci_spi_platform_data *pdata;
+#define SPI_TMP_BUFSZ	(SMP_CACHE_BYTES + 1)
+	u8			rx_tmp_buf[SPI_TMP_BUFSZ];
+	int			rcount;
+	int			wcount;
+	struct davinci_spi_dma	dma;
+	struct davinci_spi_platform_data *pdata;
 
 	void			(*get_rx)(u32 rx_data, struct davinci_spi *);
 	u32			(*get_tx)(struct davinci_spi *);
 
-	struct davinci_spi_slave slave[SPI_MAX_CHIPSELECT];
+	u8			bytes_per_word[SPI_MAX_CHIPSELECT];
 };
 
-static unsigned use_dma;
+static struct davinci_spi_config davinci_spi_default_cfg;
 
-static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *davinci_spi)
+static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *dspi)
 {
-	u8 *rx = davinci_spi->rx;
-
-	*rx++ = (u8)data;
-	davinci_spi->rx = rx;
+	if (dspi->rx) {
+		u8 *rx = dspi->rx;
+		*rx++ = (u8)data;
+		dspi->rx = rx;
+	}
 }
 
-static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *davinci_spi)
+static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *dspi)
 {
-	u16 *rx = davinci_spi->rx;
-
-	*rx++ = (u16)data;
-	davinci_spi->rx = rx;
+	if (dspi->rx) {
+		u16 *rx = dspi->rx;
+		*rx++ = (u16)data;
+		dspi->rx = rx;
+	}
 }
 
-static u32 davinci_spi_tx_buf_u8(struct davinci_spi *davinci_spi)
+static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi)
 {
-	u32 data;
-	const u8 *tx = davinci_spi->tx;
-
-	data = *tx++;
-	davinci_spi->tx = tx;
+	u32 data = 0;
+	if (dspi->tx) {
+		const u8 *tx = dspi->tx;
+		data = *tx++;
+		dspi->tx = tx;
+	}
 	return data;
 }
 
-static u32 davinci_spi_tx_buf_u16(struct davinci_spi *davinci_spi)
+static u32 davinci_spi_tx_buf_u16(struct davinci_spi *dspi)
 {
-	u32 data;
-	const u16 *tx = davinci_spi->tx;
-
-	data = *tx++;
-	davinci_spi->tx = tx;
+	u32 data = 0;
+	if (dspi->tx) {
+		const u16 *tx = dspi->tx;
+		data = *tx++;
+		dspi->tx = tx;
+	}
 	return data;
 }
 
@@ -237,55 +205,67 @@
 	iowrite32(v, addr);
 }
 
-static inline void set_fmt_bits(void __iomem *addr, u32 bits, int cs_num)
-{
-	set_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits);
-}
-
-static inline void clear_fmt_bits(void __iomem *addr, u32 bits, int cs_num)
-{
-	clear_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits);
-}
-
-static void davinci_spi_set_dma_req(const struct spi_device *spi, int enable)
-{
-	struct davinci_spi *davinci_spi = spi_master_get_devdata(spi->master);
-
-	if (enable)
-		set_io_bits(davinci_spi->base + SPIINT, SPIINT_DMA_REQ_EN);
-	else
-		clear_io_bits(davinci_spi->base + SPIINT, SPIINT_DMA_REQ_EN);
-}
-
 /*
  * Interface to control the chip select signal
  */
 static void davinci_spi_chipselect(struct spi_device *spi, int value)
 {
-	struct davinci_spi *davinci_spi;
+	struct davinci_spi *dspi;
 	struct davinci_spi_platform_data *pdata;
-	u32 data1_reg_val = 0;
+	u8 chip_sel = spi->chip_select;
+	u16 spidat1 = CS_DEFAULT;
+	bool gpio_chipsel = false;
 
-	davinci_spi = spi_master_get_devdata(spi->master);
-	pdata = davinci_spi->pdata;
+	dspi = spi_master_get_devdata(spi->master);
+	pdata = dspi->pdata;
+
+	if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
+				pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
+		gpio_chipsel = true;
 
 	/*
 	 * Board specific chip select logic decides the polarity and cs
 	 * line for the controller
 	 */
-	if (value == BITBANG_CS_INACTIVE) {
-		set_io_bits(davinci_spi->base + SPIDEF, CS_DEFAULT);
+	if (gpio_chipsel) {
+		if (value == BITBANG_CS_ACTIVE)
+			gpio_set_value(pdata->chip_sel[chip_sel], 0);
+		else
+			gpio_set_value(pdata->chip_sel[chip_sel], 1);
+	} else {
+		if (value == BITBANG_CS_ACTIVE) {
+			spidat1 |= SPIDAT1_CSHOLD_MASK;
+			spidat1 &= ~(0x1 << chip_sel);
+		}
 
-		data1_reg_val |= CS_DEFAULT << SPIDAT1_CSNR_SHIFT;
-		iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
-
-		while ((ioread32(davinci_spi->base + SPIBUF)
-					& SPIBUF_RXEMPTY_MASK) == 0)
-			cpu_relax();
+		iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
 	}
 }
 
 /**
+ * davinci_spi_get_prescale - Calculates the correct prescale value
+ * @maxspeed_hz: the maximum rate the SPI clock can run at
+ *
+ * This function calculates the prescale value that generates a clock rate
+ * less than or equal to the specified maximum.
+ *
+ * Returns: calculated prescale - 1 for easy programming into SPI registers
+ * or negative error number if valid prescalar cannot be updated.
+ */
+static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
+							u32 max_speed_hz)
+{
+	int ret;
+
+	ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
+
+	if (ret < 3 || ret > 256)
+		return -EINVAL;
+
+	return ret - 1;
+}
+
+/**
  * davinci_spi_setup_transfer - This functions will determine transfer method
  * @spi: spi device on which data transfer to be done
  * @t: spi transfer in which transfer info is filled
@@ -298,13 +278,15 @@
 		struct spi_transfer *t)
 {
 
-	struct davinci_spi *davinci_spi;
-	struct davinci_spi_platform_data *pdata;
+	struct davinci_spi *dspi;
+	struct davinci_spi_config *spicfg;
 	u8 bits_per_word = 0;
-	u32 hz = 0, prescale = 0, clkspeed;
+	u32 hz = 0, spifmt = 0, prescale = 0;
 
-	davinci_spi = spi_master_get_devdata(spi->master);
-	pdata = davinci_spi->pdata;
+	dspi = spi_master_get_devdata(spi->master);
+	spicfg = (struct davinci_spi_config *)spi->controller_data;
+	if (!spicfg)
+		spicfg = &davinci_spi_default_cfg;
 
 	if (t) {
 		bits_per_word = t->bits_per_word;
@@ -320,186 +302,35 @@
 	 * 8bit, 16bit or 32bit transfer
 	 */
 	if (bits_per_word <= 8 && bits_per_word >= 2) {
-		davinci_spi->get_rx = davinci_spi_rx_buf_u8;
-		davinci_spi->get_tx = davinci_spi_tx_buf_u8;
-		davinci_spi->slave[spi->chip_select].bytes_per_word = 1;
+		dspi->get_rx = davinci_spi_rx_buf_u8;
+		dspi->get_tx = davinci_spi_tx_buf_u8;
+		dspi->bytes_per_word[spi->chip_select] = 1;
 	} else if (bits_per_word <= 16 && bits_per_word >= 2) {
-		davinci_spi->get_rx = davinci_spi_rx_buf_u16;
-		davinci_spi->get_tx = davinci_spi_tx_buf_u16;
-		davinci_spi->slave[spi->chip_select].bytes_per_word = 2;
+		dspi->get_rx = davinci_spi_rx_buf_u16;
+		dspi->get_tx = davinci_spi_tx_buf_u16;
+		dspi->bytes_per_word[spi->chip_select] = 2;
 	} else
 		return -EINVAL;
 
 	if (!hz)
 		hz = spi->max_speed_hz;
 
-	clear_fmt_bits(davinci_spi->base, SPIFMT_CHARLEN_MASK,
-			spi->chip_select);
-	set_fmt_bits(davinci_spi->base, bits_per_word & 0x1f,
-			spi->chip_select);
+	/* Set up SPIFMTn register, unique to this chipselect. */
 
-	clkspeed = clk_get_rate(davinci_spi->clk);
-	if (hz > clkspeed / 2)
-		prescale = 1 << 8;
-	if (hz < clkspeed / 256)
-		prescale = 255 << 8;
-	if (!prescale)
-		prescale = ((clkspeed / hz - 1) << 8) & 0x0000ff00;
+	prescale = davinci_spi_get_prescale(dspi, hz);
+	if (prescale < 0)
+		return prescale;
 
-	clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->chip_select);
-	set_fmt_bits(davinci_spi->base, prescale, spi->chip_select);
+	spifmt = (prescale << SPIFMT_PRESCALE_SHIFT) | (bits_per_word & 0x1f);
 
-	return 0;
-}
-
-static void davinci_spi_dma_rx_callback(unsigned lch, u16 ch_status, void *data)
-{
-	struct spi_device *spi = (struct spi_device *)data;
-	struct davinci_spi *davinci_spi;
-	struct davinci_spi_dma *davinci_spi_dma;
-	struct davinci_spi_platform_data *pdata;
-
-	davinci_spi = spi_master_get_devdata(spi->master);
-	davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]);
-	pdata = davinci_spi->pdata;
-
-	if (ch_status == DMA_COMPLETE)
-		edma_stop(davinci_spi_dma->dma_rx_channel);
-	else
-		edma_clean_channel(davinci_spi_dma->dma_rx_channel);
-
-	complete(&davinci_spi_dma->dma_rx_completion);
-	/* We must disable the DMA RX request */
-	davinci_spi_set_dma_req(spi, 0);
-}
-
-static void davinci_spi_dma_tx_callback(unsigned lch, u16 ch_status, void *data)
-{
-	struct spi_device *spi = (struct spi_device *)data;
-	struct davinci_spi *davinci_spi;
-	struct davinci_spi_dma *davinci_spi_dma;
-	struct davinci_spi_platform_data *pdata;
-
-	davinci_spi = spi_master_get_devdata(spi->master);
-	davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]);
-	pdata = davinci_spi->pdata;
-
-	if (ch_status == DMA_COMPLETE)
-		edma_stop(davinci_spi_dma->dma_tx_channel);
-	else
-		edma_clean_channel(davinci_spi_dma->dma_tx_channel);
-
-	complete(&davinci_spi_dma->dma_tx_completion);
-	/* We must disable the DMA TX request */
-	davinci_spi_set_dma_req(spi, 0);
-}
-
-static int davinci_spi_request_dma(struct spi_device *spi)
-{
-	struct davinci_spi *davinci_spi;
-	struct davinci_spi_dma *davinci_spi_dma;
-	struct davinci_spi_platform_data *pdata;
-	struct device *sdev;
-	int r;
-
-	davinci_spi = spi_master_get_devdata(spi->master);
-	davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
-	pdata = davinci_spi->pdata;
-	sdev = davinci_spi->bitbang.master->dev.parent;
-
-	r = edma_alloc_channel(davinci_spi_dma->dma_rx_sync_dev,
-				davinci_spi_dma_rx_callback, spi,
-				davinci_spi_dma->eventq);
-	if (r < 0) {
-		dev_dbg(sdev, "Unable to request DMA channel for SPI RX\n");
-		return -EAGAIN;
-	}
-	davinci_spi_dma->dma_rx_channel = r;
-	r = edma_alloc_channel(davinci_spi_dma->dma_tx_sync_dev,
-				davinci_spi_dma_tx_callback, spi,
-				davinci_spi_dma->eventq);
-	if (r < 0) {
-		edma_free_channel(davinci_spi_dma->dma_rx_channel);
-		davinci_spi_dma->dma_rx_channel = -1;
-		dev_dbg(sdev, "Unable to request DMA channel for SPI TX\n");
-		return -EAGAIN;
-	}
-	davinci_spi_dma->dma_tx_channel = r;
-
-	return 0;
-}
-
-/**
- * davinci_spi_setup - This functions will set default transfer method
- * @spi: spi device on which data transfer to be done
- *
- * This functions sets the default transfer method.
- */
-
-static int davinci_spi_setup(struct spi_device *spi)
-{
-	int retval;
-	struct davinci_spi *davinci_spi;
-	struct davinci_spi_dma *davinci_spi_dma;
-	struct device *sdev;
-
-	davinci_spi = spi_master_get_devdata(spi->master);
-	sdev = davinci_spi->bitbang.master->dev.parent;
-
-	/* if bits per word length is zero then set it default 8 */
-	if (!spi->bits_per_word)
-		spi->bits_per_word = 8;
-
-	davinci_spi->slave[spi->chip_select].cmd_to_write = 0;
-
-	if (use_dma && davinci_spi->dma_channels) {
-		davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
-
-		if ((davinci_spi_dma->dma_rx_channel == -1)
-				|| (davinci_spi_dma->dma_tx_channel == -1)) {
-			retval = davinci_spi_request_dma(spi);
-			if (retval < 0)
-				return retval;
-		}
-	}
-
-	/*
-	 * SPI in DaVinci and DA8xx operate between
-	 * 600 KHz and 50 MHz
-	 */
-	if (spi->max_speed_hz < 600000 || spi->max_speed_hz > 50000000) {
-		dev_dbg(sdev, "Operating frequency is not in acceptable "
-				"range\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * Set up SPIFMTn register, unique to this chipselect.
-	 *
-	 * NOTE: we could do all of these with one write.  Also, some
-	 * of the "version 2" features are found in chips that don't
-	 * support all of them...
-	 */
 	if (spi->mode & SPI_LSB_FIRST)
-		set_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
-				spi->chip_select);
-	else
-		clear_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
-				spi->chip_select);
+		spifmt |= SPIFMT_SHIFTDIR_MASK;
 
 	if (spi->mode & SPI_CPOL)
-		set_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
-				spi->chip_select);
-	else
-		clear_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
-				spi->chip_select);
+		spifmt |= SPIFMT_POLARITY_MASK;
 
 	if (!(spi->mode & SPI_CPHA))
-		set_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
-				spi->chip_select);
-	else
-		clear_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
-				spi->chip_select);
+		spifmt |= SPIFMT_PHASE_MASK;
 
 	/*
 	 * Version 1 hardware supports two basic SPI modes:
@@ -514,111 +345,84 @@
 	 *  - 4 pin with enable is (SPI_READY | SPI_NO_CS)
 	 */
 
-	if (davinci_spi->version == SPI_VERSION_2) {
-		clear_fmt_bits(davinci_spi->base, SPIFMT_WDELAY_MASK,
-				spi->chip_select);
-		set_fmt_bits(davinci_spi->base,
-				(davinci_spi->pdata->wdelay
-						<< SPIFMT_WDELAY_SHIFT)
-					& SPIFMT_WDELAY_MASK,
-				spi->chip_select);
+	if (dspi->version == SPI_VERSION_2) {
 
-		if (davinci_spi->pdata->odd_parity)
-			set_fmt_bits(davinci_spi->base,
-					SPIFMT_ODD_PARITY_MASK,
-					spi->chip_select);
-		else
-			clear_fmt_bits(davinci_spi->base,
-					SPIFMT_ODD_PARITY_MASK,
-					spi->chip_select);
+		u32 delay = 0;
 
-		if (davinci_spi->pdata->parity_enable)
-			set_fmt_bits(davinci_spi->base,
-					SPIFMT_PARITYENA_MASK,
-					spi->chip_select);
-		else
-			clear_fmt_bits(davinci_spi->base,
-					SPIFMT_PARITYENA_MASK,
-					spi->chip_select);
+		spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
+							& SPIFMT_WDELAY_MASK);
 
-		if (davinci_spi->pdata->wait_enable)
-			set_fmt_bits(davinci_spi->base,
-					SPIFMT_WAITENA_MASK,
-					spi->chip_select);
-		else
-			clear_fmt_bits(davinci_spi->base,
-					SPIFMT_WAITENA_MASK,
-					spi->chip_select);
+		if (spicfg->odd_parity)
+			spifmt |= SPIFMT_ODD_PARITY_MASK;
 
-		if (davinci_spi->pdata->timer_disable)
-			set_fmt_bits(davinci_spi->base,
-					SPIFMT_DISTIMER_MASK,
-					spi->chip_select);
-		else
-			clear_fmt_bits(davinci_spi->base,
-					SPIFMT_DISTIMER_MASK,
-					spi->chip_select);
-	}
+		if (spicfg->parity_enable)
+			spifmt |= SPIFMT_PARITYENA_MASK;
 
-	retval = davinci_spi_setup_transfer(spi, NULL);
-
-	return retval;
-}
-
-static void davinci_spi_cleanup(struct spi_device *spi)
-{
-	struct davinci_spi *davinci_spi = spi_master_get_devdata(spi->master);
-	struct davinci_spi_dma *davinci_spi_dma;
-
-	davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
-
-	if (use_dma && davinci_spi->dma_channels) {
-		davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
-
-		if ((davinci_spi_dma->dma_rx_channel != -1)
-				&& (davinci_spi_dma->dma_tx_channel != -1)) {
-			edma_free_channel(davinci_spi_dma->dma_tx_channel);
-			edma_free_channel(davinci_spi_dma->dma_rx_channel);
+		if (spicfg->timer_disable) {
+			spifmt |= SPIFMT_DISTIMER_MASK;
+		} else {
+			delay |= (spicfg->c2tdelay << SPIDELAY_C2TDELAY_SHIFT)
+						& SPIDELAY_C2TDELAY_MASK;
+			delay |= (spicfg->t2cdelay << SPIDELAY_T2CDELAY_SHIFT)
+						& SPIDELAY_T2CDELAY_MASK;
 		}
+
+		if (spi->mode & SPI_READY) {
+			spifmt |= SPIFMT_WAITENA_MASK;
+			delay |= (spicfg->t2edelay << SPIDELAY_T2EDELAY_SHIFT)
+						& SPIDELAY_T2EDELAY_MASK;
+			delay |= (spicfg->c2edelay << SPIDELAY_C2EDELAY_SHIFT)
+						& SPIDELAY_C2EDELAY_MASK;
+		}
+
+		iowrite32(delay, dspi->base + SPIDELAY);
 	}
-}
 
-static int davinci_spi_bufs_prep(struct spi_device *spi,
-				 struct davinci_spi *davinci_spi)
-{
-	int op_mode = 0;
-
-	/*
-	 * REVISIT  unless devices disagree about SPI_LOOP or
-	 * SPI_READY (SPI_NO_CS only allows one device!), this
-	 * should not need to be done before each message...
-	 * optimize for both flags staying cleared.
-	 */
-
-	op_mode = SPIPC0_DIFUN_MASK
-		| SPIPC0_DOFUN_MASK
-		| SPIPC0_CLKFUN_MASK;
-	if (!(spi->mode & SPI_NO_CS))
-		op_mode |= 1 << spi->chip_select;
-	if (spi->mode & SPI_READY)
-		op_mode |= SPIPC0_SPIENA_MASK;
-
-	iowrite32(op_mode, davinci_spi->base + SPIPC0);
-
-	if (spi->mode & SPI_LOOP)
-		set_io_bits(davinci_spi->base + SPIGCR1,
-				SPIGCR1_LOOPBACK_MASK);
-	else
-		clear_io_bits(davinci_spi->base + SPIGCR1,
-				SPIGCR1_LOOPBACK_MASK);
+	iowrite32(spifmt, dspi->base + SPIFMT0);
 
 	return 0;
 }
 
-static int davinci_spi_check_error(struct davinci_spi *davinci_spi,
-				   int int_status)
+/**
+ * davinci_spi_setup - This functions will set default transfer method
+ * @spi: spi device on which data transfer to be done
+ *
+ * This functions sets the default transfer method.
+ */
+static int davinci_spi_setup(struct spi_device *spi)
 {
-	struct device *sdev = davinci_spi->bitbang.master->dev.parent;
+	int retval = 0;
+	struct davinci_spi *dspi;
+	struct davinci_spi_platform_data *pdata;
+
+	dspi = spi_master_get_devdata(spi->master);
+	pdata = dspi->pdata;
+
+	/* if bits per word length is zero then set it default 8 */
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	if (!(spi->mode & SPI_NO_CS)) {
+		if ((pdata->chip_sel == NULL) ||
+		    (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
+			set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
+
+	}
+
+	if (spi->mode & SPI_READY)
+		set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
+
+	if (spi->mode & SPI_LOOP)
+		set_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
+	else
+		clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
+
+	return retval;
+}
+
+static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
+{
+	struct device *sdev = dspi->bitbang.master->dev.parent;
 
 	if (int_status & SPIFLG_TIMEOUT_MASK) {
 		dev_dbg(sdev, "SPI Time-out Error\n");
@@ -633,7 +437,7 @@
 		return -EIO;
 	}
 
-	if (davinci_spi->version == SPI_VERSION_2) {
+	if (dspi->version == SPI_VERSION_2) {
 		if (int_status & SPIFLG_DLEN_ERR_MASK) {
 			dev_dbg(sdev, "SPI Data Length Error\n");
 			return -EIO;
@@ -646,10 +450,6 @@
 			dev_dbg(sdev, "SPI Data Overrun error\n");
 			return -EIO;
 		}
-		if (int_status & SPIFLG_TX_INTR_MASK) {
-			dev_dbg(sdev, "SPI TX intr bit set\n");
-			return -EIO;
-		}
 		if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) {
 			dev_dbg(sdev, "SPI Buffer Init Active\n");
 			return -EBUSY;
@@ -660,6 +460,61 @@
 }
 
 /**
+ * davinci_spi_process_events - check for and handle any SPI controller events
+ * @dspi: the controller data
+ *
+ * This function will check the SPIFLG register and handle any events that are
+ * detected there
+ */
+static int davinci_spi_process_events(struct davinci_spi *dspi)
+{
+	u32 buf, status, errors = 0, spidat1;
+
+	buf = ioread32(dspi->base + SPIBUF);
+
+	if (dspi->rcount > 0 && !(buf & SPIBUF_RXEMPTY_MASK)) {
+		dspi->get_rx(buf & 0xFFFF, dspi);
+		dspi->rcount--;
+	}
+
+	status = ioread32(dspi->base + SPIFLG);
+
+	if (unlikely(status & SPIFLG_ERROR_MASK)) {
+		errors = status & SPIFLG_ERROR_MASK;
+		goto out;
+	}
+
+	if (dspi->wcount > 0 && !(buf & SPIBUF_TXFULL_MASK)) {
+		spidat1 = ioread32(dspi->base + SPIDAT1);
+		dspi->wcount--;
+		spidat1 &= ~0xFFFF;
+		spidat1 |= 0xFFFF & dspi->get_tx(dspi);
+		iowrite32(spidat1, dspi->base + SPIDAT1);
+	}
+
+out:
+	return errors;
+}
+
+static void davinci_spi_dma_callback(unsigned lch, u16 status, void *data)
+{
+	struct davinci_spi *dspi = data;
+	struct davinci_spi_dma *dma = &dspi->dma;
+
+	edma_stop(lch);
+
+	if (status == DMA_COMPLETE) {
+		if (lch == dma->rx_channel)
+			dspi->rcount = 0;
+		if (lch == dma->tx_channel)
+			dspi->wcount = 0;
+	}
+
+	if ((!dspi->wcount && !dspi->rcount) || (status != DMA_COMPLETE))
+		complete(&dspi->done);
+}
+
+/**
  * davinci_spi_bufs - functions which will handle transfer data
  * @spi: spi device on which data transfer to be done
  * @t: spi transfer in which transfer info is filled
@@ -668,358 +523,276 @@
  * of SPI controller and then wait until the completion will be marked
  * by the IRQ Handler.
  */
-static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t)
+static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 {
-	struct davinci_spi *davinci_spi;
-	int int_status, count, ret;
-	u8 conv, tmp;
-	u32 tx_data, data1_reg_val;
-	u32 buf_val, flg_val;
+	struct davinci_spi *dspi;
+	int data_type, ret;
+	u32 tx_data, spidat1;
+	u32 errors = 0;
+	struct davinci_spi_config *spicfg;
 	struct davinci_spi_platform_data *pdata;
-
-	davinci_spi = spi_master_get_devdata(spi->master);
-	pdata = davinci_spi->pdata;
-
-	davinci_spi->tx = t->tx_buf;
-	davinci_spi->rx = t->rx_buf;
-
-	/* convert len to words based on bits_per_word */
-	conv = davinci_spi->slave[spi->chip_select].bytes_per_word;
-	davinci_spi->count = t->len / conv;
-
-	INIT_COMPLETION(davinci_spi->done);
-
-	ret = davinci_spi_bufs_prep(spi, davinci_spi);
-	if (ret)
-		return ret;
-
-	/* Enable SPI */
-	set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
-
-	iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) |
-			(pdata->t2cdelay << SPI_T2CDELAY_SHIFT),
-			davinci_spi->base + SPIDELAY);
-
-	count = davinci_spi->count;
-	data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT;
-	tmp = ~(0x1 << spi->chip_select);
-
-	clear_io_bits(davinci_spi->base + SPIDEF, ~tmp);
-
-	data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT;
-
-	while ((ioread32(davinci_spi->base + SPIBUF)
-				& SPIBUF_RXEMPTY_MASK) == 0)
-		cpu_relax();
-
-	/* Determine the command to execute READ or WRITE */
-	if (t->tx_buf) {
-		clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL);
-
-		while (1) {
-			tx_data = davinci_spi->get_tx(davinci_spi);
-
-			data1_reg_val &= ~(0xFFFF);
-			data1_reg_val |= (0xFFFF & tx_data);
-
-			buf_val = ioread32(davinci_spi->base + SPIBUF);
-			if ((buf_val & SPIBUF_TXFULL_MASK) == 0) {
-				iowrite32(data1_reg_val,
-						davinci_spi->base + SPIDAT1);
-
-				count--;
-			}
-			while (ioread32(davinci_spi->base + SPIBUF)
-					& SPIBUF_RXEMPTY_MASK)
-				cpu_relax();
-
-			/* getting the returned byte */
-			if (t->rx_buf) {
-				buf_val = ioread32(davinci_spi->base + SPIBUF);
-				davinci_spi->get_rx(buf_val, davinci_spi);
-			}
-			if (count <= 0)
-				break;
-		}
-	} else {
-		if (pdata->poll_mode) {
-			while (1) {
-				/* keeps the serial clock going */
-				if ((ioread32(davinci_spi->base + SPIBUF)
-						& SPIBUF_TXFULL_MASK) == 0)
-					iowrite32(data1_reg_val,
-						davinci_spi->base + SPIDAT1);
-
-				while (ioread32(davinci_spi->base + SPIBUF) &
-						SPIBUF_RXEMPTY_MASK)
-					cpu_relax();
-
-				flg_val = ioread32(davinci_spi->base + SPIFLG);
-				buf_val = ioread32(davinci_spi->base + SPIBUF);
-
-				davinci_spi->get_rx(buf_val, davinci_spi);
-
-				count--;
-				if (count <= 0)
-					break;
-			}
-		} else {	/* Receive in Interrupt mode */
-			int i;
-
-			for (i = 0; i < davinci_spi->count; i++) {
-				set_io_bits(davinci_spi->base + SPIINT,
-						SPIINT_BITERR_INTR
-						| SPIINT_OVRRUN_INTR
-						| SPIINT_RX_INTR);
-
-				iowrite32(data1_reg_val,
-						davinci_spi->base + SPIDAT1);
-
-				while (ioread32(davinci_spi->base + SPIINT) &
-						SPIINT_RX_INTR)
-					cpu_relax();
-			}
-			iowrite32((data1_reg_val & 0x0ffcffff),
-					davinci_spi->base + SPIDAT1);
-		}
-	}
-
-	/*
-	 * Check for bit error, desync error,parity error,timeout error and
-	 * receive overflow errors
-	 */
-	int_status = ioread32(davinci_spi->base + SPIFLG);
-
-	ret = davinci_spi_check_error(davinci_spi, int_status);
-	if (ret != 0)
-		return ret;
-
-	/* SPI Framework maintains the count only in bytes so convert back */
-	davinci_spi->count *= conv;
-
-	return t->len;
-}
-
-#define DAVINCI_DMA_DATA_TYPE_S8	0x01
-#define DAVINCI_DMA_DATA_TYPE_S16	0x02
-#define DAVINCI_DMA_DATA_TYPE_S32	0x04
-
-static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct davinci_spi *davinci_spi;
-	int int_status = 0;
-	int count, temp_count;
-	u8 conv = 1;
-	u8 tmp;
-	u32 data1_reg_val;
-	struct davinci_spi_dma *davinci_spi_dma;
-	int word_len, data_type, ret;
-	unsigned long tx_reg, rx_reg;
-	struct davinci_spi_platform_data *pdata;
+	unsigned uninitialized_var(rx_buf_count);
 	struct device *sdev;
 
-	davinci_spi = spi_master_get_devdata(spi->master);
-	pdata = davinci_spi->pdata;
-	sdev = davinci_spi->bitbang.master->dev.parent;
-
-	davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
-
-	tx_reg = (unsigned long)davinci_spi->pbase + SPIDAT1;
-	rx_reg = (unsigned long)davinci_spi->pbase + SPIBUF;
-
-	davinci_spi->tx = t->tx_buf;
-	davinci_spi->rx = t->rx_buf;
+	dspi = spi_master_get_devdata(spi->master);
+	pdata = dspi->pdata;
+	spicfg = (struct davinci_spi_config *)spi->controller_data;
+	if (!spicfg)
+		spicfg = &davinci_spi_default_cfg;
+	sdev = dspi->bitbang.master->dev.parent;
 
 	/* convert len to words based on bits_per_word */
-	conv = davinci_spi->slave[spi->chip_select].bytes_per_word;
-	davinci_spi->count = t->len / conv;
+	data_type = dspi->bytes_per_word[spi->chip_select];
 
-	INIT_COMPLETION(davinci_spi->done);
+	dspi->tx = t->tx_buf;
+	dspi->rx = t->rx_buf;
+	dspi->wcount = t->len / data_type;
+	dspi->rcount = dspi->wcount;
 
-	init_completion(&davinci_spi_dma->dma_rx_completion);
-	init_completion(&davinci_spi_dma->dma_tx_completion);
+	spidat1 = ioread32(dspi->base + SPIDAT1);
 
-	word_len = conv * 8;
+	clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
 
-	if (word_len <= 8)
-		data_type = DAVINCI_DMA_DATA_TYPE_S8;
-	else if (word_len <= 16)
-		data_type = DAVINCI_DMA_DATA_TYPE_S16;
-	else if (word_len <= 32)
-		data_type = DAVINCI_DMA_DATA_TYPE_S32;
-	else
-		return -EINVAL;
+	INIT_COMPLETION(dspi->done);
 
-	ret = davinci_spi_bufs_prep(spi, davinci_spi);
-	if (ret)
-		return ret;
+	if (spicfg->io_type == SPI_IO_TYPE_INTR)
+		set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
 
-	/* Put delay val if required */
-	iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) |
-			(pdata->t2cdelay << SPI_T2CDELAY_SHIFT),
-			davinci_spi->base + SPIDELAY);
-
-	count = davinci_spi->count;	/* the number of elements */
-	data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT;
-
-	/* CS default = 0xFF */
-	tmp = ~(0x1 << spi->chip_select);
-
-	clear_io_bits(davinci_spi->base + SPIDEF, ~tmp);
-
-	data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT;
-
-	/* disable all interrupts for dma transfers */
-	clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL);
-	/* Disable SPI to write configuration bits in SPIDAT */
-	clear_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
-	iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
-	/* Enable SPI */
-	set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
-
-	while ((ioread32(davinci_spi->base + SPIBUF)
-				& SPIBUF_RXEMPTY_MASK) == 0)
-		cpu_relax();
-
-
-	if (t->tx_buf) {
-		t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf, count,
-				DMA_TO_DEVICE);
-		if (dma_mapping_error(&spi->dev, t->tx_dma)) {
-			dev_dbg(sdev, "Unable to DMA map a %d bytes"
-				" TX buffer\n", count);
-			return -ENOMEM;
-		}
-		temp_count = count;
+	if (spicfg->io_type != SPI_IO_TYPE_DMA) {
+		/* start the transfer */
+		dspi->wcount--;
+		tx_data = dspi->get_tx(dspi);
+		spidat1 &= 0xFFFF0000;
+		spidat1 |= tx_data & 0xFFFF;
+		iowrite32(spidat1, dspi->base + SPIDAT1);
 	} else {
-		/* We need TX clocking for RX transaction */
-		t->tx_dma = dma_map_single(&spi->dev,
-				(void *)davinci_spi->tmp_buf, count + 1,
-				DMA_TO_DEVICE);
-		if (dma_mapping_error(&spi->dev, t->tx_dma)) {
-			dev_dbg(sdev, "Unable to DMA map a %d bytes"
-				" TX tmp buffer\n", count);
-			return -ENOMEM;
+		struct davinci_spi_dma *dma;
+		unsigned long tx_reg, rx_reg;
+		struct edmacc_param param;
+		void *rx_buf;
+
+		dma = &dspi->dma;
+
+		tx_reg = (unsigned long)dspi->pbase + SPIDAT1;
+		rx_reg = (unsigned long)dspi->pbase + SPIBUF;
+
+		/*
+		 * Transmit DMA setup
+		 *
+		 * If there is transmit data, map the transmit buffer, set it
+		 * as the source of data and set the source B index to data
+		 * size. If there is no transmit data, set the transmit register
+		 * as the source of data, and set the source B index to zero.
+		 *
+		 * The destination is always the transmit register itself. And
+		 * the destination never increments.
+		 */
+
+		if (t->tx_buf) {
+			t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf,
+						dspi->wcount, DMA_TO_DEVICE);
+			if (dma_mapping_error(&spi->dev, t->tx_dma)) {
+				dev_dbg(sdev, "Unable to DMA map %d bytes"
+						"TX buffer\n", dspi->wcount);
+				return -ENOMEM;
+			}
 		}
-		temp_count = count + 1;
-	}
 
-	edma_set_transfer_params(davinci_spi_dma->dma_tx_channel,
-					data_type, temp_count, 1, 0, ASYNC);
-	edma_set_dest(davinci_spi_dma->dma_tx_channel, tx_reg, INCR, W8BIT);
-	edma_set_src(davinci_spi_dma->dma_tx_channel, t->tx_dma, INCR, W8BIT);
-	edma_set_src_index(davinci_spi_dma->dma_tx_channel, data_type, 0);
-	edma_set_dest_index(davinci_spi_dma->dma_tx_channel, 0, 0);
+		param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
+		param.src = t->tx_buf ? t->tx_dma : tx_reg;
+		param.a_b_cnt = dspi->wcount << 16 | data_type;
+		param.dst = tx_reg;
+		param.src_dst_bidx = t->tx_buf ? data_type : 0;
+		param.link_bcntrld = 0xffff;
+		param.src_dst_cidx = 0;
+		param.ccnt = 1;
+		edma_write_slot(dma->tx_channel, &param);
+		edma_link(dma->tx_channel, dma->dummy_param_slot);
 
-	if (t->rx_buf) {
-		/* initiate transaction */
-		iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
+		/*
+		 * Receive DMA setup
+		 *
+		 * If there is receive buffer, use it to receive data. If there
+		 * is none provided, use a temporary receive buffer. Set the
+		 * destination B index to 0 so effectively only one byte is used
+		 * in the temporary buffer (address does not increment).
+		 *
+		 * The source of receive data is the receive data register. The
+		 * source address never increments.
+		 */
 
-		t->rx_dma = dma_map_single(&spi->dev, (void *)t->rx_buf, count,
-				DMA_FROM_DEVICE);
+		if (t->rx_buf) {
+			rx_buf = t->rx_buf;
+			rx_buf_count = dspi->rcount;
+		} else {
+			rx_buf = dspi->rx_tmp_buf;
+			rx_buf_count = sizeof(dspi->rx_tmp_buf);
+		}
+
+		t->rx_dma = dma_map_single(&spi->dev, rx_buf, rx_buf_count,
+							DMA_FROM_DEVICE);
 		if (dma_mapping_error(&spi->dev, t->rx_dma)) {
 			dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
-					count);
-			if (t->tx_buf != NULL)
-				dma_unmap_single(NULL, t->tx_dma,
-						 count, DMA_TO_DEVICE);
+								rx_buf_count);
+			if (t->tx_buf)
+				dma_unmap_single(NULL, t->tx_dma, dspi->wcount,
+								DMA_TO_DEVICE);
 			return -ENOMEM;
 		}
-		edma_set_transfer_params(davinci_spi_dma->dma_rx_channel,
-				data_type, count, 1, 0, ASYNC);
-		edma_set_src(davinci_spi_dma->dma_rx_channel,
-				rx_reg, INCR, W8BIT);
-		edma_set_dest(davinci_spi_dma->dma_rx_channel,
-				t->rx_dma, INCR, W8BIT);
-		edma_set_src_index(davinci_spi_dma->dma_rx_channel, 0, 0);
-		edma_set_dest_index(davinci_spi_dma->dma_rx_channel,
-				data_type, 0);
+
+		param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
+		param.src = rx_reg;
+		param.a_b_cnt = dspi->rcount << 16 | data_type;
+		param.dst = t->rx_dma;
+		param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
+		param.link_bcntrld = 0xffff;
+		param.src_dst_cidx = 0;
+		param.ccnt = 1;
+		edma_write_slot(dma->rx_channel, &param);
+
+		if (pdata->cshold_bug)
+			iowrite16(spidat1 >> 16, dspi->base + SPIDAT1 + 2);
+
+		edma_start(dma->rx_channel);
+		edma_start(dma->tx_channel);
+		set_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
 	}
 
-	if ((t->tx_buf) || (t->rx_buf))
-		edma_start(davinci_spi_dma->dma_tx_channel);
+	/* Wait for the transfer to complete */
+	if (spicfg->io_type != SPI_IO_TYPE_POLL) {
+		wait_for_completion_interruptible(&(dspi->done));
+	} else {
+		while (dspi->rcount > 0 || dspi->wcount > 0) {
+			errors = davinci_spi_process_events(dspi);
+			if (errors)
+				break;
+			cpu_relax();
+		}
+	}
 
-	if (t->rx_buf)
-		edma_start(davinci_spi_dma->dma_rx_channel);
+	clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL);
+	if (spicfg->io_type == SPI_IO_TYPE_DMA) {
 
-	if ((t->rx_buf) || (t->tx_buf))
-		davinci_spi_set_dma_req(spi, 1);
+		if (t->tx_buf)
+			dma_unmap_single(NULL, t->tx_dma, dspi->wcount,
+								DMA_TO_DEVICE);
 
-	if (t->tx_buf)
-		wait_for_completion_interruptible(
-				&davinci_spi_dma->dma_tx_completion);
+		dma_unmap_single(NULL, t->rx_dma, rx_buf_count,
+							DMA_FROM_DEVICE);
 
-	if (t->rx_buf)
-		wait_for_completion_interruptible(
-				&davinci_spi_dma->dma_rx_completion);
+		clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
+	}
 
-	dma_unmap_single(NULL, t->tx_dma, temp_count, DMA_TO_DEVICE);
-
-	if (t->rx_buf)
-		dma_unmap_single(NULL, t->rx_dma, count, DMA_FROM_DEVICE);
+	clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
 
 	/*
 	 * Check for bit error, desync error,parity error,timeout error and
 	 * receive overflow errors
 	 */
-	int_status = ioread32(davinci_spi->base + SPIFLG);
-
-	ret = davinci_spi_check_error(davinci_spi, int_status);
-	if (ret != 0)
+	if (errors) {
+		ret = davinci_spi_check_error(dspi, errors);
+		WARN(!ret, "%s: error reported but no error found!\n",
+							dev_name(&spi->dev));
 		return ret;
+	}
 
-	/* SPI Framework maintains the count only in bytes so convert back */
-	davinci_spi->count *= conv;
+	if (dspi->rcount != 0 || dspi->wcount != 0) {
+		dev_err(sdev, "SPI data transfer error\n");
+		return -EIO;
+	}
 
 	return t->len;
 }
 
 /**
- * davinci_spi_irq - IRQ handler for DaVinci SPI
+ * davinci_spi_irq - Interrupt handler for SPI Master Controller
  * @irq: IRQ number for this SPI Master
  * @context_data: structure for SPI Master controller davinci_spi
+ *
+ * ISR will determine that interrupt arrives either for READ or WRITE command.
+ * According to command it will do the appropriate action. It will check
+ * transfer length and if it is not zero then dispatch transfer command again.
+ * If transfer length is zero then it will indicate the COMPLETION so that
+ * davinci_spi_bufs function can go ahead.
  */
-static irqreturn_t davinci_spi_irq(s32 irq, void *context_data)
+static irqreturn_t davinci_spi_irq(s32 irq, void *data)
 {
-	struct davinci_spi *davinci_spi = context_data;
-	u32 int_status, rx_data = 0;
-	irqreturn_t ret = IRQ_NONE;
+	struct davinci_spi *dspi = data;
+	int status;
 
-	int_status = ioread32(davinci_spi->base + SPIFLG);
+	status = davinci_spi_process_events(dspi);
+	if (unlikely(status != 0))
+		clear_io_bits(dspi->base + SPIINT, SPIINT_MASKINT);
 
-	while ((int_status & SPIFLG_RX_INTR_MASK)) {
-		if (likely(int_status & SPIFLG_RX_INTR_MASK)) {
-			ret = IRQ_HANDLED;
+	if ((!dspi->rcount && !dspi->wcount) || status)
+		complete(&dspi->done);
 
-			rx_data = ioread32(davinci_spi->base + SPIBUF);
-			davinci_spi->get_rx(rx_data, davinci_spi);
+	return IRQ_HANDLED;
+}
 
-			/* Disable Receive Interrupt */
-			iowrite32(~(SPIINT_RX_INTR | SPIINT_TX_INTR),
-					davinci_spi->base + SPIINT);
-		} else
-			(void)davinci_spi_check_error(davinci_spi, int_status);
+static int davinci_spi_request_dma(struct davinci_spi *dspi)
+{
+	int r;
+	struct davinci_spi_dma *dma = &dspi->dma;
 
-		int_status = ioread32(davinci_spi->base + SPIFLG);
+	r = edma_alloc_channel(dma->rx_channel, davinci_spi_dma_callback, dspi,
+								dma->eventq);
+	if (r < 0) {
+		pr_err("Unable to request DMA channel for SPI RX\n");
+		r = -EAGAIN;
+		goto rx_dma_failed;
 	}
 
-	return ret;
+	r = edma_alloc_channel(dma->tx_channel, davinci_spi_dma_callback, dspi,
+								dma->eventq);
+	if (r < 0) {
+		pr_err("Unable to request DMA channel for SPI TX\n");
+		r = -EAGAIN;
+		goto tx_dma_failed;
+	}
+
+	r = edma_alloc_slot(EDMA_CTLR(dma->tx_channel), EDMA_SLOT_ANY);
+	if (r < 0) {
+		pr_err("Unable to request SPI TX DMA param slot\n");
+		r = -EAGAIN;
+		goto param_failed;
+	}
+	dma->dummy_param_slot = r;
+	edma_link(dma->dummy_param_slot, dma->dummy_param_slot);
+
+	return 0;
+param_failed:
+	edma_free_channel(dma->tx_channel);
+tx_dma_failed:
+	edma_free_channel(dma->rx_channel);
+rx_dma_failed:
+	return r;
 }
 
 /**
  * davinci_spi_probe - probe function for SPI Master Controller
  * @pdev: platform_device structure which contains plateform specific data
+ *
+ * According to Linux Device Model this function will be invoked by Linux
+ * with platform_device struct which contains the device specific info.
+ * This function will map the SPI controller's memory, register IRQ,
+ * Reset SPI controller and setting its registers to default value.
+ * It will invoke spi_bitbang_start to create work queue so that client driver
+ * can register transfer method to work queue.
  */
 static int davinci_spi_probe(struct platform_device *pdev)
 {
 	struct spi_master *master;
-	struct davinci_spi *davinci_spi;
+	struct davinci_spi *dspi;
 	struct davinci_spi_platform_data *pdata;
 	struct resource *r, *mem;
 	resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
 	resource_size_t	dma_tx_chan = SPI_NO_RESOURCE;
 	resource_size_t	dma_eventq = SPI_NO_RESOURCE;
 	int i = 0, ret = 0;
+	u32 spipc0;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -1035,8 +808,8 @@
 
 	dev_set_drvdata(&pdev->dev, master);
 
-	davinci_spi = spi_master_get_devdata(master);
-	if (davinci_spi == NULL) {
+	dspi = spi_master_get_devdata(master);
+	if (dspi == NULL) {
 		ret = -ENOENT;
 		goto free_master;
 	}
@@ -1047,164 +820,143 @@
 		goto free_master;
 	}
 
-	davinci_spi->pbase = r->start;
-	davinci_spi->region_size = resource_size(r);
-	davinci_spi->pdata = pdata;
+	dspi->pbase = r->start;
+	dspi->pdata = pdata;
 
-	mem = request_mem_region(r->start, davinci_spi->region_size,
-					pdev->name);
+	mem = request_mem_region(r->start, resource_size(r), pdev->name);
 	if (mem == NULL) {
 		ret = -EBUSY;
 		goto free_master;
 	}
 
-	davinci_spi->base = (struct davinci_spi_reg __iomem *)
-			ioremap(r->start, davinci_spi->region_size);
-	if (davinci_spi->base == NULL) {
+	dspi->base = ioremap(r->start, resource_size(r));
+	if (dspi->base == NULL) {
 		ret = -ENOMEM;
 		goto release_region;
 	}
 
-	davinci_spi->irq = platform_get_irq(pdev, 0);
-	if (davinci_spi->irq <= 0) {
+	dspi->irq = platform_get_irq(pdev, 0);
+	if (dspi->irq <= 0) {
 		ret = -EINVAL;
 		goto unmap_io;
 	}
 
-	ret = request_irq(davinci_spi->irq, davinci_spi_irq, IRQF_DISABLED,
-			  dev_name(&pdev->dev), davinci_spi);
+	ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev),
+									dspi);
 	if (ret)
 		goto unmap_io;
 
-	/* Allocate tmp_buf for tx_buf */
-	davinci_spi->tmp_buf = kzalloc(SPI_BUFSIZ, GFP_KERNEL);
-	if (davinci_spi->tmp_buf == NULL) {
-		ret = -ENOMEM;
+	dspi->bitbang.master = spi_master_get(master);
+	if (dspi->bitbang.master == NULL) {
+		ret = -ENODEV;
 		goto irq_free;
 	}
 
-	davinci_spi->bitbang.master = spi_master_get(master);
-	if (davinci_spi->bitbang.master == NULL) {
-		ret = -ENODEV;
-		goto free_tmp_buf;
-	}
-
-	davinci_spi->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(davinci_spi->clk)) {
+	dspi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dspi->clk)) {
 		ret = -ENODEV;
 		goto put_master;
 	}
-	clk_enable(davinci_spi->clk);
-
+	clk_enable(dspi->clk);
 
 	master->bus_num = pdev->id;
 	master->num_chipselect = pdata->num_chipselect;
 	master->setup = davinci_spi_setup;
-	master->cleanup = davinci_spi_cleanup;
 
-	davinci_spi->bitbang.chipselect = davinci_spi_chipselect;
-	davinci_spi->bitbang.setup_transfer = davinci_spi_setup_transfer;
+	dspi->bitbang.chipselect = davinci_spi_chipselect;
+	dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
 
-	davinci_spi->version = pdata->version;
-	use_dma = pdata->use_dma;
+	dspi->version = pdata->version;
 
-	davinci_spi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
-	if (davinci_spi->version == SPI_VERSION_2)
-		davinci_spi->bitbang.flags |= SPI_READY;
+	dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
+	if (dspi->version == SPI_VERSION_2)
+		dspi->bitbang.flags |= SPI_READY;
 
-	if (use_dma) {
-			r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-			if (r)
-				dma_rx_chan = r->start;
-			r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-			if (r)
-				dma_tx_chan = r->start;
-			r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
-			if (r)
-				dma_eventq = r->start;
-	}
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (r)
+		dma_rx_chan = r->start;
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (r)
+		dma_tx_chan = r->start;
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
+	if (r)
+		dma_eventq = r->start;
 
-	if (!use_dma ||
-	    dma_rx_chan == SPI_NO_RESOURCE ||
-	    dma_tx_chan == SPI_NO_RESOURCE ||
-	    dma_eventq	== SPI_NO_RESOURCE) {
-		davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_pio;
-		use_dma = 0;
-	} else {
-		davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_dma;
-		davinci_spi->dma_channels = kzalloc(master->num_chipselect
-				* sizeof(struct davinci_spi_dma), GFP_KERNEL);
-		if (davinci_spi->dma_channels == NULL) {
-			ret = -ENOMEM;
+	dspi->bitbang.txrx_bufs = davinci_spi_bufs;
+	if (dma_rx_chan != SPI_NO_RESOURCE &&
+	    dma_tx_chan != SPI_NO_RESOURCE &&
+	    dma_eventq != SPI_NO_RESOURCE) {
+		dspi->dma.rx_channel = dma_rx_chan;
+		dspi->dma.tx_channel = dma_tx_chan;
+		dspi->dma.eventq = dma_eventq;
+
+		ret = davinci_spi_request_dma(dspi);
+		if (ret)
 			goto free_clk;
-		}
 
-		for (i = 0; i < master->num_chipselect; i++) {
-			davinci_spi->dma_channels[i].dma_rx_channel = -1;
-			davinci_spi->dma_channels[i].dma_rx_sync_dev =
-				dma_rx_chan;
-			davinci_spi->dma_channels[i].dma_tx_channel = -1;
-			davinci_spi->dma_channels[i].dma_tx_sync_dev =
-				dma_tx_chan;
-			davinci_spi->dma_channels[i].eventq = dma_eventq;
-		}
-		dev_info(&pdev->dev, "DaVinci SPI driver in EDMA mode\n"
-				"Using RX channel = %d , TX channel = %d and "
-				"event queue = %d", dma_rx_chan, dma_tx_chan,
+		dev_info(&pdev->dev, "DMA: supported\n");
+		dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
+				"event queue: %d\n", dma_rx_chan, dma_tx_chan,
 				dma_eventq);
 	}
 
-	davinci_spi->get_rx = davinci_spi_rx_buf_u8;
-	davinci_spi->get_tx = davinci_spi_tx_buf_u8;
+	dspi->get_rx = davinci_spi_rx_buf_u8;
+	dspi->get_tx = davinci_spi_tx_buf_u8;
 
-	init_completion(&davinci_spi->done);
+	init_completion(&dspi->done);
 
 	/* Reset In/OUT SPI module */
-	iowrite32(0, davinci_spi->base + SPIGCR0);
+	iowrite32(0, dspi->base + SPIGCR0);
 	udelay(100);
-	iowrite32(1, davinci_spi->base + SPIGCR0);
+	iowrite32(1, dspi->base + SPIGCR0);
 
-	/* Clock internal */
-	if (davinci_spi->pdata->clk_internal)
-		set_io_bits(davinci_spi->base + SPIGCR1,
-				SPIGCR1_CLKMOD_MASK);
+	/* Set up SPIPC0.  CS and ENA init is done in davinci_spi_setup */
+	spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK;
+	iowrite32(spipc0, dspi->base + SPIPC0);
+
+	/* initialize chip selects */
+	if (pdata->chip_sel) {
+		for (i = 0; i < pdata->num_chipselect; i++) {
+			if (pdata->chip_sel[i] != SPI_INTERN_CS)
+				gpio_direction_output(pdata->chip_sel[i], 1);
+		}
+	}
+
+	if (pdata->intr_line)
+		iowrite32(SPI_INTLVL_1, dspi->base + SPILVL);
 	else
-		clear_io_bits(davinci_spi->base + SPIGCR1,
-				SPIGCR1_CLKMOD_MASK);
+		iowrite32(SPI_INTLVL_0, dspi->base + SPILVL);
+
+	iowrite32(CS_DEFAULT, dspi->base + SPIDEF);
 
 	/* master mode default */
-	set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
+	set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
 
-	if (davinci_spi->pdata->intr_level)
-		iowrite32(SPI_INTLVL_1, davinci_spi->base + SPILVL);
-	else
-		iowrite32(SPI_INTLVL_0, davinci_spi->base + SPILVL);
-
-	ret = spi_bitbang_start(&davinci_spi->bitbang);
+	ret = spi_bitbang_start(&dspi->bitbang);
 	if (ret)
-		goto free_clk;
+		goto free_dma;
 
-	dev_info(&pdev->dev, "Controller at 0x%p \n", davinci_spi->base);
-
-	if (!pdata->poll_mode)
-		dev_info(&pdev->dev, "Operating in interrupt mode"
-			" using IRQ %d\n", davinci_spi->irq);
+	dev_info(&pdev->dev, "Controller at 0x%p\n", dspi->base);
 
 	return ret;
 
+free_dma:
+	edma_free_channel(dspi->dma.tx_channel);
+	edma_free_channel(dspi->dma.rx_channel);
+	edma_free_slot(dspi->dma.dummy_param_slot);
 free_clk:
-	clk_disable(davinci_spi->clk);
-	clk_put(davinci_spi->clk);
+	clk_disable(dspi->clk);
+	clk_put(dspi->clk);
 put_master:
 	spi_master_put(master);
-free_tmp_buf:
-	kfree(davinci_spi->tmp_buf);
 irq_free:
-	free_irq(davinci_spi->irq, davinci_spi);
+	free_irq(dspi->irq, dspi);
 unmap_io:
-	iounmap(davinci_spi->base);
+	iounmap(dspi->base);
 release_region:
-	release_mem_region(davinci_spi->pbase, davinci_spi->region_size);
+	release_mem_region(dspi->pbase, resource_size(r));
 free_master:
 	kfree(master);
 err:
@@ -1222,27 +974,31 @@
  */
 static int __exit davinci_spi_remove(struct platform_device *pdev)
 {
-	struct davinci_spi *davinci_spi;
+	struct davinci_spi *dspi;
 	struct spi_master *master;
+	struct resource *r;
 
 	master = dev_get_drvdata(&pdev->dev);
-	davinci_spi = spi_master_get_devdata(master);
+	dspi = spi_master_get_devdata(master);
 
-	spi_bitbang_stop(&davinci_spi->bitbang);
+	spi_bitbang_stop(&dspi->bitbang);
 
-	clk_disable(davinci_spi->clk);
-	clk_put(davinci_spi->clk);
+	clk_disable(dspi->clk);
+	clk_put(dspi->clk);
 	spi_master_put(master);
-	kfree(davinci_spi->tmp_buf);
-	free_irq(davinci_spi->irq, davinci_spi);
-	iounmap(davinci_spi->base);
-	release_mem_region(davinci_spi->pbase, davinci_spi->region_size);
+	free_irq(dspi->irq, dspi);
+	iounmap(dspi->base);
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(dspi->pbase, resource_size(r));
 
 	return 0;
 }
 
 static struct platform_driver davinci_spi_driver = {
-	.driver.name = "spi_davinci",
+	.driver = {
+		.name = "spi_davinci",
+		.owner = THIS_MODULE,
+	},
 	.remove = __exit_p(davinci_spi_remove),
 };
 
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 0838c79..22af77f 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -164,20 +164,23 @@
 
 static void wait_till_not_busy(struct dw_spi *dws)
 {
-	unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);
+	unsigned long end = jiffies + 1 + usecs_to_jiffies(5000);
 
 	while (time_before(jiffies, end)) {
 		if (!(dw_readw(dws, sr) & SR_BUSY))
 			return;
+		cpu_relax();
 	}
 	dev_err(&dws->master->dev,
-		"DW SPI: Status keeps busy for 1000us after a read/write!\n");
+		"DW SPI: Status keeps busy for 5000us after a read/write!\n");
 }
 
 static void flush(struct dw_spi *dws)
 {
-	while (dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+	while (dw_readw(dws, sr) & SR_RF_NOT_EMPT) {
 		dw_readw(dws, dr);
+		cpu_relax();
+	}
 
 	wait_till_not_busy(dws);
 }
@@ -285,8 +288,10 @@
  */
 static int map_dma_buffers(struct dw_spi *dws)
 {
-	if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited
-		|| !dws->cur_chip->enable_dma)
+	if (!dws->cur_msg->is_dma_mapped
+		|| !dws->dma_inited
+		|| !dws->cur_chip->enable_dma
+		|| !dws->dma_ops)
 		return 0;
 
 	if (dws->cur_transfer->tx_dma)
@@ -338,7 +343,7 @@
 	tasklet_schedule(&dws->pump_transfers);
 }
 
-static void transfer_complete(struct dw_spi *dws)
+void dw_spi_xfer_done(struct dw_spi *dws)
 {
 	/* Update total byte transfered return count actual bytes read */
 	dws->cur_msg->actual_length += dws->len;
@@ -353,6 +358,7 @@
 	} else
 		tasklet_schedule(&dws->pump_transfers);
 }
+EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
@@ -384,7 +390,7 @@
 		if (dws->tx_end > dws->tx)
 			spi_umask_intr(dws, SPI_INT_TXEI);
 		else
-			transfer_complete(dws);
+			dw_spi_xfer_done(dws);
 	}
 
 	return IRQ_HANDLED;
@@ -419,11 +425,7 @@
 	 */
 	dws->read(dws);
 
-	transfer_complete(dws);
-}
-
-static void dma_transfer(struct dw_spi *dws, int cs_change)
-{
+	dw_spi_xfer_done(dws);
 }
 
 static void pump_transfers(unsigned long data)
@@ -592,7 +594,7 @@
 		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
 		spi_chip_sel(dws, spi->chip_select);
 
-		/* Set the interrupt mask, for poll mode just diable all int */
+		/* Set the interrupt mask, for poll mode just disable all int */
 		spi_mask_intr(dws, 0xff);
 		if (imask)
 			spi_umask_intr(dws, imask);
@@ -605,7 +607,7 @@
 	}
 
 	if (dws->dma_mapped)
-		dma_transfer(dws, cs_change);
+		dws->dma_ops->dma_transfer(dws, cs_change);
 
 	if (chip->poll_mode)
 		poll_transfer(dws);
@@ -901,11 +903,17 @@
 	master->setup = dw_spi_setup;
 	master->transfer = dw_spi_transfer;
 
-	dws->dma_inited = 0;
-
 	/* Basic HW init */
 	spi_hw_init(dws);
 
+	if (dws->dma_ops && dws->dma_ops->dma_init) {
+		ret = dws->dma_ops->dma_init(dws);
+		if (ret) {
+			dev_warn(&master->dev, "DMA init failed\n");
+			dws->dma_inited = 0;
+		}
+	}
+
 	/* Initial and start queue */
 	ret = init_queue(dws);
 	if (ret) {
@@ -930,6 +938,8 @@
 
 err_queue_alloc:
 	destroy_queue(dws);
+	if (dws->dma_ops && dws->dma_ops->dma_exit)
+		dws->dma_ops->dma_exit(dws);
 err_diable_hw:
 	spi_enable_chip(dws, 0);
 	free_irq(dws->irq, dws);
@@ -938,7 +948,7 @@
 exit:
 	return ret;
 }
-EXPORT_SYMBOL(dw_spi_add_host);
+EXPORT_SYMBOL_GPL(dw_spi_add_host);
 
 void __devexit dw_spi_remove_host(struct dw_spi *dws)
 {
@@ -954,6 +964,8 @@
 		dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
 			"complete, message memory not freed\n");
 
+	if (dws->dma_ops && dws->dma_ops->dma_exit)
+		dws->dma_ops->dma_exit(dws);
 	spi_enable_chip(dws, 0);
 	/* Disable clk */
 	spi_set_clk(dws, 0);
@@ -962,7 +974,7 @@
 	/* Disconnect from the SPI framework */
 	spi_unregister_master(dws->master);
 }
-EXPORT_SYMBOL(dw_spi_remove_host);
+EXPORT_SYMBOL_GPL(dw_spi_remove_host);
 
 int dw_spi_suspend_host(struct dw_spi *dws)
 {
@@ -975,7 +987,7 @@
 	spi_set_clk(dws, 0);
 	return ret;
 }
-EXPORT_SYMBOL(dw_spi_suspend_host);
+EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
 
 int dw_spi_resume_host(struct dw_spi *dws)
 {
@@ -987,7 +999,7 @@
 		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
 	return ret;
 }
-EXPORT_SYMBOL(dw_spi_resume_host);
+EXPORT_SYMBOL_GPL(dw_spi_resume_host);
 
 MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
 MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/dw_spi_mid.c
new file mode 100644
index 0000000..c91c966
--- /dev/null
+++ b/drivers/spi/dw_spi_mid.c
@@ -0,0 +1,223 @@
+/*
+ * dw_spi_mid.c - special handling for DW core on Intel MID platform
+ *
+ * Copyright (c) 2009, 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.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/dw_spi.h>
+
+#ifdef CONFIG_SPI_DW_MID_DMA
+#include <linux/intel_mid_dma.h>
+#include <linux/pci.h>
+
+struct mid_dma {
+	struct intel_mid_dma_slave	dmas_tx;
+	struct intel_mid_dma_slave	dmas_rx;
+};
+
+static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
+{
+	struct dw_spi *dws = param;
+
+	return dws->dmac && (&dws->dmac->dev == chan->device->dev);
+}
+
+static int mid_spi_dma_init(struct dw_spi *dws)
+{
+	struct mid_dma *dw_dma = dws->dma_priv;
+	struct intel_mid_dma_slave *rxs, *txs;
+	dma_cap_mask_t mask;
+
+	/*
+	 * Get pci device for DMA controller, currently it could only
+	 * be the DMA controller of either Moorestown or Medfield
+	 */
+	dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL);
+	if (!dws->dmac)
+		dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	/* 1. Init rx channel */
+	dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
+	if (!dws->rxchan)
+		goto err_exit;
+	rxs = &dw_dma->dmas_rx;
+	rxs->hs_mode = LNW_DMA_HW_HS;
+	rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
+	dws->rxchan->private = rxs;
+
+	/* 2. Init tx channel */
+	dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
+	if (!dws->txchan)
+		goto free_rxchan;
+	txs = &dw_dma->dmas_tx;
+	txs->hs_mode = LNW_DMA_HW_HS;
+	txs->cfg_mode = LNW_DMA_MEM_TO_PER;
+	dws->txchan->private = txs;
+
+	dws->dma_inited = 1;
+	return 0;
+
+free_rxchan:
+	dma_release_channel(dws->rxchan);
+err_exit:
+	return -1;
+
+}
+
+static void mid_spi_dma_exit(struct dw_spi *dws)
+{
+	dma_release_channel(dws->txchan);
+	dma_release_channel(dws->rxchan);
+}
+
+/*
+ * dws->dma_chan_done is cleared before the dma transfer starts,
+ * callback for rx/tx channel will each increment it by 1.
+ * Reaching 2 means the whole spi transaction is done.
+ */
+static void dw_spi_dma_done(void *arg)
+{
+	struct dw_spi *dws = arg;
+
+	if (++dws->dma_chan_done != 2)
+		return;
+	dw_spi_xfer_done(dws);
+}
+
+static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
+{
+	struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
+	struct dma_chan *txchan, *rxchan;
+	struct dma_slave_config txconf, rxconf;
+	u16 dma_ctrl = 0;
+
+	/* 1. setup DMA related registers */
+	if (cs_change) {
+		spi_enable_chip(dws, 0);
+		dw_writew(dws, dmardlr, 0xf);
+		dw_writew(dws, dmatdlr, 0x10);
+		if (dws->tx_dma)
+			dma_ctrl |= 0x2;
+		if (dws->rx_dma)
+			dma_ctrl |= 0x1;
+		dw_writew(dws, dmacr, dma_ctrl);
+		spi_enable_chip(dws, 1);
+	}
+
+	dws->dma_chan_done = 0;
+	txchan = dws->txchan;
+	rxchan = dws->rxchan;
+
+	/* 2. Prepare the TX dma transfer */
+	txconf.direction = DMA_TO_DEVICE;
+	txconf.dst_addr = dws->dma_addr;
+	txconf.dst_maxburst = LNW_DMA_MSIZE_16;
+	txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+	txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
+				       (unsigned long) &txconf);
+
+	memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
+	dws->tx_sgl.dma_address = dws->tx_dma;
+	dws->tx_sgl.length = dws->len;
+
+	txdesc = txchan->device->device_prep_slave_sg(txchan,
+				&dws->tx_sgl,
+				1,
+				DMA_TO_DEVICE,
+				DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
+	txdesc->callback = dw_spi_dma_done;
+	txdesc->callback_param = dws;
+
+	/* 3. Prepare the RX dma transfer */
+	rxconf.direction = DMA_FROM_DEVICE;
+	rxconf.src_addr = dws->dma_addr;
+	rxconf.src_maxburst = LNW_DMA_MSIZE_16;
+	rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+	rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
+				       (unsigned long) &rxconf);
+
+	memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
+	dws->rx_sgl.dma_address = dws->rx_dma;
+	dws->rx_sgl.length = dws->len;
+
+	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+				&dws->rx_sgl,
+				1,
+				DMA_FROM_DEVICE,
+				DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
+	rxdesc->callback = dw_spi_dma_done;
+	rxdesc->callback_param = dws;
+
+	/* rx must be started before tx due to spi instinct */
+	rxdesc->tx_submit(rxdesc);
+	txdesc->tx_submit(txdesc);
+	return 0;
+}
+
+static struct dw_spi_dma_ops mid_dma_ops = {
+	.dma_init	= mid_spi_dma_init,
+	.dma_exit	= mid_spi_dma_exit,
+	.dma_transfer	= mid_spi_dma_transfer,
+};
+#endif
+
+/* Some specific info for SPI0 controller on Moorestown */
+
+/* HW info for MRST CLk Control Unit, one 32b reg */
+#define MRST_SPI_CLK_BASE	100000000	/* 100m */
+#define MRST_CLK_SPI0_REG	0xff11d86c
+#define CLK_SPI_BDIV_OFFSET	0
+#define CLK_SPI_BDIV_MASK	0x00000007
+#define CLK_SPI_CDIV_OFFSET	9
+#define CLK_SPI_CDIV_MASK	0x00000e00
+#define CLK_SPI_DISABLE_OFFSET	8
+
+int dw_spi_mid_init(struct dw_spi *dws)
+{
+	u32 *clk_reg, clk_cdiv;
+
+	clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
+	if (!clk_reg)
+		return -ENOMEM;
+
+	/* get SPI controller operating freq info */
+	clk_cdiv  = (readl(clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
+	dws->max_freq = MRST_SPI_CLK_BASE / (clk_cdiv + 1);
+	iounmap(clk_reg);
+
+	dws->num_cs = 16;
+	dws->fifo_len = 40;	/* FIFO has 40 words buffer */
+
+#ifdef CONFIG_SPI_DW_MID_DMA
+	dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
+	if (!dws->dma_priv)
+		return -ENOMEM;
+	dws->dma_ops = &mid_dma_ops;
+#endif
+	return 0;
+}
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
index 1f52755..49ec3aa 100644
--- a/drivers/spi/dw_spi_pci.c
+++ b/drivers/spi/dw_spi_pci.c
@@ -1,5 +1,5 @@
 /*
- * mrst_spi_pci.c - PCI interface driver for DW SPI Core
+ * dw_spi_pci.c - PCI interface driver for DW SPI Core
  *
  * Copyright (c) 2009, Intel Corporation.
  *
@@ -26,8 +26,8 @@
 #define DRIVER_NAME "dw_spi_pci"
 
 struct dw_spi_pci {
-	struct pci_dev		*pdev;
-	struct dw_spi		dws;
+	struct pci_dev	*pdev;
+	struct dw_spi	dws;
 };
 
 static int __devinit spi_pci_probe(struct pci_dev *pdev,
@@ -72,9 +72,17 @@
 	dws->parent_dev = &pdev->dev;
 	dws->bus_num = 0;
 	dws->num_cs = 4;
-	dws->max_freq = 25000000;	/* for Moorestwon */
 	dws->irq = pdev->irq;
-	dws->fifo_len = 40;		/* FIFO has 40 words buffer */
+
+	/*
+	 * Specific handling for Intel MID paltforms, like dma setup,
+	 * clock rate, FIFO depth.
+	 */
+	if (pdev->device == 0x0800) {
+		ret = dw_spi_mid_init(dws);
+		if (ret)
+			goto err_unmap;
+	}
 
 	ret = dw_spi_add_host(dws);
 	if (ret)
@@ -140,7 +148,7 @@
 #endif
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
-	/* Intel Moorestown platform SPI controller 0 */
+	/* Intel MID platform SPI controller 0 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
 	{},
 };
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 983fbbf..8a904c1 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -363,7 +363,7 @@
 }
 
 /* bus_num is used only for the case dev->platform_data == NULL */
-static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
+static int __devinit mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
 				u32 size, unsigned int irq, s16 bus_num)
 {
 	struct fsl_spi_platform_data *pdata = dev->platform_data;
@@ -450,22 +450,7 @@
 	return ret;
 }
 
-static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
-{
-	struct spi_master *master = dev_get_drvdata(dev);
-	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
-
-	flush_workqueue(mps->workqueue);
-	destroy_workqueue(mps->workqueue);
-	spi_unregister_master(master);
-	free_irq(mps->irq, mps);
-	if (mps->psc)
-		iounmap(mps->psc);
-
-	return 0;
-}
-
-static int __init mpc52xx_psc_spi_of_probe(struct platform_device *op,
+static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op,
 	const struct of_device_id *match)
 {
 	const u32 *regaddr_p;
@@ -495,9 +480,19 @@
 				irq_of_parse_and_map(op->dev.of_node, 0), id);
 }
 
-static int __exit mpc52xx_psc_spi_of_remove(struct platform_device *op)
+static int __devexit mpc52xx_psc_spi_of_remove(struct platform_device *op)
 {
-	return mpc52xx_psc_spi_do_remove(&op->dev);
+	struct spi_master *master = dev_get_drvdata(&op->dev);
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
+
+	flush_workqueue(mps->workqueue);
+	destroy_workqueue(mps->workqueue);
+	spi_unregister_master(master);
+	free_irq(mps->irq, mps);
+	if (mps->psc)
+		iounmap(mps->psc);
+
+	return 0;
 }
 
 static const struct of_device_id mpc52xx_psc_spi_of_match[] = {
@@ -510,7 +505,7 @@
 
 static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
 	.probe = mpc52xx_psc_spi_of_probe,
-	.remove = __exit_p(mpc52xx_psc_spi_of_remove),
+	.remove = __devexit_p(mpc52xx_psc_spi_of_remove),
 	.driver = {
 		.name = "mpc52xx-psc-spi",
 		.owner = THIS_MODULE,
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 2a651e6..abb1ffb 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -397,7 +397,7 @@
 
 	if (tx != NULL) {
 		wait_for_completion(&mcspi_dma->dma_tx_completion);
-		dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+		dma_unmap_single(&spi->dev, xfer->tx_dma, count, DMA_TO_DEVICE);
 
 		/* for TX_ONLY mode, be sure all words have shifted out */
 		if (rx == NULL) {
@@ -412,7 +412,7 @@
 
 	if (rx != NULL) {
 		wait_for_completion(&mcspi_dma->dma_rx_completion);
-		dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
+		dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE);
 		omap2_mcspi_set_enable(spi, 0);
 
 		if (l & OMAP2_MCSPI_CHCONF_TURBO) {
@@ -1025,11 +1025,6 @@
 		if (m->is_dma_mapped || len < DMA_MIN_BYTES)
 			continue;
 
-		/* Do DMA mapping "early" for better error reporting and
-		 * dcache use.  Note that if dma_unmap_single() ever starts
-		 * to do real work on ARM, we'd need to clean up mappings
-		 * for previous transfers on *ALL* exits of this loop...
-		 */
 		if (tx_buf != NULL) {
 			t->tx_dma = dma_map_single(&spi->dev, (void *) tx_buf,
 					len, DMA_TO_DEVICE);
@@ -1046,7 +1041,7 @@
 				dev_dbg(&spi->dev, "dma %cX %d bytes error\n",
 						'R', len);
 				if (tx_buf != NULL)
-					dma_unmap_single(NULL, t->tx_dma,
+					dma_unmap_single(&spi->dev, t->tx_dma,
 							len, DMA_TO_DEVICE);
 				return -EINVAL;
 			}
@@ -1305,10 +1300,49 @@
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:omap2_mcspi");
 
+#ifdef	CONFIG_SUSPEND
+/*
+ * When SPI wake up from off-mode, CS is in activate state. If it was in
+ * unactive state when driver was suspend, then force it to unactive state at
+ * wake up.
+ */
+static int omap2_mcspi_resume(struct device *dev)
+{
+	struct spi_master	*master = dev_get_drvdata(dev);
+	struct omap2_mcspi	*mcspi = spi_master_get_devdata(master);
+	struct omap2_mcspi_cs *cs;
+
+	omap2_mcspi_enable_clocks(mcspi);
+	list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs,
+			    node) {
+		if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
+
+			/*
+			 * We need to toggle CS state for OMAP take this
+			 * change in account.
+			 */
+			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
+			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+			MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
+			__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+		}
+	}
+	omap2_mcspi_disable_clocks(mcspi);
+	return 0;
+}
+#else
+#define	omap2_mcspi_resume	NULL
+#endif
+
+static const struct dev_pm_ops omap2_mcspi_pm_ops = {
+	.resume = omap2_mcspi_resume,
+};
+
 static struct platform_driver omap2_mcspi_driver = {
 	.driver = {
 		.name =		"omap2_mcspi",
 		.owner =	THIS_MODULE,
+		.pm =		&omap2_mcspi_pm_ops
 	},
 	.remove =	__exit_p(omap2_mcspi_remove),
 };
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index e76b1af..9592883 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -23,11 +23,11 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/spi/pxa2xx_spi.h>
 #include <linux/dma-mapping.h>
 #include <linux/spi/spi.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 
@@ -35,9 +35,6 @@
 #include <asm/irq.h>
 #include <asm/delay.h>
 
-#include <mach/dma.h>
-#include <plat/ssp.h>
-#include <mach/pxa2xx_spi.h>
 
 MODULE_AUTHOR("Stephen Street");
 MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
@@ -46,8 +43,6 @@
 
 #define MAX_BUSES 3
 
-#define RX_THRESH_DFLT 	8
-#define TX_THRESH_DFLT 	8
 #define TIMOUT_DFLT		1000
 
 #define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
@@ -168,7 +163,10 @@
 	u8 enable_dma;
 	u8 bits_per_word;
 	u32 speed_hz;
-	int gpio_cs;
+	union {
+		int gpio_cs;
+		unsigned int frm;
+	};
 	int gpio_cs_inverted;
 	int (*write)(struct driver_data *drv_data);
 	int (*read)(struct driver_data *drv_data);
@@ -181,6 +179,11 @@
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
+	if (drv_data->ssp_type == CE4100_SSP) {
+		write_SSSR(drv_data->cur_chip->frm, drv_data->ioaddr);
+		return;
+	}
+
 	if (chip->cs_control) {
 		chip->cs_control(PXA2XX_CS_ASSERT);
 		return;
@@ -194,6 +197,9 @@
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
+	if (drv_data->ssp_type == CE4100_SSP)
+		return;
+
 	if (chip->cs_control) {
 		chip->cs_control(PXA2XX_CS_DEASSERT);
 		return;
@@ -203,6 +209,25 @@
 		gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
 }
 
+static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
+{
+	void __iomem *reg = drv_data->ioaddr;
+
+	if (drv_data->ssp_type == CE4100_SSP)
+		val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
+
+	write_SSSR(val, reg);
+}
+
+static int pxa25x_ssp_comp(struct driver_data *drv_data)
+{
+	if (drv_data->ssp_type == PXA25x_SSP)
+		return 1;
+	if (drv_data->ssp_type == CE4100_SSP)
+		return 1;
+	return 0;
+}
+
 static int flush(struct driver_data *drv_data)
 {
 	unsigned long limit = loops_per_jiffy << 1;
@@ -214,7 +239,7 @@
 			read_SSDR(reg);
 		}
 	} while ((read_SSSR(reg) & SSSR_BSY) && --limit);
-	write_SSSR(SSSR_ROR, reg);
+	write_SSSR_CS(drv_data, SSSR_ROR);
 
 	return limit;
 }
@@ -224,7 +249,7 @@
 	void __iomem *reg = drv_data->ioaddr;
 	u8 n_bytes = drv_data->n_bytes;
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 
@@ -252,7 +277,7 @@
 {
 	void __iomem *reg = drv_data->ioaddr;
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 
@@ -279,7 +304,7 @@
 {
 	void __iomem *reg = drv_data->ioaddr;
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 
@@ -306,7 +331,7 @@
 {
 	void __iomem *reg = drv_data->ioaddr;
 
-	if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+	if (((read_SSSR(reg) & SSSR_TFL_MASK) == SSSR_TFL_MASK)
 		|| (drv_data->tx == drv_data->tx_end))
 		return 0;
 
@@ -507,9 +532,9 @@
 	/* Stop and reset */
 	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	write_SSSR(drv_data->clear_sr, reg);
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
 	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, reg);
 	flush(drv_data);
 	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
@@ -529,7 +554,7 @@
 
 	/* Clear and disable interrupts on SSP and DMA channels*/
 	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	write_SSSR(drv_data->clear_sr, reg);
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
 	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
 	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
 
@@ -622,7 +647,7 @@
 
 		/* Clear and disable timeout interrupt, do the rest in
 		 * dma_transfer_complete */
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(0, reg);
 
 		/* finish this transfer, start the next */
@@ -635,14 +660,26 @@
 	return IRQ_NONE;
 }
 
+static void reset_sccr1(struct driver_data *drv_data)
+{
+	void __iomem *reg = drv_data->ioaddr;
+	struct chip_data *chip = drv_data->cur_chip;
+	u32 sccr1_reg;
+
+	sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1;
+	sccr1_reg &= ~SSCR1_RFT;
+	sccr1_reg |= chip->threshold;
+	write_SSCR1(sccr1_reg, reg);
+}
+
 static void int_error_stop(struct driver_data *drv_data, const char* msg)
 {
 	void __iomem *reg = drv_data->ioaddr;
 
 	/* Stop and reset SSP */
-	write_SSSR(drv_data->clear_sr, reg);
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	reset_sccr1(drv_data);
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, reg);
 	flush(drv_data);
 	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
@@ -658,9 +695,9 @@
 	void __iomem *reg = drv_data->ioaddr;
 
 	/* Stop SSP */
-	write_SSSR(drv_data->clear_sr, reg);
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	write_SSSR_CS(drv_data, drv_data->clear_sr);
+	reset_sccr1(drv_data);
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, reg);
 
 	/* Update total byte transfered return count actual bytes read */
@@ -714,24 +751,34 @@
 	}
 
 	if (drv_data->tx == drv_data->tx_end) {
-		write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
-		/* PXA25x_SSP has no timeout, read trailing bytes */
-		if (drv_data->ssp_type == PXA25x_SSP) {
-			if (!wait_ssp_rx_stall(reg))
-			{
-				int_error_stop(drv_data, "interrupt_transfer: "
-						"rx stall failed");
-				return IRQ_HANDLED;
+		u32 bytes_left;
+		u32 sccr1_reg;
+
+		sccr1_reg = read_SSCR1(reg);
+		sccr1_reg &= ~SSCR1_TIE;
+
+		/*
+		 * PXA25x_SSP has no timeout, set up rx threshould for the
+		 * remaing RX bytes.
+		 */
+		if (pxa25x_ssp_comp(drv_data)) {
+
+			sccr1_reg &= ~SSCR1_RFT;
+
+			bytes_left = drv_data->rx_end - drv_data->rx;
+			switch (drv_data->n_bytes) {
+			case 4:
+				bytes_left >>= 1;
+			case 2:
+				bytes_left >>= 1;
 			}
-			if (!drv_data->read(drv_data))
-			{
-				int_error_stop(drv_data,
-						"interrupt_transfer: "
-						"trailing byte read failed");
-				return IRQ_HANDLED;
-			}
-			int_transfer_complete(drv_data);
+
+			if (bytes_left > RX_THRESH_DFLT)
+				bytes_left = RX_THRESH_DFLT;
+
+			sccr1_reg |= SSCR1_RxTresh(bytes_left);
 		}
+		write_SSCR1(sccr1_reg, reg);
 	}
 
 	/* We did something */
@@ -742,14 +789,26 @@
 {
 	struct driver_data *drv_data = dev_id;
 	void __iomem *reg = drv_data->ioaddr;
+	u32 sccr1_reg = read_SSCR1(reg);
+	u32 mask = drv_data->mask_sr;
+	u32 status;
+
+	status = read_SSSR(reg);
+
+	/* Ignore possible writes if we don't need to write */
+	if (!(sccr1_reg & SSCR1_TIE))
+		mask &= ~SSSR_TFS;
+
+	if (!(status & mask))
+		return IRQ_NONE;
 
 	if (!drv_data->cur_msg) {
 
 		write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
 		write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(0, reg);
-		write_SSSR(drv_data->clear_sr, reg);
+		write_SSSR_CS(drv_data, drv_data->clear_sr);
 
 		dev_err(&drv_data->pdev->dev, "bad message state "
 			"in interrupt handler\n");
@@ -862,7 +921,7 @@
 {
 	unsigned long ssp_clk = clk_get_rate(ssp->clk);
 
-	if (ssp->type == PXA25x_SSP)
+	if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
 		return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
 	else
 		return ((ssp_clk / rate - 1) & 0xfff) << 8;
@@ -1088,7 +1147,7 @@
 
 		/* Clear status  */
 		cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
-		write_SSSR(drv_data->clear_sr, reg);
+		write_SSSR_CS(drv_data, drv_data->clear_sr);
 	}
 
 	/* see if we need to reload the config registers */
@@ -1098,7 +1157,7 @@
 
 		/* stop the SSP, and update the other bits */
 		write_SSCR0(cr0 & ~SSCR0_SSE, reg);
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(chip->timeout, reg);
 		/* first set CR1 without interrupt and service enables */
 		write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
@@ -1106,7 +1165,7 @@
 		write_SSCR0(cr0, reg);
 
 	} else {
-		if (drv_data->ssp_type != PXA25x_SSP)
+		if (!pxa25x_ssp_comp(drv_data))
 			write_SSTO(chip->timeout, reg);
 	}
 
@@ -1233,14 +1292,13 @@
 	uint tx_thres = TX_THRESH_DFLT;
 	uint rx_thres = RX_THRESH_DFLT;
 
-	if (drv_data->ssp_type != PXA25x_SSP
+	if (!pxa25x_ssp_comp(drv_data)
 		&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
 		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
 				"b/w not 4-32 for type non-PXA25x_SSP\n",
 				drv_data->ssp_type, spi->bits_per_word);
 		return -EINVAL;
-	}
-	else if (drv_data->ssp_type == PXA25x_SSP
+	} else if (pxa25x_ssp_comp(drv_data)
 			&& (spi->bits_per_word < 4
 				|| spi->bits_per_word > 16)) {
 		dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
@@ -1259,7 +1317,17 @@
 			return -ENOMEM;
 		}
 
-		chip->gpio_cs = -1;
+		if (drv_data->ssp_type == CE4100_SSP) {
+			if (spi->chip_select > 4) {
+				dev_err(&spi->dev, "failed setup: "
+				"cs number must not be > 4.\n");
+				kfree(chip);
+				return -EINVAL;
+			}
+
+			chip->frm = spi->chip_select;
+		} else
+			chip->gpio_cs = -1;
 		chip->enable_dma = 0;
 		chip->timeout = TIMOUT_DFLT;
 		chip->dma_burst_size = drv_data->master_info->enable_dma ?
@@ -1315,7 +1383,7 @@
 			| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
 
 	/* NOTE:  PXA25x_SSP _could_ use external clocking ... */
-	if (drv_data->ssp_type != PXA25x_SSP)
+	if (!pxa25x_ssp_comp(drv_data))
 		dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
 			clk_get_rate(ssp->clk)
 				/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
@@ -1350,23 +1418,27 @@
 
 	spi_set_ctldata(spi, chip);
 
+	if (drv_data->ssp_type == CE4100_SSP)
+		return 0;
+
 	return setup_cs(spi, chip, chip_info);
 }
 
 static void cleanup(struct spi_device *spi)
 {
 	struct chip_data *chip = spi_get_ctldata(spi);
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
 
 	if (!chip)
 		return;
 
-	if (gpio_is_valid(chip->gpio_cs))
+	if (drv_data->ssp_type != CE4100_SSP && gpio_is_valid(chip->gpio_cs))
 		gpio_free(chip->gpio_cs);
 
 	kfree(chip);
 }
 
-static int __init init_queue(struct driver_data *drv_data)
+static int __devinit init_queue(struct driver_data *drv_data)
 {
 	INIT_LIST_HEAD(&drv_data->queue);
 	spin_lock_init(&drv_data->lock);
@@ -1454,7 +1526,7 @@
 	return 0;
 }
 
-static int __init pxa2xx_spi_probe(struct platform_device *pdev)
+static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct pxa2xx_spi_master *platform_info;
@@ -1484,6 +1556,10 @@
 	drv_data->pdev = pdev;
 	drv_data->ssp = ssp;
 
+	master->dev.parent = &pdev->dev;
+#ifdef CONFIG_OF
+	master->dev.of_node = pdev->dev.of_node;
+#endif
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
@@ -1500,7 +1576,7 @@
 
 	drv_data->ioaddr = ssp->mmio_base;
 	drv_data->ssdr_physical = ssp->phys_base + SSDR;
-	if (ssp->type == PXA25x_SSP) {
+	if (pxa25x_ssp_comp(drv_data)) {
 		drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE;
 		drv_data->dma_cr1 = 0;
 		drv_data->clear_sr = SSSR_ROR;
@@ -1512,7 +1588,8 @@
 		drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
 	}
 
-	status = request_irq(ssp->irq, ssp_int, 0, dev_name(dev), drv_data);
+	status = request_irq(ssp->irq, ssp_int, IRQF_SHARED, dev_name(dev),
+			drv_data);
 	if (status < 0) {
 		dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
 		goto out_error_master_alloc;
@@ -1561,7 +1638,7 @@
 			| SSCR0_Motorola
 			| SSCR0_DataSize(8),
 			drv_data->ioaddr);
-	if (drv_data->ssp_type != PXA25x_SSP)
+	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, drv_data->ioaddr);
 	write_SSPSP(0, drv_data->ioaddr);
 
@@ -1723,13 +1800,14 @@
 		.pm	= &pxa2xx_spi_pm_ops,
 #endif
 	},
+	.probe = pxa2xx_spi_probe,
 	.remove = pxa2xx_spi_remove,
 	.shutdown = pxa2xx_spi_shutdown,
 };
 
 static int __init pxa2xx_spi_init(void)
 {
-	return platform_driver_probe(&driver, pxa2xx_spi_probe);
+	return platform_driver_register(&driver);
 }
 subsys_initcall(pxa2xx_spi_init);
 
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c
new file mode 100644
index 0000000..351d8a375
--- /dev/null
+++ b/drivers/spi/pxa2xx_spi_pci.c
@@ -0,0 +1,201 @@
+/*
+ * CE4100's SPI device is more or less the same one as found on PXA
+ *
+ */
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/spi/pxa2xx_spi.h>
+
+struct awesome_struct {
+	struct ssp_device ssp;
+	struct platform_device spi_pdev;
+	struct pxa2xx_spi_master spi_pdata;
+};
+
+static DEFINE_MUTEX(ssp_lock);
+static LIST_HEAD(ssp_list);
+
+struct ssp_device *pxa_ssp_request(int port, const char *label)
+{
+	struct ssp_device *ssp = NULL;
+
+	mutex_lock(&ssp_lock);
+
+	list_for_each_entry(ssp, &ssp_list, node) {
+		if (ssp->port_id == port && ssp->use_count == 0) {
+			ssp->use_count++;
+			ssp->label = label;
+			break;
+		}
+	}
+
+	mutex_unlock(&ssp_lock);
+
+	if (&ssp->node == &ssp_list)
+		return NULL;
+
+	return ssp;
+}
+EXPORT_SYMBOL_GPL(pxa_ssp_request);
+
+void pxa_ssp_free(struct ssp_device *ssp)
+{
+	mutex_lock(&ssp_lock);
+	if (ssp->use_count) {
+		ssp->use_count--;
+		ssp->label = NULL;
+	} else
+		dev_err(&ssp->pdev->dev, "device already free\n");
+	mutex_unlock(&ssp_lock);
+}
+EXPORT_SYMBOL_GPL(pxa_ssp_free);
+
+static void plat_dev_release(struct device *dev)
+{
+	struct awesome_struct *as = container_of(dev,
+			struct awesome_struct, spi_pdev.dev);
+
+	of_device_node_put(&as->spi_pdev.dev);
+}
+
+static int __devinit ce4100_spi_probe(struct pci_dev *dev,
+		const struct pci_device_id *ent)
+{
+	int ret;
+	resource_size_t phys_beg;
+	resource_size_t phys_len;
+	struct awesome_struct *spi_info;
+	struct platform_device *pdev;
+	struct pxa2xx_spi_master *spi_pdata;
+	struct ssp_device *ssp;
+
+	ret = pci_enable_device(dev);
+	if (ret)
+		return ret;
+
+	phys_beg = pci_resource_start(dev, 0);
+	phys_len = pci_resource_len(dev, 0);
+
+	if (!request_mem_region(phys_beg, phys_len,
+				"CE4100 SPI")) {
+		dev_err(&dev->dev, "Can't request register space.\n");
+		ret = -EBUSY;
+		return ret;
+	}
+
+	spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
+	if (!spi_info) {
+		ret = -ENOMEM;
+		goto err_kz;
+	}
+	ssp = &spi_info->ssp;
+	pdev = &spi_info->spi_pdev;
+	spi_pdata =  &spi_info->spi_pdata;
+
+	pdev->name = "pxa2xx-spi";
+	pdev->id = dev->devfn;
+	pdev->dev.parent = &dev->dev;
+	pdev->dev.platform_data = &spi_info->spi_pdata;
+
+#ifdef CONFIG_OF
+	pdev->dev.of_node = dev->dev.of_node;
+#endif
+	pdev->dev.release = plat_dev_release;
+
+	spi_pdata->num_chipselect = dev->devfn;
+
+	ssp->phys_base = pci_resource_start(dev, 0);
+	ssp->mmio_base = ioremap(phys_beg, phys_len);
+	if (!ssp->mmio_base) {
+		dev_err(&pdev->dev, "failed to ioremap() registers\n");
+		ret = -EIO;
+		goto err_remap;
+	}
+	ssp->irq = dev->irq;
+	ssp->port_id = pdev->id;
+	ssp->type = PXA25x_SSP;
+
+	mutex_lock(&ssp_lock);
+	list_add(&ssp->node, &ssp_list);
+	mutex_unlock(&ssp_lock);
+
+	pci_set_drvdata(dev, spi_info);
+
+	ret = platform_device_register(pdev);
+	if (ret)
+		goto err_dev_add;
+
+	return ret;
+
+err_dev_add:
+	pci_set_drvdata(dev, NULL);
+	mutex_lock(&ssp_lock);
+	list_del(&ssp->node);
+	mutex_unlock(&ssp_lock);
+	iounmap(ssp->mmio_base);
+
+err_remap:
+	kfree(spi_info);
+
+err_kz:
+	release_mem_region(phys_beg, phys_len);
+
+	return ret;
+}
+
+static void __devexit ce4100_spi_remove(struct pci_dev *dev)
+{
+	struct awesome_struct *spi_info;
+	struct platform_device *pdev;
+	struct ssp_device *ssp;
+
+	spi_info = pci_get_drvdata(dev);
+
+	ssp = &spi_info->ssp;
+	pdev = &spi_info->spi_pdev;
+
+	platform_device_unregister(pdev);
+
+	iounmap(ssp->mmio_base);
+	release_mem_region(pci_resource_start(dev, 0),
+			pci_resource_len(dev, 0));
+
+	mutex_lock(&ssp_lock);
+	list_del(&ssp->node);
+	mutex_unlock(&ssp_lock);
+
+	pci_set_drvdata(dev, NULL);
+	pci_disable_device(dev);
+	kfree(spi_info);
+}
+
+static struct pci_device_id ce4100_spi_devices[] __devinitdata = {
+
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
+
+static struct pci_driver ce4100_spi_driver = {
+	.name           = "ce4100_spi",
+	.id_table       = ce4100_spi_devices,
+	.probe          = ce4100_spi_probe,
+	.remove         = __devexit_p(ce4100_spi_remove),
+};
+
+static int __init ce4100_spi_init(void)
+{
+	return pci_register_driver(&ce4100_spi_driver);
+}
+module_init(ce4100_spi_init);
+
+static void __exit ce4100_spi_exit(void)
+{
+	pci_unregister_driver(&ce4100_spi_driver);
+}
+module_exit(ce4100_spi_exit);
+
+MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 55a38e2..9469564 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -66,7 +66,6 @@
 	SPI_IMX_VER_0_5,
 	SPI_IMX_VER_0_7,
 	SPI_IMX_VER_2_3,
-	SPI_IMX_VER_AUTODETECT,
 };
 
 struct spi_imx_data;
@@ -720,9 +719,6 @@
 
 static struct platform_device_id spi_imx_devtype[] = {
 	{
-		.name = DRIVER_NAME,
-		.driver_data = SPI_IMX_VER_AUTODETECT,
-	}, {
 		.name = "imx1-cspi",
 		.driver_data = SPI_IMX_VER_IMX1,
 	}, {
@@ -802,30 +798,8 @@
 
 	init_completion(&spi_imx->xfer_done);
 
-	if (pdev->id_entry->driver_data == SPI_IMX_VER_AUTODETECT) {
-		if (cpu_is_mx25() || cpu_is_mx35())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_0_7];
-		else if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_0_4];
-		else if (cpu_is_mx27() || cpu_is_mx21())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_0_0];
-		else if (cpu_is_mx1())
-			spi_imx->devtype_data =
-				spi_imx_devtype_data[SPI_IMX_VER_IMX1];
-		else
-			BUG();
-	} else
-		spi_imx->devtype_data =
-			spi_imx_devtype_data[pdev->id_entry->driver_data];
-
-	if (!spi_imx->devtype_data.intctrl) {
-		dev_err(&pdev->dev, "no support for this device compiled in\n");
-		ret = -ENODEV;
-		goto out_gpio_free;
-	}
+	spi_imx->devtype_data =
+		spi_imx_devtype_data[pdev->id_entry->driver_data];
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -847,7 +821,7 @@
 	}
 
 	spi_imx->irq = platform_get_irq(pdev, 0);
-	if (spi_imx->irq <= 0) {
+	if (spi_imx->irq < 0) {
 		ret = -EINVAL;
 		goto out_iounmap;
 	}
diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi_nuc900.c
index dff63be..d5be18b 100644
--- a/drivers/spi/spi_nuc900.c
+++ b/drivers/spi/spi_nuc900.c
@@ -449,7 +449,7 @@
 	release_mem_region(hw->res->start, resource_size(hw->res));
 	kfree(hw->ioarea);
 err_pdata:
-	spi_master_put(hw->master);;
+	spi_master_put(hw->master);
 
 err_nomem:
 	return err;
diff --git a/drivers/spi/spi_topcliff_pch.c b/drivers/spi/spi_topcliff_pch.c
index 58e187f..79e48d4 100644
--- a/drivers/spi/spi_topcliff_pch.c
+++ b/drivers/spi/spi_topcliff_pch.c
@@ -267,7 +267,7 @@
 	if (reg_spsr_val & SPSR_FI_BIT) {
 		/* disable FI & RFI interrupts */
 		pch_spi_setclr_reg(data->master, PCH_SPCR, 0,
-				   SPCR_FIE_BIT | SPCR_TFIE_BIT);
+				   SPCR_FIE_BIT | SPCR_RFIE_BIT);
 
 		/* transfer is completed;inform pch_spi_process_messages */
 		data->transfer_complete = true;
@@ -677,15 +677,15 @@
 {
 	/* enable interrupts */
 	if ((data->bpw_len) > PCH_MAX_FIFO_DEPTH) {
-		/* set receive threhold to PCH_RX_THOLD */
+		/* set receive threshold to PCH_RX_THOLD */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   PCH_RX_THOLD << SPCR_TFIC_FIELD,
-				   ~MASK_TFIC_SPCR_BITS);
+				   PCH_RX_THOLD << SPCR_RFIC_FIELD,
+				   ~MASK_RFIC_SPCR_BITS);
 		/* enable FI and RFI interrupts */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
-				   SPCR_RFIE_BIT | SPCR_TFIE_BIT, 0);
+				   SPCR_RFIE_BIT | SPCR_FIE_BIT, 0);
 	} else {
-		/* set receive threhold to maximum */
+		/* set receive threshold to maximum */
 		pch_spi_setclr_reg(data->master, PCH_SPCR,
 				   PCH_RX_THOLD_MAX << SPCR_TFIC_FIELD,
 				   ~MASK_TFIC_SPCR_BITS);
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 80f2db5..7adaef6 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -1,26 +1,27 @@
 /*
- * xilinx_spi.c
- *
  * Xilinx SPI controller driver (master mode only)
  *
  * Author: MontaVista Software, Inc.
  *	source@mvista.com
  *
- * 2002-2007 (c) MontaVista Software, Inc.  This file is licensed under the
- * terms of the GNU General Public License version 2.  This program is licensed
- * "as is" without any warranty of any kind, whether express or implied.
+ * Copyright (c) 2010 Secret Lab Technologies, Ltd.
+ * Copyright (c) 2009 Intel Corporation
+ * 2002-2007 (c) MontaVista Software, Inc.
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-
+#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
-#include <linux/io.h>
-
-#include "xilinx_spi.h"
 #include <linux/spi/xilinx_spi.h>
+#include <linux/io.h>
 
 #define XILINX_SPI_NAME "xilinx_spi"
 
@@ -350,19 +351,22 @@
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id xilinx_spi_of_match[] = {
+	{ .compatible = "xlnx,xps-spi-2.00.a", },
+	{ .compatible = "xlnx,xps-spi-2.00.b", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
+#endif
+
 struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-	u32 irq, s16 bus_num)
+	u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
 {
 	struct spi_master *master;
 	struct xilinx_spi *xspi;
-	struct xspi_platform_data *pdata = dev->platform_data;
 	int ret;
 
-	if (!pdata) {
-		dev_err(dev, "No platform data attached\n");
-		return NULL;
-	}
-
 	master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
 	if (!master)
 		return NULL;
@@ -389,21 +393,21 @@
 	}
 
 	master->bus_num = bus_num;
-	master->num_chipselect = pdata->num_chipselect;
+	master->num_chipselect = num_cs;
 #ifdef CONFIG_OF
 	master->dev.of_node = dev->of_node;
 #endif
 
 	xspi->mem = *mem;
 	xspi->irq = irq;
-	if (pdata->little_endian) {
+	if (little_endian) {
 		xspi->read_fn = xspi_read32;
 		xspi->write_fn = xspi_write32;
 	} else {
 		xspi->read_fn = xspi_read32_be;
 		xspi->write_fn = xspi_write32_be;
 	}
-	xspi->bits_per_word = pdata->bits_per_word;
+	xspi->bits_per_word = bits_per_word;
 	if (xspi->bits_per_word == 8) {
 		xspi->tx_fn = xspi_tx8;
 		xspi->rx_fn = xspi_rx8;
@@ -462,6 +466,97 @@
 }
 EXPORT_SYMBOL(xilinx_spi_deinit);
 
+static int __devinit xilinx_spi_probe(struct platform_device *dev)
+{
+	struct xspi_platform_data *pdata;
+	struct resource *r;
+	int irq, num_cs = 0, little_endian = 0, bits_per_word = 8;
+	struct spi_master *master;
+	u8 i;
+
+	pdata = dev->dev.platform_data;
+	if (pdata) {
+		num_cs = pdata->num_chipselect;
+		little_endian = pdata->little_endian;
+		bits_per_word = pdata->bits_per_word;
+	}
+
+#ifdef CONFIG_OF
+	if (dev->dev.of_node) {
+		const __be32 *prop;
+		int len;
+
+		/* number of slave select bits is required */
+		prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits",
+				       &len);
+		if (prop && len >= sizeof(*prop))
+			num_cs = __be32_to_cpup(prop);
+	}
+#endif
+
+	if (!num_cs) {
+		dev_err(&dev->dev, "Missing slave select configuration data\n");
+		return -EINVAL;
+	}
+
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0)
+		return -ENXIO;
+
+	master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs,
+				 little_endian, bits_per_word);
+	if (!master)
+		return -ENODEV;
+
+	if (pdata) {
+		for (i = 0; i < pdata->num_devices; i++)
+			spi_new_device(master, pdata->devices + i);
+	}
+
+	platform_set_drvdata(dev, master);
+	return 0;
+}
+
+static int __devexit xilinx_spi_remove(struct platform_device *dev)
+{
+	xilinx_spi_deinit(platform_get_drvdata(dev));
+	platform_set_drvdata(dev, 0);
+
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:" XILINX_SPI_NAME);
+
+static struct platform_driver xilinx_spi_driver = {
+	.probe = xilinx_spi_probe,
+	.remove = __devexit_p(xilinx_spi_remove),
+	.driver = {
+		.name = XILINX_SPI_NAME,
+		.owner = THIS_MODULE,
+#ifdef CONFIG_OF
+		.of_match_table = xilinx_spi_of_match,
+#endif
+	},
+};
+
+static int __init xilinx_spi_pltfm_init(void)
+{
+	return platform_driver_register(&xilinx_spi_driver);
+}
+module_init(xilinx_spi_pltfm_init);
+
+static void __exit xilinx_spi_pltfm_exit(void)
+{
+	platform_driver_unregister(&xilinx_spi_driver);
+}
+module_exit(xilinx_spi_pltfm_exit);
+
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
 MODULE_DESCRIPTION("Xilinx SPI driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h
deleted file mode 100644
index d211acc..0000000
--- a/drivers/spi/xilinx_spi.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Xilinx SPI device driver API and platform data header file
- *
- * Copyright (c) 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 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.
- */
-
-#ifndef _XILINX_SPI_H_
-#define _XILINX_SPI_H_
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-
-#define XILINX_SPI_NAME "xilinx_spi"
-
-struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-	u32 irq, s16 bus_num);
-
-void xilinx_spi_deinit(struct spi_master *master);
-#endif
diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c
deleted file mode 100644
index b66c2db..0000000
--- a/drivers/spi/xilinx_spi_of.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Xilinx SPI OF device driver
- *
- * Copyright (c) 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 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:
- * Xilinx SPI devices as OF devices
- *
- * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
-#include <linux/of_spi.h>
-
-#include <linux/spi/xilinx_spi.h>
-#include "xilinx_spi.h"
-
-
-static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev,
-	const struct of_device_id *match)
-{
-	struct spi_master *master;
-	struct xspi_platform_data *pdata;
-	struct resource r_mem;
-	struct resource r_irq;
-	int rc = 0;
-	const u32 *prop;
-	int len;
-
-	rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem);
-	if (rc) {
-		dev_warn(&ofdev->dev, "invalid address\n");
-		return rc;
-	}
-
-	rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq);
-	if (rc == NO_IRQ) {
-		dev_warn(&ofdev->dev, "no IRQ found\n");
-		return -ENODEV;
-	}
-
-	ofdev->dev.platform_data =
-		kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL);
-	pdata = ofdev->dev.platform_data;
-	if (!pdata)
-		return -ENOMEM;
-
-	/* number of slave select bits is required */
-	prop = of_get_property(ofdev->dev.of_node, "xlnx,num-ss-bits", &len);
-	if (!prop || len < sizeof(*prop)) {
-		dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
-		return -EINVAL;
-	}
-	pdata->num_chipselect = *prop;
-	pdata->bits_per_word = 8;
-	master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1);
-	if (!master)
-		return -ENODEV;
-
-	dev_set_drvdata(&ofdev->dev, master);
-
-	return 0;
-}
-
-static int __devexit xilinx_spi_remove(struct platform_device *ofdev)
-{
-	xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev));
-	dev_set_drvdata(&ofdev->dev, 0);
-	kfree(ofdev->dev.platform_data);
-	ofdev->dev.platform_data = NULL;
-	return 0;
-}
-
-static int __exit xilinx_spi_of_remove(struct platform_device *op)
-{
-	return xilinx_spi_remove(op);
-}
-
-static const struct of_device_id xilinx_spi_of_match[] = {
-	{ .compatible = "xlnx,xps-spi-2.00.a", },
-	{ .compatible = "xlnx,xps-spi-2.00.b", },
-	{}
-};
-
-MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-
-static struct of_platform_driver xilinx_spi_of_driver = {
-	.probe = xilinx_spi_of_probe,
-	.remove = __exit_p(xilinx_spi_of_remove),
-	.driver = {
-		.name = "xilinx-xps-spi",
-		.owner = THIS_MODULE,
-		.of_match_table = xilinx_spi_of_match,
-	},
-};
-
-static int __init xilinx_spi_of_init(void)
-{
-	return of_register_platform_driver(&xilinx_spi_of_driver);
-}
-module_init(xilinx_spi_of_init);
-
-static void __exit xilinx_spi_of_exit(void)
-{
-	of_unregister_platform_driver(&xilinx_spi_of_driver);
-}
-module_exit(xilinx_spi_of_exit);
-
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_DESCRIPTION("Xilinx SPI platform driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/xilinx_spi_pltfm.c b/drivers/spi/xilinx_spi_pltfm.c
deleted file mode 100644
index 24debac..0000000
--- a/drivers/spi/xilinx_spi_pltfm.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Support for Xilinx SPI platform devices
- * Copyright (c) 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 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:
- * Xilinx SPI devices as platform devices
- *
- * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/spi/xilinx_spi.h>
-
-#include "xilinx_spi.h"
-
-static int __devinit xilinx_spi_probe(struct platform_device *dev)
-{
-	struct xspi_platform_data *pdata;
-	struct resource *r;
-	int irq;
-	struct spi_master *master;
-	u8 i;
-
-	pdata = dev->dev.platform_data;
-	if (!pdata)
-		return -ENODEV;
-
-	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -ENODEV;
-
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0)
-		return -ENXIO;
-
-	master = xilinx_spi_init(&dev->dev, r, irq, dev->id);
-	if (!master)
-		return -ENODEV;
-
-	for (i = 0; i < pdata->num_devices; i++)
-		spi_new_device(master, pdata->devices + i);
-
-	platform_set_drvdata(dev, master);
-	return 0;
-}
-
-static int __devexit xilinx_spi_remove(struct platform_device *dev)
-{
-	xilinx_spi_deinit(platform_get_drvdata(dev));
-	platform_set_drvdata(dev, 0);
-
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:" XILINX_SPI_NAME);
-
-static struct platform_driver xilinx_spi_driver = {
-	.probe	= xilinx_spi_probe,
-	.remove	= __devexit_p(xilinx_spi_remove),
-	.driver = {
-		.name = XILINX_SPI_NAME,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init xilinx_spi_pltfm_init(void)
-{
-	return platform_driver_register(&xilinx_spi_driver);
-}
-module_init(xilinx_spi_pltfm_init);
-
-static void __exit xilinx_spi_pltfm_exit(void)
-{
-	platform_driver_unregister(&xilinx_spi_driver);
-}
-module_exit(xilinx_spi_pltfm_exit);
-
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_DESCRIPTION("Xilinx SPI platform driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 5eafdf4..bdc632b6 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -51,9 +51,11 @@
 
 source "drivers/staging/tm6000/Kconfig"
 
-source "drivers/staging/cpia/Kconfig"
+source "drivers/staging/dabusb/Kconfig"
 
-source "drivers/staging/stradis/Kconfig"
+source "drivers/staging/se401/Kconfig"
+
+source "drivers/staging/usbvideo/Kconfig"
 
 source "drivers/staging/usbip/Kconfig"
 
@@ -111,8 +113,6 @@
 
 source "drivers/staging/vt6656/Kconfig"
 
-source "drivers/staging/udlfb/Kconfig"
-
 source "drivers/staging/hv/Kconfig"
 
 source "drivers/staging/vme/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index a97a955..3eda5c7 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -8,8 +8,9 @@
 obj-$(CONFIG_VIDEO_GO7007)	+= go7007/
 obj-$(CONFIG_VIDEO_CX25821)	+= cx25821/
 obj-$(CONFIG_VIDEO_TM6000)	+= tm6000/
-obj-$(CONFIG_VIDEO_CPIA)	+= cpia/
-obj-$(CONFIG_VIDEO_STRADIS)	+= stradis/
+obj-$(CONFIG_USB_DABUSB)        += dabusb/
+obj-$(CONFIG_USB_VICAM)         += usbvideo/
+obj-$(CONFIG_USB_SE401)         += se401/
 obj-$(CONFIG_LIRC_STAGING)	+= lirc/
 obj-$(CONFIG_USB_IP_COMMON)	+= usbip/
 obj-$(CONFIG_W35UND)		+= winbond/
@@ -38,7 +39,6 @@
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_VT6655)		+= vt6655/
 obj-$(CONFIG_VT6656)		+= vt6656/
-obj-$(CONFIG_FB_UDL)		+= udlfb/
 obj-$(CONFIG_HYPERV)		+= hv/
 obj-$(CONFIG_VME_BUS)		+= vme/
 obj-$(CONFIG_MRST_RAR_HANDLER)	+= memrar/
diff --git a/drivers/staging/autofs/root.c b/drivers/staging/autofs/root.c
index 0fdec4b..bf0e975 100644
--- a/drivers/staging/autofs/root.c
+++ b/drivers/staging/autofs/root.c
@@ -154,13 +154,16 @@
  * yet completely filled in, and revalidate has to delay such
  * lookups..
  */
-static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd)
+static int autofs_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode * dir;
 	struct autofs_sb_info *sbi;
 	struct autofs_dir_ent *ent;
 	int res;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
 	lock_kernel();
 	dir = dentry->d_parent->d_inode;
 	sbi = autofs_sbi(dir->i_sb);
@@ -237,7 +240,7 @@
 	 *
 	 * We need to do this before we release the directory semaphore.
 	 */
-	dentry->d_op = &autofs_dentry_operations;
+	d_set_d_op(dentry, &autofs_dentry_operations);
 	dentry->d_flags |= DCACHE_AUTOFS_PENDING;
 	d_add(dentry, NULL);
 
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index 824f9a4..e97ad99 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -277,7 +277,7 @@
 		if(psAdapter->bDoSuspend)
 		{
 #ifdef CONFIG_PM
-			udev->autosuspend_delay = 0;
+			pm_runtime_set_autosuspend_delay(&udev->dev, 0);
 			intf->needs_remote_wakeup = 1;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
  			udev->autosuspend_disabled = 0;
diff --git a/drivers/staging/cpia/Kconfig b/drivers/staging/cpia/Kconfig
deleted file mode 100644
index 205d247..0000000
--- a/drivers/staging/cpia/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
-config VIDEO_CPIA
-	tristate "CPiA Video For Linux (DEPRECATED)"
-	depends on VIDEO_V4L1
-	default n
-	---help---
-	  This driver is DEPRECATED please use the gspca cpia1 module
-	  instead. Note that you need atleast version 0.6.4 of libv4l for
-	  the cpia1 gspca module.
-
-	  This is the video4linux driver for cameras based on Vision's CPiA
-	  (Colour Processor Interface ASIC), such as the Creative Labs Video
-	  Blaster Webcam II. If you have one of these cameras, say Y here
-	  and select parallel port and/or USB lowlevel support below,
-	  otherwise say N. This will not work with the Creative Webcam III.
-
-	  Please read <file:Documentation/video4linux/README.cpia> for more
-	  information.
-
-	  This driver is also available as a module (cpia).
-
-config VIDEO_CPIA_PP
-	tristate "CPiA Parallel Port Lowlevel Support"
-	depends on PARPORT_1284 && VIDEO_CPIA && PARPORT
-	help
-	  This is the lowlevel parallel port support for cameras based on
-	  Vision's CPiA (Colour Processor Interface ASIC), such as the
-	  Creative Webcam II. If you have the parallel port version of one
-	  of these cameras, say Y here, otherwise say N. It is also available
-	  as a module (cpia_pp).
-
-config VIDEO_CPIA_USB
-	tristate "CPiA USB Lowlevel Support"
-	depends on VIDEO_CPIA && USB
-	help
-	  This is the lowlevel USB support for cameras based on Vision's CPiA
-	  (Colour Processor Interface ASIC), such as the Creative Webcam II.
-	  If you have the USB version of one of these cameras, say Y here,
-	  otherwise say N. This will not work with the Creative Webcam III.
-	  It is also available as a module (cpia_usb).
diff --git a/drivers/staging/cpia/Makefile b/drivers/staging/cpia/Makefile
deleted file mode 100644
index 89e52f1..0000000
--- a/drivers/staging/cpia/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_VIDEO_CPIA) += cpia.o
-obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
-obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
-
-EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/staging/cpia/TODO b/drivers/staging/cpia/TODO
deleted file mode 100644
index ccb1c07..0000000
--- a/drivers/staging/cpia/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-This is an obsolete driver for some cpia-based webcams that use the parallel port.
-We couldn't find anyone with this hardware in order to port it to use V4L2.
-
-Also, parallel-port webcams are obsolete nowadays.
-
-If nobody take care on it, the driver will be removed for 2.6.38.
-
-Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/staging/cpia/cpia.c b/drivers/staging/cpia/cpia.c
deleted file mode 100644
index 0e740b8..0000000
--- a/drivers/staging/cpia/cpia.c
+++ /dev/null
@@ -1,4028 +0,0 @@
-/*
- * cpia CPiA driver
- *
- * Supports CPiA based Video Camera's.
- *
- * (C) Copyright 1999-2000 Peter Pregler
- * (C) Copyright 1999-2000 Scott J. Bertin
- * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
- * (C) Copyright 2000 STMicroelectronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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 _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_  1 */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/ctype.h>
-#include <linux/pagemap.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <linux/mutex.h>
-
-#include "cpia.h"
-
-static int video_nr = -1;
-
-#ifdef MODULE
-module_param(video_nr, int, 0);
-MODULE_AUTHOR("Scott J. Bertin <sbertin@securenym.net> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <johannes@erdfelt.com>");
-MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("video");
-#endif
-
-static unsigned short colorspace_conv;
-module_param(colorspace_conv, ushort, 0444);
-MODULE_PARM_DESC(colorspace_conv,
-		 " Colorspace conversion:"
-		 "\n  0 = disable, 1 = enable"
-		 "\n  Default value is 0"
-		 );
-
-#define ABOUT "V4L-Driver for Vision CPiA based cameras"
-
-#define CPIA_MODULE_CPIA			(0<<5)
-#define CPIA_MODULE_SYSTEM			(1<<5)
-#define CPIA_MODULE_VP_CTRL			(5<<5)
-#define CPIA_MODULE_CAPTURE			(6<<5)
-#define CPIA_MODULE_DEBUG			(7<<5)
-
-#define INPUT (DATA_IN << 8)
-#define OUTPUT (DATA_OUT << 8)
-
-#define CPIA_COMMAND_GetCPIAVersion	(INPUT | CPIA_MODULE_CPIA | 1)
-#define CPIA_COMMAND_GetPnPID		(INPUT | CPIA_MODULE_CPIA | 2)
-#define CPIA_COMMAND_GetCameraStatus	(INPUT | CPIA_MODULE_CPIA | 3)
-#define CPIA_COMMAND_GotoHiPower	(OUTPUT | CPIA_MODULE_CPIA | 4)
-#define CPIA_COMMAND_GotoLoPower	(OUTPUT | CPIA_MODULE_CPIA | 5)
-#define CPIA_COMMAND_GotoSuspend	(OUTPUT | CPIA_MODULE_CPIA | 7)
-#define CPIA_COMMAND_GotoPassThrough	(OUTPUT | CPIA_MODULE_CPIA | 8)
-#define CPIA_COMMAND_ModifyCameraStatus	(OUTPUT | CPIA_MODULE_CPIA | 10)
-
-#define CPIA_COMMAND_ReadVCRegs		(INPUT | CPIA_MODULE_SYSTEM | 1)
-#define CPIA_COMMAND_WriteVCReg		(OUTPUT | CPIA_MODULE_SYSTEM | 2)
-#define CPIA_COMMAND_ReadMCPorts	(INPUT | CPIA_MODULE_SYSTEM | 3)
-#define CPIA_COMMAND_WriteMCPort	(OUTPUT | CPIA_MODULE_SYSTEM | 4)
-#define CPIA_COMMAND_SetBaudRate	(OUTPUT | CPIA_MODULE_SYSTEM | 5)
-#define CPIA_COMMAND_SetECPTiming	(OUTPUT | CPIA_MODULE_SYSTEM | 6)
-#define CPIA_COMMAND_ReadIDATA		(INPUT | CPIA_MODULE_SYSTEM | 7)
-#define CPIA_COMMAND_WriteIDATA		(OUTPUT | CPIA_MODULE_SYSTEM | 8)
-#define CPIA_COMMAND_GenericCall	(OUTPUT | CPIA_MODULE_SYSTEM | 9)
-#define CPIA_COMMAND_I2CStart		(OUTPUT | CPIA_MODULE_SYSTEM | 10)
-#define CPIA_COMMAND_I2CStop		(OUTPUT | CPIA_MODULE_SYSTEM | 11)
-#define CPIA_COMMAND_I2CWrite		(OUTPUT | CPIA_MODULE_SYSTEM | 12)
-#define CPIA_COMMAND_I2CRead		(INPUT | CPIA_MODULE_SYSTEM | 13)
-
-#define CPIA_COMMAND_GetVPVersion	(INPUT | CPIA_MODULE_VP_CTRL | 1)
-#define CPIA_COMMAND_ResetFrameCounter	(INPUT | CPIA_MODULE_VP_CTRL | 2)
-#define CPIA_COMMAND_SetColourParams	(OUTPUT | CPIA_MODULE_VP_CTRL | 3)
-#define CPIA_COMMAND_SetExposure	(OUTPUT | CPIA_MODULE_VP_CTRL | 4)
-#define CPIA_COMMAND_SetColourBalance	(OUTPUT | CPIA_MODULE_VP_CTRL | 6)
-#define CPIA_COMMAND_SetSensorFPS	(OUTPUT | CPIA_MODULE_VP_CTRL | 7)
-#define CPIA_COMMAND_SetVPDefaults	(OUTPUT | CPIA_MODULE_VP_CTRL | 8)
-#define CPIA_COMMAND_SetApcor		(OUTPUT | CPIA_MODULE_VP_CTRL | 9)
-#define CPIA_COMMAND_SetFlickerCtrl	(OUTPUT | CPIA_MODULE_VP_CTRL | 10)
-#define CPIA_COMMAND_SetVLOffset	(OUTPUT | CPIA_MODULE_VP_CTRL | 11)
-#define CPIA_COMMAND_GetColourParams	(INPUT | CPIA_MODULE_VP_CTRL | 16)
-#define CPIA_COMMAND_GetColourBalance	(INPUT | CPIA_MODULE_VP_CTRL | 17)
-#define CPIA_COMMAND_GetExposure	(INPUT | CPIA_MODULE_VP_CTRL | 18)
-#define CPIA_COMMAND_SetSensorMatrix	(OUTPUT | CPIA_MODULE_VP_CTRL | 19)
-#define CPIA_COMMAND_ColourBars		(OUTPUT | CPIA_MODULE_VP_CTRL | 25)
-#define CPIA_COMMAND_ReadVPRegs		(INPUT | CPIA_MODULE_VP_CTRL | 30)
-#define CPIA_COMMAND_WriteVPReg		(OUTPUT | CPIA_MODULE_VP_CTRL | 31)
-
-#define CPIA_COMMAND_GrabFrame		(OUTPUT | CPIA_MODULE_CAPTURE | 1)
-#define CPIA_COMMAND_UploadFrame	(OUTPUT | CPIA_MODULE_CAPTURE | 2)
-#define CPIA_COMMAND_SetGrabMode	(OUTPUT | CPIA_MODULE_CAPTURE | 3)
-#define CPIA_COMMAND_InitStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 4)
-#define CPIA_COMMAND_FiniStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 5)
-#define CPIA_COMMAND_StartStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 6)
-#define CPIA_COMMAND_EndStreamCap	(OUTPUT | CPIA_MODULE_CAPTURE | 7)
-#define CPIA_COMMAND_SetFormat		(OUTPUT | CPIA_MODULE_CAPTURE | 8)
-#define CPIA_COMMAND_SetROI		(OUTPUT | CPIA_MODULE_CAPTURE | 9)
-#define CPIA_COMMAND_SetCompression	(OUTPUT | CPIA_MODULE_CAPTURE | 10)
-#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
-#define CPIA_COMMAND_SetYUVThresh	(OUTPUT | CPIA_MODULE_CAPTURE | 12)
-#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
-#define CPIA_COMMAND_DiscardFrame	(OUTPUT | CPIA_MODULE_CAPTURE | 14)
-#define CPIA_COMMAND_GrabReset		(OUTPUT | CPIA_MODULE_CAPTURE | 15)
-
-#define CPIA_COMMAND_OutputRS232	(OUTPUT | CPIA_MODULE_DEBUG | 1)
-#define CPIA_COMMAND_AbortProcess	(OUTPUT | CPIA_MODULE_DEBUG | 4)
-#define CPIA_COMMAND_SetDramPage	(OUTPUT | CPIA_MODULE_DEBUG | 5)
-#define CPIA_COMMAND_StartDramUpload	(OUTPUT | CPIA_MODULE_DEBUG | 6)
-#define CPIA_COMMAND_StartDummyDtream	(OUTPUT | CPIA_MODULE_DEBUG | 8)
-#define CPIA_COMMAND_AbortStream	(OUTPUT | CPIA_MODULE_DEBUG | 9)
-#define CPIA_COMMAND_DownloadDRAM	(OUTPUT | CPIA_MODULE_DEBUG | 10)
-#define CPIA_COMMAND_Null		(OUTPUT | CPIA_MODULE_DEBUG | 11)
-
-enum {
-	FRAME_READY,		/* Ready to grab into */
-	FRAME_GRABBING,		/* In the process of being grabbed into */
-	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
-	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
-};
-
-#define COMMAND_NONE			0x0000
-#define COMMAND_SETCOMPRESSION		0x0001
-#define COMMAND_SETCOMPRESSIONTARGET	0x0002
-#define COMMAND_SETCOLOURPARAMS		0x0004
-#define COMMAND_SETFORMAT		0x0008
-#define COMMAND_PAUSE			0x0010
-#define COMMAND_RESUME			0x0020
-#define COMMAND_SETYUVTHRESH		0x0040
-#define COMMAND_SETECPTIMING		0x0080
-#define COMMAND_SETCOMPRESSIONPARAMS	0x0100
-#define COMMAND_SETEXPOSURE		0x0200
-#define COMMAND_SETCOLOURBALANCE	0x0400
-#define COMMAND_SETSENSORFPS		0x0800
-#define COMMAND_SETAPCOR		0x1000
-#define COMMAND_SETFLICKERCTRL		0x2000
-#define COMMAND_SETVLOFFSET		0x4000
-#define COMMAND_SETLIGHTS		0x8000
-
-#define ROUND_UP_EXP_FOR_FLICKER 15
-
-/* Constants for automatic frame rate adjustment */
-#define MAX_EXP       302
-#define MAX_EXP_102   255
-#define LOW_EXP       140
-#define VERY_LOW_EXP   70
-#define TC             94
-#define	EXP_ACC_DARK   50
-#define	EXP_ACC_LIGHT  90
-#define HIGH_COMP_102 160
-#define MAX_COMP      239
-#define DARK_TIME       3
-#define LIGHT_TIME      3
-
-/* Maximum number of 10ms loops to wait for the stream to become ready */
-#define READY_TIMEOUT 100
-
-/* Developer's Guide Table 5 p 3-34
- * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
-static u8 flicker_jumps[2][2][4] =
-{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
-  { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
-};
-
-/* forward declaration of local function */
-static void reset_camera_struct(struct cam_data *cam);
-static int find_over_exposure(int brightness);
-static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
-			int on);
-
-
-/**********************************************************************
- *
- * 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);
-}
-
-/**********************************************************************
- *
- * /proc interface
- *
- **********************************************************************/
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *cpia_proc_root=NULL;
-
-static int cpia_proc_show(struct seq_file *m, void *v)
-{
-	struct cam_data *cam = m->private;
-	int tmp;
-	char tmpstr[29];
-
-	seq_printf(m, "read-only\n-----------------------\n");
-	seq_printf(m, "V4L Driver version:       %d.%d.%d\n",
-		       CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
-	seq_printf(m, "CPIA Version:             %d.%02d (%d.%d)\n",
-		       cam->params.version.firmwareVersion,
-		       cam->params.version.firmwareRevision,
-		       cam->params.version.vcVersion,
-		       cam->params.version.vcRevision);
-	seq_printf(m, "CPIA PnP-ID:              %04x:%04x:%04x\n",
-		       cam->params.pnpID.vendor, cam->params.pnpID.product,
-		       cam->params.pnpID.deviceRevision);
-	seq_printf(m, "VP-Version:               %d.%d %04x\n",
-		       cam->params.vpVersion.vpVersion,
-		       cam->params.vpVersion.vpRevision,
-		       cam->params.vpVersion.cameraHeadID);
-
-	seq_printf(m, "system_state:             %#04x\n",
-		       cam->params.status.systemState);
-	seq_printf(m, "grab_state:               %#04x\n",
-		       cam->params.status.grabState);
-	seq_printf(m, "stream_state:             %#04x\n",
-		       cam->params.status.streamState);
-	seq_printf(m, "fatal_error:              %#04x\n",
-		       cam->params.status.fatalError);
-	seq_printf(m, "cmd_error:                %#04x\n",
-		       cam->params.status.cmdError);
-	seq_printf(m, "debug_flags:              %#04x\n",
-		       cam->params.status.debugFlags);
-	seq_printf(m, "vp_status:                %#04x\n",
-		       cam->params.status.vpStatus);
-	seq_printf(m, "error_code:               %#04x\n",
-		       cam->params.status.errorCode);
-	/* QX3 specific entries */
-	if (cam->params.qx3.qx3_detected) {
-		seq_printf(m, "button:                   %4d\n",
-			       cam->params.qx3.button);
-		seq_printf(m, "cradled:                  %4d\n",
-			       cam->params.qx3.cradled);
-	}
-	seq_printf(m, "video_size:               %s\n",
-		       cam->params.format.videoSize == VIDEOSIZE_CIF ?
-		       "CIF " : "QCIF");
-	seq_printf(m, "roi:                      (%3d, %3d) to (%3d, %3d)\n",
-		       cam->params.roi.colStart*8,
-		       cam->params.roi.rowStart*4,
-		       cam->params.roi.colEnd*8,
-		       cam->params.roi.rowEnd*4);
-	seq_printf(m, "actual_fps:               %3d\n", cam->fps);
-	seq_printf(m, "transfer_rate:            %4dkB/s\n",
-		       cam->transfer_rate);
-
-	seq_printf(m, "\nread-write\n");
-	seq_printf(m, "-----------------------  current       min"
-		       "       max   default  comment\n");
-	seq_printf(m, "brightness:             %8d  %8d  %8d  %8d\n",
-		       cam->params.colourParams.brightness, 0, 100, 50);
-	if (cam->params.version.firmwareVersion == 1 &&
-	   cam->params.version.firmwareRevision == 2)
-		/* 1-02 firmware limits contrast to 80 */
-		tmp = 80;
-	else
-		tmp = 96;
-
-	seq_printf(m, "contrast:               %8d  %8d  %8d  %8d"
-		       "  steps of 8\n",
-		       cam->params.colourParams.contrast, 0, tmp, 48);
-	seq_printf(m, "saturation:             %8d  %8d  %8d  %8d\n",
-		       cam->params.colourParams.saturation, 0, 100, 50);
-	tmp = (25000+5000*cam->params.sensorFps.baserate)/
-	      (1<<cam->params.sensorFps.divisor);
-	seq_printf(m, "sensor_fps:             %4d.%03d  %8d  %8d  %8d\n",
-		       tmp/1000, tmp%1000, 3, 30, 15);
-	seq_printf(m, "stream_start_line:      %8d  %8d  %8d  %8d\n",
-		       2*cam->params.streamStartLine, 0,
-		       cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
-		       cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
-	seq_printf(m, "sub_sample:             %8s  %8s  %8s  %8s\n",
-		       cam->params.format.subSample == SUBSAMPLE_420 ?
-		       "420" : "422", "420", "422", "422");
-	seq_printf(m, "yuv_order:              %8s  %8s  %8s  %8s\n",
-		       cam->params.format.yuvOrder == YUVORDER_YUYV ?
-		       "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV");
-	seq_printf(m, "ecp_timing:             %8s  %8s  %8s  %8s\n",
-		       cam->params.ecpTiming ? "slow" : "normal", "slow",
-		       "normal", "normal");
-
-	if (cam->params.colourBalance.balanceMode == 2) {
-		sprintf(tmpstr, "auto");
-	} else {
-		sprintf(tmpstr, "manual");
-	}
-	seq_printf(m, "color_balance_mode:     %8s  %8s  %8s"
-		       "  %8s\n",  tmpstr, "manual", "auto", "auto");
-	seq_printf(m, "red_gain:               %8d  %8d  %8d  %8d\n",
-		       cam->params.colourBalance.redGain, 0, 212, 32);
-	seq_printf(m, "green_gain:             %8d  %8d  %8d  %8d\n",
-		       cam->params.colourBalance.greenGain, 0, 212, 6);
-	seq_printf(m, "blue_gain:              %8d  %8d  %8d  %8d\n",
-		       cam->params.colourBalance.blueGain, 0, 212, 92);
-
-	if (cam->params.version.firmwareVersion == 1 &&
-	   cam->params.version.firmwareRevision == 2)
-		/* 1-02 firmware limits gain to 2 */
-		sprintf(tmpstr, "%8d  %8d  %8d", 1, 2, 2);
-	else
-		sprintf(tmpstr, "%8d  %8d  %8d", 1, 8, 2);
-
-	if (cam->params.exposure.gainMode == 0)
-		seq_printf(m, "max_gain:                unknown  %28s"
-			       "  powers of 2\n", tmpstr);
-	else
-		seq_printf(m, "max_gain:               %8d  %28s"
-			       "  1,2,4 or 8 \n",
-			       1<<(cam->params.exposure.gainMode-1), tmpstr);
-
-	switch(cam->params.exposure.expMode) {
-	case 1:
-	case 3:
-		sprintf(tmpstr, "manual");
-		break;
-	case 2:
-		sprintf(tmpstr, "auto");
-		break;
-	default:
-		sprintf(tmpstr, "unknown");
-		break;
-	}
-	seq_printf(m, "exposure_mode:          %8s  %8s  %8s"
-		       "  %8s\n",  tmpstr, "manual", "auto", "auto");
-	seq_printf(m, "centre_weight:          %8s  %8s  %8s  %8s\n",
-		       (2-cam->params.exposure.centreWeight) ? "on" : "off",
-		       "off", "on", "on");
-	seq_printf(m, "gain:                   %8d  %8d  max_gain  %8d  1,2,4,8 possible\n",
-		       1<<cam->params.exposure.gain, 1, 1);
-	if (cam->params.version.firmwareVersion == 1 &&
-	   cam->params.version.firmwareRevision == 2)
-		/* 1-02 firmware limits fineExp/2 to 127 */
-		tmp = 254;
-	else
-		tmp = 510;
-
-	seq_printf(m, "fine_exp:               %8d  %8d  %8d  %8d\n",
-		       cam->params.exposure.fineExp*2, 0, tmp, 0);
-	if (cam->params.version.firmwareVersion == 1 &&
-	   cam->params.version.firmwareRevision == 2)
-		/* 1-02 firmware limits coarseExpHi to 0 */
-		tmp = MAX_EXP_102;
-	else
-		tmp = MAX_EXP;
-
-	seq_printf(m, "coarse_exp:             %8d  %8d  %8d"
-		       "  %8d\n", cam->params.exposure.coarseExpLo+
-		       256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
-	seq_printf(m, "red_comp:               %8d  %8d  %8d  %8d\n",
-		       cam->params.exposure.redComp, COMP_RED, 255, COMP_RED);
-	seq_printf(m, "green1_comp:            %8d  %8d  %8d  %8d\n",
-		       cam->params.exposure.green1Comp, COMP_GREEN1, 255,
-		       COMP_GREEN1);
-	seq_printf(m, "green2_comp:            %8d  %8d  %8d  %8d\n",
-		       cam->params.exposure.green2Comp, COMP_GREEN2, 255,
-		       COMP_GREEN2);
-	seq_printf(m, "blue_comp:              %8d  %8d  %8d  %8d\n",
-		       cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE);
-
-	seq_printf(m, "apcor_gain1:            %#8x  %#8x  %#8x  %#8x\n",
-		       cam->params.apcor.gain1, 0, 0xff, 0x1c);
-	seq_printf(m, "apcor_gain2:            %#8x  %#8x  %#8x  %#8x\n",
-		       cam->params.apcor.gain2, 0, 0xff, 0x1a);
-	seq_printf(m, "apcor_gain4:            %#8x  %#8x  %#8x  %#8x\n",
-		       cam->params.apcor.gain4, 0, 0xff, 0x2d);
-	seq_printf(m, "apcor_gain8:            %#8x  %#8x  %#8x  %#8x\n",
-		       cam->params.apcor.gain8, 0, 0xff, 0x2a);
-	seq_printf(m, "vl_offset_gain1:        %8d  %8d  %8d  %8d\n",
-		       cam->params.vlOffset.gain1, 0, 255, 24);
-	seq_printf(m, "vl_offset_gain2:        %8d  %8d  %8d  %8d\n",
-		       cam->params.vlOffset.gain2, 0, 255, 28);
-	seq_printf(m, "vl_offset_gain4:        %8d  %8d  %8d  %8d\n",
-		       cam->params.vlOffset.gain4, 0, 255, 30);
-	seq_printf(m, "vl_offset_gain8:        %8d  %8d  %8d  %8d\n",
-		       cam->params.vlOffset.gain8, 0, 255, 30);
-	seq_printf(m, "flicker_control:        %8s  %8s  %8s  %8s\n",
-		       cam->params.flickerControl.flickerMode ? "on" : "off",
-		       "off", "on", "off");
-	seq_printf(m, "mains_frequency:        %8d  %8d  %8d  %8d"
-		       " only 50/60\n",
-		       cam->mainsFreq ? 60 : 50, 50, 60, 50);
-	if(cam->params.flickerControl.allowableOverExposure < 0)
-		seq_printf(m, "allowable_overexposure: %4dauto      auto  %8d      auto\n",
-			       -cam->params.flickerControl.allowableOverExposure,
-			       255);
-	else
-		seq_printf(m, "allowable_overexposure: %8d      auto  %8d      auto\n",
-			       cam->params.flickerControl.allowableOverExposure,
-			       255);
-	seq_printf(m, "compression_mode:       ");
-	switch(cam->params.compression.mode) {
-	case CPIA_COMPRESSION_NONE:
-		seq_printf(m, "%8s", "none");
-		break;
-	case CPIA_COMPRESSION_AUTO:
-		seq_printf(m, "%8s", "auto");
-		break;
-	case CPIA_COMPRESSION_MANUAL:
-		seq_printf(m, "%8s", "manual");
-		break;
-	default:
-		seq_printf(m, "%8s", "unknown");
-		break;
-	}
-	seq_printf(m, "    none,auto,manual      auto\n");
-	seq_printf(m, "decimation_enable:      %8s  %8s  %8s  %8s\n",
-		       cam->params.compression.decimation ==
-		       DECIMATION_ENAB ? "on":"off", "off", "on",
-		       "off");
-	seq_printf(m, "compression_target:    %9s %9s %9s %9s\n",
-		       cam->params.compressionTarget.frTargeting  ==
-		       CPIA_COMPRESSION_TARGET_FRAMERATE ?
-		       "framerate":"quality",
-		       "framerate", "quality", "quality");
-	seq_printf(m, "target_framerate:       %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionTarget.targetFR, 1, 30, 15);
-	seq_printf(m, "target_quality:         %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionTarget.targetQ, 1, 64, 5);
-	seq_printf(m, "y_threshold:            %8d  %8d  %8d  %8d\n",
-		       cam->params.yuvThreshold.yThreshold, 0, 31, 6);
-	seq_printf(m, "uv_threshold:           %8d  %8d  %8d  %8d\n",
-		       cam->params.yuvThreshold.uvThreshold, 0, 31, 6);
-	seq_printf(m, "hysteresis:             %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.hysteresis, 0, 255, 3);
-	seq_printf(m, "threshold_max:          %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.threshMax, 0, 255, 11);
-	seq_printf(m, "small_step:             %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.smallStep, 0, 255, 1);
-	seq_printf(m, "large_step:             %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.largeStep, 0, 255, 3);
-	seq_printf(m, "decimation_hysteresis:  %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.decimationHysteresis,
-		       0, 255, 2);
-	seq_printf(m, "fr_diff_step_thresh:    %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.frDiffStepThresh,
-		       0, 255, 5);
-	seq_printf(m, "q_diff_step_thresh:     %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.qDiffStepThresh,
-		       0, 255, 3);
-	seq_printf(m, "decimation_thresh_mod:  %8d  %8d  %8d  %8d\n",
-		       cam->params.compressionParams.decimationThreshMod,
-		       0, 255, 2);
-	/* QX3 specific entries */
-	if (cam->params.qx3.qx3_detected) {
-		seq_printf(m, "toplight:               %8s  %8s  %8s  %8s\n",
-			       cam->params.qx3.toplight ? "on" : "off",
-			       "off", "on", "off");
-		seq_printf(m, "bottomlight:            %8s  %8s  %8s  %8s\n",
-			       cam->params.qx3.bottomlight ? "on" : "off",
-			       "off", "on", "off");
-	}
-
-	return 0;
-}
-
-static int cpia_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, cpia_proc_show, PDE(inode)->data);
-}
-
-static int match(char *checkstr, char **buffer, size_t *count,
-		 int *find_colon, int *err)
-{
-	int ret, colon_found = 1;
-	int len = strlen(checkstr);
-	ret = (len <= *count && strncmp(*buffer, checkstr, len) == 0);
-	if (ret) {
-		*buffer += len;
-		*count -= len;
-		if (*find_colon) {
-			colon_found = 0;
-			while (*count && (**buffer == ' ' || **buffer == '\t' ||
-					  (!colon_found && **buffer == ':'))) {
-				if (**buffer == ':')
-					colon_found = 1;
-				--*count;
-				++*buffer;
-			}
-			if (!*count || !colon_found)
-				*err = -EINVAL;
-			*find_colon = 0;
-		}
-	}
-	return ret;
-}
-
-static unsigned long int value(char **buffer, size_t *count, int *err)
-{
-	char *p;
-	unsigned long int ret;
-	ret = simple_strtoul(*buffer, &p, 0);
-	if (p == *buffer)
-		*err = -EINVAL;
-	else {
-		*count -= p - *buffer;
-		*buffer = p;
-	}
-	return ret;
-}
-
-static ssize_t cpia_proc_write(struct file *file, const char __user *buf,
-			       size_t count, loff_t *pos)
-{
-	struct cam_data *cam = PDE(file->f_path.dentry->d_inode)->data;
-	struct cam_params new_params;
-	char *page, *buffer;
-	int retval, find_colon;
-	int size = count;
-	unsigned long val = 0;
-	u32 command_flags = 0;
-	u8 new_mains;
-
-	/*
-	 * This code to copy from buf to page is shamelessly copied
-	 * from the comx driver
-	 */
-	if (count > PAGE_SIZE) {
-		printk(KERN_ERR "count is %zu > %d!!!\n", count, (int)PAGE_SIZE);
-		return -ENOSPC;
-	}
-
-	if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;
-
-	if(copy_from_user(page, buf, count))
-	{
-		retval = -EFAULT;
-		goto out;
-	}
-
-	if (page[count-1] == '\n')
-		page[count-1] = '\0';
-	else if (count < PAGE_SIZE)
-		page[count] = '\0';
-	else if (page[count]) {
-		retval = -EINVAL;
-		goto out;
-	}
-
-	buffer = page;
-
-	if (mutex_lock_interruptible(&cam->param_lock))
-		return -ERESTARTSYS;
-
-	/*
-	 * Skip over leading whitespace
-	 */
-	while (count && isspace(*buffer)) {
-		--count;
-		++buffer;
-	}
-
-	memcpy(&new_params, &cam->params, sizeof(struct cam_params));
-	new_mains = cam->mainsFreq;
-
-#define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval))
-#define VALUE (value(&buffer,&count, &retval))
-#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
-			       new_params.version.firmwareRevision == (y))
-
-	retval = 0;
-	while (count && !retval) {
-		find_colon = 1;
-		if (MATCH("brightness")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 100)
-					new_params.colourParams.brightness = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOLOURPARAMS;
-			if(new_params.flickerControl.allowableOverExposure < 0)
-				new_params.flickerControl.allowableOverExposure =
-					-find_over_exposure(new_params.colourParams.brightness);
-			if(new_params.flickerControl.flickerMode != 0)
-				command_flags |= COMMAND_SETFLICKERCTRL;
-
-		} else if (MATCH("contrast")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 100) {
-					/* contrast is in steps of 8, so round*/
-					val = ((val + 3) / 8) * 8;
-					/* 1-02 firmware limits contrast to 80*/
-					if (FIRMWARE_VERSION(1,2) && val > 80)
-						val = 80;
-
-					new_params.colourParams.contrast = val;
-				} else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOLOURPARAMS;
-		} else if (MATCH("saturation")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 100)
-					new_params.colourParams.saturation = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOLOURPARAMS;
-		} else if (MATCH("sensor_fps")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				/* find values so that sensorFPS is minimized,
-				 * but >= val */
-				if (val > 30)
-					retval = -EINVAL;
-				else if (val > 25) {
-					new_params.sensorFps.divisor = 0;
-					new_params.sensorFps.baserate = 1;
-				} else if (val > 15) {
-					new_params.sensorFps.divisor = 0;
-					new_params.sensorFps.baserate = 0;
-				} else if (val > 12) {
-					new_params.sensorFps.divisor = 1;
-					new_params.sensorFps.baserate = 1;
-				} else if (val > 7) {
-					new_params.sensorFps.divisor = 1;
-					new_params.sensorFps.baserate = 0;
-				} else if (val > 6) {
-					new_params.sensorFps.divisor = 2;
-					new_params.sensorFps.baserate = 1;
-				} else if (val > 3) {
-					new_params.sensorFps.divisor = 2;
-					new_params.sensorFps.baserate = 0;
-				} else {
-					new_params.sensorFps.divisor = 3;
-					/* Either base rate would work here */
-					new_params.sensorFps.baserate = 1;
-				}
-				new_params.flickerControl.coarseJump =
-					flicker_jumps[new_mains]
-					[new_params.sensorFps.baserate]
-					[new_params.sensorFps.divisor];
-				if (new_params.flickerControl.flickerMode)
-					command_flags |= COMMAND_SETFLICKERCTRL;
-			}
-			command_flags |= COMMAND_SETSENSORFPS;
-			cam->exposure_status = EXPOSURE_NORMAL;
-		} else if (MATCH("stream_start_line")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				int max_line = 288;
-
-				if (new_params.format.videoSize == VIDEOSIZE_QCIF)
-					max_line = 144;
-				if (val <= max_line)
-					new_params.streamStartLine = val/2;
-				else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("sub_sample")) {
-			if (!retval && MATCH("420"))
-				new_params.format.subSample = SUBSAMPLE_420;
-			else if (!retval && MATCH("422"))
-				new_params.format.subSample = SUBSAMPLE_422;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETFORMAT;
-		} else if (MATCH("yuv_order")) {
-			if (!retval && MATCH("YUYV"))
-				new_params.format.yuvOrder = YUVORDER_YUYV;
-			else if (!retval && MATCH("UYVY"))
-				new_params.format.yuvOrder = YUVORDER_UYVY;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETFORMAT;
-		} else if (MATCH("ecp_timing")) {
-			if (!retval && MATCH("normal"))
-				new_params.ecpTiming = 0;
-			else if (!retval && MATCH("slow"))
-				new_params.ecpTiming = 1;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETECPTIMING;
-		} else if (MATCH("color_balance_mode")) {
-			if (!retval && MATCH("manual"))
-				new_params.colourBalance.balanceMode = 3;
-			else if (!retval && MATCH("auto"))
-				new_params.colourBalance.balanceMode = 2;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETCOLOURBALANCE;
-		} else if (MATCH("red_gain")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 212) {
-					new_params.colourBalance.redGain = val;
-					new_params.colourBalance.balanceMode = 1;
-				} else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOLOURBALANCE;
-		} else if (MATCH("green_gain")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 212) {
-					new_params.colourBalance.greenGain = val;
-					new_params.colourBalance.balanceMode = 1;
-				} else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOLOURBALANCE;
-		} else if (MATCH("blue_gain")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 212) {
-					new_params.colourBalance.blueGain = val;
-					new_params.colourBalance.balanceMode = 1;
-				} else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOLOURBALANCE;
-		} else if (MATCH("max_gain")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				/* 1-02 firmware limits gain to 2 */
-				if (FIRMWARE_VERSION(1,2) && val > 2)
-					val = 2;
-				switch(val) {
-				case 1:
-					new_params.exposure.gainMode = 1;
-					break;
-				case 2:
-					new_params.exposure.gainMode = 2;
-					break;
-				case 4:
-					new_params.exposure.gainMode = 3;
-					break;
-				case 8:
-					new_params.exposure.gainMode = 4;
-					break;
-				default:
-					retval = -EINVAL;
-					break;
-				}
-			}
-			command_flags |= COMMAND_SETEXPOSURE;
-		} else if (MATCH("exposure_mode")) {
-			if (!retval && MATCH("auto"))
-				new_params.exposure.expMode = 2;
-			else if (!retval && MATCH("manual")) {
-				if (new_params.exposure.expMode == 2)
-					new_params.exposure.expMode = 3;
-				if(new_params.flickerControl.flickerMode != 0)
-					command_flags |= COMMAND_SETFLICKERCTRL;
-				new_params.flickerControl.flickerMode = 0;
-			} else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETEXPOSURE;
-		} else if (MATCH("centre_weight")) {
-			if (!retval && MATCH("on"))
-				new_params.exposure.centreWeight = 1;
-			else if (!retval && MATCH("off"))
-				new_params.exposure.centreWeight = 2;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETEXPOSURE;
-		} else if (MATCH("gain")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				switch(val) {
-				case 1:
-					new_params.exposure.gain = 0;
-					break;
-				case 2:
-					new_params.exposure.gain = 1;
-					break;
-				case 4:
-					new_params.exposure.gain = 2;
-					break;
-				case 8:
-					new_params.exposure.gain = 3;
-					break;
-				default:
-					retval = -EINVAL;
-					break;
-				}
-				new_params.exposure.expMode = 1;
-				if(new_params.flickerControl.flickerMode != 0)
-					command_flags |= COMMAND_SETFLICKERCTRL;
-				new_params.flickerControl.flickerMode = 0;
-				command_flags |= COMMAND_SETEXPOSURE;
-				if (new_params.exposure.gain >
-				    new_params.exposure.gainMode-1)
-					retval = -EINVAL;
-			}
-		} else if (MATCH("fine_exp")) {
-			if (!retval)
-				val = VALUE/2;
-
-			if (!retval) {
-				if (val < 256) {
-					/* 1-02 firmware limits fineExp/2 to 127*/
-					if (FIRMWARE_VERSION(1,2) && val > 127)
-						val = 127;
-					new_params.exposure.fineExp = val;
-					new_params.exposure.expMode = 1;
-					command_flags |= COMMAND_SETEXPOSURE;
-					if(new_params.flickerControl.flickerMode != 0)
-						command_flags |= COMMAND_SETFLICKERCTRL;
-					new_params.flickerControl.flickerMode = 0;
-					command_flags |= COMMAND_SETFLICKERCTRL;
-				} else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("coarse_exp")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= MAX_EXP) {
-					if (FIRMWARE_VERSION(1,2) &&
-					    val > MAX_EXP_102)
-						val = MAX_EXP_102;
-					new_params.exposure.coarseExpLo =
-						val & 0xff;
-					new_params.exposure.coarseExpHi =
-						val >> 8;
-					new_params.exposure.expMode = 1;
-					command_flags |= COMMAND_SETEXPOSURE;
-					if(new_params.flickerControl.flickerMode != 0)
-						command_flags |= COMMAND_SETFLICKERCTRL;
-					new_params.flickerControl.flickerMode = 0;
-					command_flags |= COMMAND_SETFLICKERCTRL;
-				} else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("red_comp")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val >= COMP_RED && val <= 255) {
-					new_params.exposure.redComp = val;
-					new_params.exposure.compMode = 1;
-					command_flags |= COMMAND_SETEXPOSURE;
-				} else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("green1_comp")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val >= COMP_GREEN1 && val <= 255) {
-					new_params.exposure.green1Comp = val;
-					new_params.exposure.compMode = 1;
-					command_flags |= COMMAND_SETEXPOSURE;
-				} else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("green2_comp")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val >= COMP_GREEN2 && val <= 255) {
-					new_params.exposure.green2Comp = val;
-					new_params.exposure.compMode = 1;
-					command_flags |= COMMAND_SETEXPOSURE;
-				} else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("blue_comp")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val >= COMP_BLUE && val <= 255) {
-					new_params.exposure.blueComp = val;
-					new_params.exposure.compMode = 1;
-					command_flags |= COMMAND_SETEXPOSURE;
-				} else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("apcor_gain1")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				command_flags |= COMMAND_SETAPCOR;
-				if (val <= 0xff)
-					new_params.apcor.gain1 = val;
-				else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("apcor_gain2")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				command_flags |= COMMAND_SETAPCOR;
-				if (val <= 0xff)
-					new_params.apcor.gain2 = val;
-				else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("apcor_gain4")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				command_flags |= COMMAND_SETAPCOR;
-				if (val <= 0xff)
-					new_params.apcor.gain4 = val;
-				else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("apcor_gain8")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				command_flags |= COMMAND_SETAPCOR;
-				if (val <= 0xff)
-					new_params.apcor.gain8 = val;
-				else
-					retval = -EINVAL;
-			}
-		} else if (MATCH("vl_offset_gain1")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.vlOffset.gain1 = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETVLOFFSET;
-		} else if (MATCH("vl_offset_gain2")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.vlOffset.gain2 = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETVLOFFSET;
-		} else if (MATCH("vl_offset_gain4")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.vlOffset.gain4 = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETVLOFFSET;
-		} else if (MATCH("vl_offset_gain8")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.vlOffset.gain8 = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETVLOFFSET;
-		} else if (MATCH("flicker_control")) {
-			if (!retval && MATCH("on")) {
-				set_flicker(&new_params, &command_flags, 1);
-			} else if (!retval && MATCH("off")) {
-				set_flicker(&new_params, &command_flags, 0);
-			} else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETFLICKERCTRL;
-		} else if (MATCH("mains_frequency")) {
-			if (!retval && MATCH("50")) {
-				new_mains = 0;
-				new_params.flickerControl.coarseJump =
-					flicker_jumps[new_mains]
-					[new_params.sensorFps.baserate]
-					[new_params.sensorFps.divisor];
-				if (new_params.flickerControl.flickerMode)
-					command_flags |= COMMAND_SETFLICKERCTRL;
-			} else if (!retval && MATCH("60")) {
-				new_mains = 1;
-				new_params.flickerControl.coarseJump =
-					flicker_jumps[new_mains]
-					[new_params.sensorFps.baserate]
-					[new_params.sensorFps.divisor];
-				if (new_params.flickerControl.flickerMode)
-					command_flags |= COMMAND_SETFLICKERCTRL;
-			} else
-				retval = -EINVAL;
-		} else if (MATCH("allowable_overexposure")) {
-			if (!retval && MATCH("auto")) {
-				new_params.flickerControl.allowableOverExposure =
-					-find_over_exposure(new_params.colourParams.brightness);
-				if(new_params.flickerControl.flickerMode != 0)
-					command_flags |= COMMAND_SETFLICKERCTRL;
-			} else {
-				if (!retval)
-					val = VALUE;
-
-				if (!retval) {
-					if (val <= 0xff) {
-						new_params.flickerControl.
-							allowableOverExposure = val;
-						if(new_params.flickerControl.flickerMode != 0)
-							command_flags |= COMMAND_SETFLICKERCTRL;
-					} else
-						retval = -EINVAL;
-				}
-			}
-		} else if (MATCH("compression_mode")) {
-			if (!retval && MATCH("none"))
-				new_params.compression.mode =
-					CPIA_COMPRESSION_NONE;
-			else if (!retval && MATCH("auto"))
-				new_params.compression.mode =
-					CPIA_COMPRESSION_AUTO;
-			else if (!retval && MATCH("manual"))
-				new_params.compression.mode =
-					CPIA_COMPRESSION_MANUAL;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETCOMPRESSION;
-		} else if (MATCH("decimation_enable")) {
-			if (!retval && MATCH("off"))
-				new_params.compression.decimation = 0;
-			else if (!retval && MATCH("on"))
-				new_params.compression.decimation = 1;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETCOMPRESSION;
-		} else if (MATCH("compression_target")) {
-			if (!retval && MATCH("quality"))
-				new_params.compressionTarget.frTargeting =
-					CPIA_COMPRESSION_TARGET_QUALITY;
-			else if (!retval && MATCH("framerate"))
-				new_params.compressionTarget.frTargeting =
-					CPIA_COMPRESSION_TARGET_FRAMERATE;
-			else
-				retval = -EINVAL;
-
-			command_flags |= COMMAND_SETCOMPRESSIONTARGET;
-		} else if (MATCH("target_framerate")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if(val > 0 && val <= 30)
-					new_params.compressionTarget.targetFR = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONTARGET;
-		} else if (MATCH("target_quality")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if(val > 0 && val <= 64)
-					new_params.compressionTarget.targetQ = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONTARGET;
-		} else if (MATCH("y_threshold")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val < 32)
-					new_params.yuvThreshold.yThreshold = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETYUVTHRESH;
-		} else if (MATCH("uv_threshold")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val < 32)
-					new_params.yuvThreshold.uvThreshold = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETYUVTHRESH;
-		} else if (MATCH("hysteresis")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.hysteresis = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("threshold_max")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.threshMax = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("small_step")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.smallStep = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("large_step")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.largeStep = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("decimation_hysteresis")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.decimationHysteresis = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("fr_diff_step_thresh")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.frDiffStepThresh = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("q_diff_step_thresh")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.qDiffStepThresh = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("decimation_thresh_mod")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					new_params.compressionParams.decimationThreshMod = val;
-				else
-					retval = -EINVAL;
-			}
-			command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
-		} else if (MATCH("toplight")) {
-			if (!retval && MATCH("on"))
-				new_params.qx3.toplight = 1;
-			else if (!retval && MATCH("off"))
-				new_params.qx3.toplight = 0;
-			else
-				retval = -EINVAL;
-			command_flags |= COMMAND_SETLIGHTS;
-		} else if (MATCH("bottomlight")) {
-			if (!retval && MATCH("on"))
-				new_params.qx3.bottomlight = 1;
-			else if (!retval && MATCH("off"))
-				new_params.qx3.bottomlight = 0;
-			else
-				retval = -EINVAL;
-			command_flags |= COMMAND_SETLIGHTS;
-		} else {
-			DBG("No match found\n");
-			retval = -EINVAL;
-		}
-
-		if (!retval) {
-			while (count && isspace(*buffer) && *buffer != '\n') {
-				--count;
-				++buffer;
-			}
-			if (count) {
-				if (*buffer == '\0' && count != 1)
-					retval = -EINVAL;
-				else if (*buffer != '\n' && *buffer != ';' &&
-					 *buffer != '\0')
-					retval = -EINVAL;
-				else {
-					--count;
-					++buffer;
-				}
-			}
-		}
-	}
-#undef MATCH
-#undef VALUE
-#undef FIRMWARE_VERSION
-	if (!retval) {
-		if (command_flags & COMMAND_SETCOLOURPARAMS) {
-			/* Adjust cam->vp to reflect these changes */
-			cam->vp.brightness =
-				new_params.colourParams.brightness*65535/100;
-			cam->vp.contrast =
-				new_params.colourParams.contrast*65535/100;
-			cam->vp.colour =
-				new_params.colourParams.saturation*65535/100;
-		}
-		if((command_flags & COMMAND_SETEXPOSURE) &&
-		   new_params.exposure.expMode == 2)
-			cam->exposure_status = EXPOSURE_NORMAL;
-
-		memcpy(&cam->params, &new_params, sizeof(struct cam_params));
-		cam->mainsFreq = new_mains;
-		cam->cmd_queue |= command_flags;
-		retval = size;
-	} else
-		DBG("error: %d\n", retval);
-
-	mutex_unlock(&cam->param_lock);
-
-out:
-	free_page((unsigned long)page);
-	return retval;
-}
-
-static const struct file_operations cpia_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= cpia_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-	.write		= cpia_proc_write,
-};
-
-static void create_proc_cpia_cam(struct cam_data *cam)
-{
-	struct proc_dir_entry *ent;
-
-	if (!cpia_proc_root || !cam)
-		return;
-
-	ent = proc_create_data(video_device_node_name(&cam->vdev),
-			       S_IRUGO|S_IWUSR, cpia_proc_root,
-			       &cpia_proc_fops, cam);
-	if (!ent)
-		return;
-
-	/*
-	   size of the proc entry is 3736 bytes for the standard webcam;
-	   the extra features of the QX3 microscope add 189 bytes.
-	   (we have not yet probed the camera to see which type it is).
-	*/
-	ent->size = 3736 + 189;
-	cam->proc_entry = ent;
-}
-
-static void destroy_proc_cpia_cam(struct cam_data *cam)
-{
-	if (!cam || !cam->proc_entry)
-		return;
-
-	remove_proc_entry(video_device_node_name(&cam->vdev), cpia_proc_root);
-	cam->proc_entry = NULL;
-}
-
-static void proc_cpia_create(void)
-{
-	cpia_proc_root = proc_mkdir("cpia", NULL);
-
-	if (!cpia_proc_root)
-		LOG("Unable to initialise /proc/cpia\n");
-}
-
-static void __exit proc_cpia_destroy(void)
-{
-	remove_proc_entry("cpia", NULL);
-}
-#endif /* CONFIG_PROC_FS */
-
-/* ----------------------- debug functions ---------------------- */
-
-#define printstatus(cam) \
-  DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\
-	cam->params.status.systemState, cam->params.status.grabState, \
-	cam->params.status.streamState, cam->params.status.fatalError, \
-	cam->params.status.cmdError, cam->params.status.debugFlags, \
-	cam->params.status.vpStatus, cam->params.status.errorCode);
-
-/* ----------------------- v4l helpers -------------------------- */
-
-/* supported frame palettes and depths */
-static inline int valid_mode(u16 palette, u16 depth)
-{
-	if ((palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
-	    (palette == VIDEO_PALETTE_YUYV && depth == 16))
-		return 1;
-
-	if (colorspace_conv)
-		return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
-		       (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
-		       (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
-		       (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
-		       (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
-		       (palette == VIDEO_PALETTE_UYVY && depth == 16);
-
-	return 0;
-}
-
-static int match_videosize( int width, int height )
-{
-	/* return the best match, where 'best' is as always
-	 * the largest that is not bigger than what is requested. */
-	if (width>=352 && height>=288)
-		return VIDEOSIZE_352_288; /* CIF */
-
-	if (width>=320 && height>=240)
-		return VIDEOSIZE_320_240; /* SIF */
-
-	if (width>=288 && height>=216)
-		return VIDEOSIZE_288_216;
-
-	if (width>=256 && height>=192)
-		return VIDEOSIZE_256_192;
-
-	if (width>=224 && height>=168)
-		return VIDEOSIZE_224_168;
-
-	if (width>=192 && height>=144)
-		return VIDEOSIZE_192_144;
-
-	if (width>=176 && height>=144)
-		return VIDEOSIZE_176_144; /* QCIF */
-
-	if (width>=160 && height>=120)
-		return VIDEOSIZE_160_120; /* QSIF */
-
-	if (width>=128 && height>=96)
-		return VIDEOSIZE_128_96;
-
-	if (width>=88 && height>=72)
-		return VIDEOSIZE_88_72;
-
-	if (width>=64 && height>=48)
-		return VIDEOSIZE_64_48;
-
-	if (width>=48 && height>=48)
-		return VIDEOSIZE_48_48;
-
-	return -1;
-}
-
-/* these are the capture sizes we support */
-static void set_vw_size(struct cam_data *cam)
-{
-	/* the col/row/start/end values are the result of simple math    */
-	/* study the SetROI-command in cpia developers guide p 2-22      */
-	/* streamStartLine is set to the recommended value in the cpia   */
-	/*  developers guide p 3-37                                      */
-	switch(cam->video_size) {
-	case VIDEOSIZE_CIF:
-		cam->vw.width = 352;
-		cam->vw.height = 288;
-		cam->params.format.videoSize=VIDEOSIZE_CIF;
-		cam->params.roi.colStart=0;
-		cam->params.roi.rowStart=0;
-		cam->params.streamStartLine = 120;
-		break;
-	case VIDEOSIZE_SIF:
-		cam->vw.width = 320;
-		cam->vw.height = 240;
-		cam->params.format.videoSize=VIDEOSIZE_CIF;
-		cam->params.roi.colStart=2;
-		cam->params.roi.rowStart=6;
-		cam->params.streamStartLine = 120;
-		break;
-	case VIDEOSIZE_288_216:
-		cam->vw.width = 288;
-		cam->vw.height = 216;
-		cam->params.format.videoSize=VIDEOSIZE_CIF;
-		cam->params.roi.colStart=4;
-		cam->params.roi.rowStart=9;
-		cam->params.streamStartLine = 120;
-		break;
-	case VIDEOSIZE_256_192:
-		cam->vw.width = 256;
-		cam->vw.height = 192;
-		cam->params.format.videoSize=VIDEOSIZE_CIF;
-		cam->params.roi.colStart=6;
-		cam->params.roi.rowStart=12;
-		cam->params.streamStartLine = 120;
-		break;
-	case VIDEOSIZE_224_168:
-		cam->vw.width = 224;
-		cam->vw.height = 168;
-		cam->params.format.videoSize=VIDEOSIZE_CIF;
-		cam->params.roi.colStart=8;
-		cam->params.roi.rowStart=15;
-		cam->params.streamStartLine = 120;
-		break;
-	case VIDEOSIZE_192_144:
-		cam->vw.width = 192;
-		cam->vw.height = 144;
-		cam->params.format.videoSize=VIDEOSIZE_CIF;
-		cam->params.roi.colStart=10;
-		cam->params.roi.rowStart=18;
-		cam->params.streamStartLine = 120;
-		break;
-	case VIDEOSIZE_QCIF:
-		cam->vw.width = 176;
-		cam->vw.height = 144;
-		cam->params.format.videoSize=VIDEOSIZE_QCIF;
-		cam->params.roi.colStart=0;
-		cam->params.roi.rowStart=0;
-		cam->params.streamStartLine = 60;
-		break;
-	case VIDEOSIZE_QSIF:
-		cam->vw.width = 160;
-		cam->vw.height = 120;
-		cam->params.format.videoSize=VIDEOSIZE_QCIF;
-		cam->params.roi.colStart=1;
-		cam->params.roi.rowStart=3;
-		cam->params.streamStartLine = 60;
-		break;
-	case VIDEOSIZE_128_96:
-		cam->vw.width = 128;
-		cam->vw.height = 96;
-		cam->params.format.videoSize=VIDEOSIZE_QCIF;
-		cam->params.roi.colStart=3;
-		cam->params.roi.rowStart=6;
-		cam->params.streamStartLine = 60;
-		break;
-	case VIDEOSIZE_88_72:
-		cam->vw.width = 88;
-		cam->vw.height = 72;
-		cam->params.format.videoSize=VIDEOSIZE_QCIF;
-		cam->params.roi.colStart=5;
-		cam->params.roi.rowStart=9;
-		cam->params.streamStartLine = 60;
-		break;
-	case VIDEOSIZE_64_48:
-		cam->vw.width = 64;
-		cam->vw.height = 48;
-		cam->params.format.videoSize=VIDEOSIZE_QCIF;
-		cam->params.roi.colStart=7;
-		cam->params.roi.rowStart=12;
-		cam->params.streamStartLine = 60;
-		break;
-	case VIDEOSIZE_48_48:
-		cam->vw.width = 48;
-		cam->vw.height = 48;
-		cam->params.format.videoSize=VIDEOSIZE_QCIF;
-		cam->params.roi.colStart=8;
-		cam->params.roi.rowStart=6;
-		cam->params.streamStartLine = 60;
-		break;
-	default:
-		LOG("bad videosize value: %d\n", cam->video_size);
-		return;
-	}
-
-	if(cam->vc.width == 0)
-		cam->vc.width = cam->vw.width;
-	if(cam->vc.height == 0)
-		cam->vc.height = cam->vw.height;
-
-	cam->params.roi.colStart += cam->vc.x >> 3;
-	cam->params.roi.colEnd = cam->params.roi.colStart +
-				 (cam->vc.width >> 3);
-	cam->params.roi.rowStart += cam->vc.y >> 2;
-	cam->params.roi.rowEnd = cam->params.roi.rowStart +
-				 (cam->vc.height >> 2);
-
-	return;
-}
-
-static int allocate_frame_buf(struct cam_data *cam)
-{
-	int i;
-
-	cam->frame_buf = rvmalloc(FRAME_NUM * CPIA_MAX_FRAME_SIZE);
-	if (!cam->frame_buf)
-		return -ENOBUFS;
-
-	for (i = 0; i < FRAME_NUM; i++)
-		cam->frame[i].data = cam->frame_buf + i * CPIA_MAX_FRAME_SIZE;
-
-	return 0;
-}
-
-static int free_frame_buf(struct cam_data *cam)
-{
-	int i;
-
-	rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE);
-	cam->frame_buf = NULL;
-	for (i=0; i < FRAME_NUM; i++)
-		cam->frame[i].data = NULL;
-
-	return 0;
-}
-
-
-static inline void free_frames(struct cpia_frame frame[FRAME_NUM])
-{
-	int i;
-
-	for (i=0; i < FRAME_NUM; i++)
-		frame[i].state = FRAME_UNUSED;
-	return;
-}
-
-/**********************************************************************
- *
- * General functions
- *
- **********************************************************************/
-/* send an arbitrary command to the camera */
-static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
-{
-	int retval, datasize;
-	u8 cmd[8], data[8];
-
-	switch(command) {
-	case CPIA_COMMAND_GetCPIAVersion:
-	case CPIA_COMMAND_GetPnPID:
-	case CPIA_COMMAND_GetCameraStatus:
-	case CPIA_COMMAND_GetVPVersion:
-		datasize=8;
-		break;
-	case CPIA_COMMAND_GetColourParams:
-	case CPIA_COMMAND_GetColourBalance:
-	case CPIA_COMMAND_GetExposure:
-		mutex_lock(&cam->param_lock);
-		datasize=8;
-		break;
-	case CPIA_COMMAND_ReadMCPorts:
-	case CPIA_COMMAND_ReadVCRegs:
-		datasize = 4;
-		break;
-	default:
-		datasize=0;
-		break;
-	}
-
-	cmd[0] = command>>8;
-	cmd[1] = command&0xff;
-	cmd[2] = a;
-	cmd[3] = b;
-	cmd[4] = c;
-	cmd[5] = d;
-	cmd[6] = datasize;
-	cmd[7] = 0;
-
-	retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
-	if (retval) {
-		DBG("%x - failed, retval=%d\n", command, retval);
-		if (command == CPIA_COMMAND_GetColourParams ||
-		    command == CPIA_COMMAND_GetColourBalance ||
-		    command == CPIA_COMMAND_GetExposure)
-			mutex_unlock(&cam->param_lock);
-	} else {
-		switch(command) {
-		case CPIA_COMMAND_GetCPIAVersion:
-			cam->params.version.firmwareVersion = data[0];
-			cam->params.version.firmwareRevision = data[1];
-			cam->params.version.vcVersion = data[2];
-			cam->params.version.vcRevision = data[3];
-			break;
-		case CPIA_COMMAND_GetPnPID:
-			cam->params.pnpID.vendor = data[0]+(((u16)data[1])<<8);
-			cam->params.pnpID.product = data[2]+(((u16)data[3])<<8);
-			cam->params.pnpID.deviceRevision =
-				data[4]+(((u16)data[5])<<8);
-			break;
-		case CPIA_COMMAND_GetCameraStatus:
-			cam->params.status.systemState = data[0];
-			cam->params.status.grabState = data[1];
-			cam->params.status.streamState = data[2];
-			cam->params.status.fatalError = data[3];
-			cam->params.status.cmdError = data[4];
-			cam->params.status.debugFlags = data[5];
-			cam->params.status.vpStatus = data[6];
-			cam->params.status.errorCode = data[7];
-			break;
-		case CPIA_COMMAND_GetVPVersion:
-			cam->params.vpVersion.vpVersion = data[0];
-			cam->params.vpVersion.vpRevision = data[1];
-			cam->params.vpVersion.cameraHeadID =
-				data[2]+(((u16)data[3])<<8);
-			break;
-		case CPIA_COMMAND_GetColourParams:
-			cam->params.colourParams.brightness = data[0];
-			cam->params.colourParams.contrast = data[1];
-			cam->params.colourParams.saturation = data[2];
-			mutex_unlock(&cam->param_lock);
-			break;
-		case CPIA_COMMAND_GetColourBalance:
-			cam->params.colourBalance.redGain = data[0];
-			cam->params.colourBalance.greenGain = data[1];
-			cam->params.colourBalance.blueGain = data[2];
-			mutex_unlock(&cam->param_lock);
-			break;
-		case CPIA_COMMAND_GetExposure:
-			cam->params.exposure.gain = data[0];
-			cam->params.exposure.fineExp = data[1];
-			cam->params.exposure.coarseExpLo = data[2];
-			cam->params.exposure.coarseExpHi = data[3];
-			cam->params.exposure.redComp = data[4];
-			cam->params.exposure.green1Comp = data[5];
-			cam->params.exposure.green2Comp = data[6];
-			cam->params.exposure.blueComp = data[7];
-			mutex_unlock(&cam->param_lock);
-			break;
-
-		case CPIA_COMMAND_ReadMCPorts:
-			if (!cam->params.qx3.qx3_detected)
-				break;
-			/* test button press */
-			cam->params.qx3.button = ((data[1] & 0x02) == 0);
-			if (cam->params.qx3.button) {
-				/* button pressed - unlock the latch */
-				do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xDF,0xDF,0);
-				do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xFF,0xFF,0);
-			}
-
-			/* test whether microscope is cradled */
-			cam->params.qx3.cradled = ((data[2] & 0x40) == 0);
-			break;
-
-		default:
-			break;
-		}
-	}
-	return retval;
-}
-
-/* send a command  to the camera with an additional data transaction */
-static int do_command_extended(struct cam_data *cam, u16 command,
-			       u8 a, u8 b, u8 c, u8 d,
-			       u8 e, u8 f, u8 g, u8 h,
-			       u8 i, u8 j, u8 k, u8 l)
-{
-	int retval;
-	u8 cmd[8], data[8];
-
-	cmd[0] = command>>8;
-	cmd[1] = command&0xff;
-	cmd[2] = a;
-	cmd[3] = b;
-	cmd[4] = c;
-	cmd[5] = d;
-	cmd[6] = 8;
-	cmd[7] = 0;
-	data[0] = e;
-	data[1] = f;
-	data[2] = g;
-	data[3] = h;
-	data[4] = i;
-	data[5] = j;
-	data[6] = k;
-	data[7] = l;
-
-	retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
-	if (retval)
-		DBG("%x - failed\n", command);
-
-	return retval;
-}
-
-/**********************************************************************
- *
- * Colorspace conversion
- *
- **********************************************************************/
-#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
-
-static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt,
-		      int linesize, int mmap_kludge)
-{
-	int y, u, v, r, g, b, y1;
-
-	/* Odd lines use the same u and v as the previous line.
-	 * Because of compression, it is necessary to get this
-	 * information from the decoded image. */
-	switch(out_fmt) {
-	case VIDEO_PALETTE_RGB555:
-		y = (*yuv++ - 16) * 76310;
-		y1 = (*yuv - 16) * 76310;
-		r = ((*(rgb+1-linesize)) & 0x7c) << 1;
-		g = ((*(rgb-linesize)) & 0xe0) >> 4 |
-		    ((*(rgb+1-linesize)) & 0x03) << 6;
-		b = ((*(rgb-linesize)) & 0x1f) << 3;
-		u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
-		v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
-		r = 104635 * v;
-		g = -25690 * u - 53294 * v;
-		b = 132278 * u;
-		*rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3);
-		*rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6);
-		*rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3);
-		*rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6);
-		return 4;
-	case VIDEO_PALETTE_RGB565:
-		y = (*yuv++ - 16) * 76310;
-		y1 = (*yuv - 16) * 76310;
-		r = (*(rgb+1-linesize)) & 0xf8;
-		g = ((*(rgb-linesize)) & 0xe0) >> 3 |
-		    ((*(rgb+1-linesize)) & 0x07) << 5;
-		b = ((*(rgb-linesize)) & 0x1f) << 3;
-		u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
-		v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
-		r = 104635 * v;
-		g = -25690 * u - 53294 * v;
-		b = 132278 * u;
-		*rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3);
-		*rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5);
-		*rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3);
-		*rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5);
-		return 4;
-		break;
-	case VIDEO_PALETTE_RGB24:
-	case VIDEO_PALETTE_RGB32:
-		y = (*yuv++ - 16) * 76310;
-		y1 = (*yuv - 16) * 76310;
-		if (mmap_kludge) {
-			r = *(rgb+2-linesize);
-			g = *(rgb+1-linesize);
-			b = *(rgb-linesize);
-		} else {
-			r = *(rgb-linesize);
-			g = *(rgb+1-linesize);
-			b = *(rgb+2-linesize);
-		}
-		u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
-		v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
-		r = 104635 * v;
-		g = -25690 * u + -53294 * v;
-		b = 132278 * u;
-		if (mmap_kludge) {
-			*rgb++ = LIMIT(b+y);
-			*rgb++ = LIMIT(g+y);
-			*rgb++ = LIMIT(r+y);
-			if(out_fmt == VIDEO_PALETTE_RGB32)
-				rgb++;
-			*rgb++ = LIMIT(b+y1);
-			*rgb++ = LIMIT(g+y1);
-			*rgb = LIMIT(r+y1);
-		} else {
-			*rgb++ = LIMIT(r+y);
-			*rgb++ = LIMIT(g+y);
-			*rgb++ = LIMIT(b+y);
-			if(out_fmt == VIDEO_PALETTE_RGB32)
-				rgb++;
-			*rgb++ = LIMIT(r+y1);
-			*rgb++ = LIMIT(g+y1);
-			*rgb = LIMIT(b+y1);
-		}
-		if(out_fmt == VIDEO_PALETTE_RGB32)
-			return 8;
-		return 6;
-	case VIDEO_PALETTE_YUV422:
-	case VIDEO_PALETTE_YUYV:
-		y = *yuv++;
-		u = *(rgb+1-linesize);
-		y1 = *yuv;
-		v = *(rgb+3-linesize);
-		*rgb++ = y;
-		*rgb++ = u;
-		*rgb++ = y1;
-		*rgb = v;
-		return 4;
-	case VIDEO_PALETTE_UYVY:
-		u = *(rgb-linesize);
-		y = *yuv++;
-		v = *(rgb+2-linesize);
-		y1 = *yuv;
-		*rgb++ = u;
-		*rgb++ = y;
-		*rgb++ = v;
-		*rgb = y1;
-		return 4;
-	case VIDEO_PALETTE_GREY:
-		*rgb++ = *yuv++;
-		*rgb = *yuv;
-		return 2;
-	default:
-		DBG("Empty: %d\n", out_fmt);
-		return 0;
-	}
-}
-
-
-static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt,
-		      int in_uyvy, int mmap_kludge)
-{
-	int y, u, v, r, g, b, y1;
-
-	switch(out_fmt) {
-	case VIDEO_PALETTE_RGB555:
-	case VIDEO_PALETTE_RGB565:
-	case VIDEO_PALETTE_RGB24:
-	case VIDEO_PALETTE_RGB32:
-		if (in_uyvy) {
-			u = *yuv++ - 128;
-			y = (*yuv++ - 16) * 76310;
-			v = *yuv++ - 128;
-			y1 = (*yuv - 16) * 76310;
-		} else {
-			y = (*yuv++ - 16) * 76310;
-			u = *yuv++ - 128;
-			y1 = (*yuv++ - 16) * 76310;
-			v = *yuv - 128;
-		}
-		r = 104635 * v;
-		g = -25690 * u + -53294 * v;
-		b = 132278 * u;
-		break;
-	default:
-		y = *yuv++;
-		u = *yuv++;
-		y1 = *yuv++;
-		v = *yuv;
-		/* Just to avoid compiler warnings */
-		r = 0;
-		g = 0;
-		b = 0;
-		break;
-	}
-	switch(out_fmt) {
-	case VIDEO_PALETTE_RGB555:
-		*rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3);
-		*rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6);
-		*rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3);
-		*rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6);
-		return 4;
-	case VIDEO_PALETTE_RGB565:
-		*rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3);
-		*rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5);
-		*rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3);
-		*rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5);
-		return 4;
-	case VIDEO_PALETTE_RGB24:
-		if (mmap_kludge) {
-			*rgb++ = LIMIT(b+y);
-			*rgb++ = LIMIT(g+y);
-			*rgb++ = LIMIT(r+y);
-			*rgb++ = LIMIT(b+y1);
-			*rgb++ = LIMIT(g+y1);
-			*rgb = LIMIT(r+y1);
-		} else {
-			*rgb++ = LIMIT(r+y);
-			*rgb++ = LIMIT(g+y);
-			*rgb++ = LIMIT(b+y);
-			*rgb++ = LIMIT(r+y1);
-			*rgb++ = LIMIT(g+y1);
-			*rgb = LIMIT(b+y1);
-		}
-		return 6;
-	case VIDEO_PALETTE_RGB32:
-		if (mmap_kludge) {
-			*rgb++ = LIMIT(b+y);
-			*rgb++ = LIMIT(g+y);
-			*rgb++ = LIMIT(r+y);
-			rgb++;
-			*rgb++ = LIMIT(b+y1);
-			*rgb++ = LIMIT(g+y1);
-			*rgb = LIMIT(r+y1);
-		} else {
-			*rgb++ = LIMIT(r+y);
-			*rgb++ = LIMIT(g+y);
-			*rgb++ = LIMIT(b+y);
-			rgb++;
-			*rgb++ = LIMIT(r+y1);
-			*rgb++ = LIMIT(g+y1);
-			*rgb = LIMIT(b+y1);
-		}
-		return 8;
-	case VIDEO_PALETTE_GREY:
-		*rgb++ = y;
-		*rgb = y1;
-		return 2;
-	case VIDEO_PALETTE_YUV422:
-	case VIDEO_PALETTE_YUYV:
-		*rgb++ = y;
-		*rgb++ = u;
-		*rgb++ = y1;
-		*rgb = v;
-		return 4;
-	case VIDEO_PALETTE_UYVY:
-		*rgb++ = u;
-		*rgb++ = y;
-		*rgb++ = v;
-		*rgb = y1;
-		return 4;
-	default:
-		DBG("Empty: %d\n", out_fmt);
-		return 0;
-	}
-}
-
-static int skipcount(int count, int fmt)
-{
-	switch(fmt) {
-	case VIDEO_PALETTE_GREY:
-		return count;
-	case VIDEO_PALETTE_RGB555:
-	case VIDEO_PALETTE_RGB565:
-	case VIDEO_PALETTE_YUV422:
-	case VIDEO_PALETTE_YUYV:
-	case VIDEO_PALETTE_UYVY:
-		return 2*count;
-	case VIDEO_PALETTE_RGB24:
-		return 3*count;
-	case VIDEO_PALETTE_RGB32:
-		return 4*count;
-	default:
-		return 0;
-	}
-}
-
-static int parse_picture(struct cam_data *cam, int size)
-{
-	u8 *obuf, *ibuf, *end_obuf;
-	int ll, in_uyvy, compressed, decimation, even_line, origsize, out_fmt;
-	int rows, cols, linesize, subsample_422;
-
-	/* make sure params don't change while we are decoding */
-	mutex_lock(&cam->param_lock);
-
-	obuf = cam->decompressed_frame.data;
-	end_obuf = obuf+CPIA_MAX_FRAME_SIZE;
-	ibuf = cam->raw_image;
-	origsize = size;
-	out_fmt = cam->vp.palette;
-
-	if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) {
-		LOG("header not found\n");
-		mutex_unlock(&cam->param_lock);
-		return -1;
-	}
-
-	if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) {
-		LOG("wrong video size\n");
-		mutex_unlock(&cam->param_lock);
-		return -1;
-	}
-
-	if (ibuf[17] != SUBSAMPLE_420 && ibuf[17] != SUBSAMPLE_422) {
-		LOG("illegal subtype %d\n",ibuf[17]);
-		mutex_unlock(&cam->param_lock);
-		return -1;
-	}
-	subsample_422 = ibuf[17] == SUBSAMPLE_422;
-
-	if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) {
-		LOG("illegal yuvorder %d\n",ibuf[18]);
-		mutex_unlock(&cam->param_lock);
-		return -1;
-	}
-	in_uyvy = ibuf[18] == YUVORDER_UYVY;
-
-	if ((ibuf[24] != cam->params.roi.colStart) ||
-	    (ibuf[25] != cam->params.roi.colEnd) ||
-	    (ibuf[26] != cam->params.roi.rowStart) ||
-	    (ibuf[27] != cam->params.roi.rowEnd)) {
-		LOG("ROI mismatch\n");
-		mutex_unlock(&cam->param_lock);
-		return -1;
-	}
-	cols = 8*(ibuf[25] - ibuf[24]);
-	rows = 4*(ibuf[27] - ibuf[26]);
-
-
-	if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) {
-		LOG("illegal compression %d\n",ibuf[28]);
-		mutex_unlock(&cam->param_lock);
-		return -1;
-	}
-	compressed = (ibuf[28] == COMPRESSED);
-
-	if (ibuf[29] != NO_DECIMATION && ibuf[29] != DECIMATION_ENAB) {
-		LOG("illegal decimation %d\n",ibuf[29]);
-		mutex_unlock(&cam->param_lock);
-		return -1;
-	}
-	decimation = (ibuf[29] == DECIMATION_ENAB);
-
-	cam->params.yuvThreshold.yThreshold = ibuf[30];
-	cam->params.yuvThreshold.uvThreshold = ibuf[31];
-	cam->params.status.systemState = ibuf[32];
-	cam->params.status.grabState = ibuf[33];
-	cam->params.status.streamState = ibuf[34];
-	cam->params.status.fatalError = ibuf[35];
-	cam->params.status.cmdError = ibuf[36];
-	cam->params.status.debugFlags = ibuf[37];
-	cam->params.status.vpStatus = ibuf[38];
-	cam->params.status.errorCode = ibuf[39];
-	cam->fps = ibuf[41];
-	mutex_unlock(&cam->param_lock);
-
-	linesize = skipcount(cols, out_fmt);
-	ibuf += FRAME_HEADER_SIZE;
-	size -= FRAME_HEADER_SIZE;
-	ll = ibuf[0] | (ibuf[1] << 8);
-	ibuf += 2;
-	even_line = 1;
-
-	while (size > 0) {
-		size -= (ll+2);
-		if (size < 0) {
-			LOG("Insufficient data in buffer\n");
-			return -1;
-		}
-
-		while (ll > 1) {
-			if (!compressed || (compressed && !(*ibuf & 1))) {
-				if(subsample_422 || even_line) {
-				obuf += yuvconvert(ibuf, obuf, out_fmt,
-						   in_uyvy, cam->mmap_kludge);
-				ibuf += 4;
-				ll -= 4;
-			} else {
-					/* SUBSAMPLE_420 on an odd line */
-					obuf += convert420(ibuf, obuf,
-							   out_fmt, linesize,
-							   cam->mmap_kludge);
-					ibuf += 2;
-					ll -= 2;
-				}
-			} else {
-				/*skip compressed interval from previous frame*/
-				obuf += skipcount(*ibuf >> 1, out_fmt);
-				if (obuf > end_obuf) {
-					LOG("Insufficient buffer size\n");
-					return -1;
-				}
-				++ibuf;
-				ll--;
-			}
-		}
-		if (ll == 1) {
-			if (*ibuf != EOL) {
-				DBG("EOL not found giving up after %d/%d"
-				    " bytes\n", origsize-size, origsize);
-				return -1;
-			}
-
-			++ibuf; /* skip over EOL */
-
-			if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) &&
-			   (ibuf[2] == EOI) && (ibuf[3] == EOI)) {
-				size -= 4;
-				break;
-			}
-
-			if(decimation) {
-				/* skip the odd lines for now */
-				obuf += linesize;
-			}
-
-			if (size > 1) {
-				ll = ibuf[0] | (ibuf[1] << 8);
-				ibuf += 2; /* skip over line length */
-			}
-			if(!decimation)
-				even_line = !even_line;
-		} else {
-			LOG("line length was not 1 but %d after %d/%d bytes\n",
-			    ll, origsize-size, origsize);
-			return -1;
-		}
-	}
-
-	if(decimation) {
-		/* interpolate odd rows */
-		int i, j;
-		u8 *prev, *next;
-		prev = cam->decompressed_frame.data;
-		obuf = prev+linesize;
-		next = obuf+linesize;
-		for(i=1; i<rows-1; i+=2) {
-			for(j=0; j<linesize; ++j) {
-				*obuf++ = ((int)*prev++ + *next++) / 2;
-			}
-			prev += linesize;
-			obuf += linesize;
-			next += linesize;
-		}
-		/* last row is odd, just copy previous row */
-		memcpy(obuf, prev, linesize);
-	}
-
-	cam->decompressed_frame.count = obuf-cam->decompressed_frame.data;
-
-	return cam->decompressed_frame.count;
-}
-
-/* InitStreamCap wrapper to select correct start line */
-static inline int init_stream_cap(struct cam_data *cam)
-{
-	return do_command(cam, CPIA_COMMAND_InitStreamCap,
-			  0, cam->params.streamStartLine, 0, 0);
-}
-
-
-/*  find_over_exposure
- *    Finds a suitable value of OverExposure for use with SetFlickerCtrl
- *    Some calculation is required because this value changes with the brightness
- *    set with SetColourParameters
- *
- *  Parameters: Brightness  -  last brightness value set with SetColourParameters
- *
- *  Returns: OverExposure value to use with SetFlickerCtrl
- */
-#define FLICKER_MAX_EXPOSURE                    250
-#define FLICKER_ALLOWABLE_OVER_EXPOSURE         146
-#define FLICKER_BRIGHTNESS_CONSTANT             59
-static int find_over_exposure(int brightness)
-{
-	int MaxAllowableOverExposure, OverExposure;
-
-	MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
-				   FLICKER_BRIGHTNESS_CONSTANT;
-
-	if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) {
-		OverExposure = MaxAllowableOverExposure;
-	} else {
-		OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
-	}
-
-	return OverExposure;
-}
-#undef FLICKER_MAX_EXPOSURE
-#undef FLICKER_ALLOWABLE_OVER_EXPOSURE
-#undef FLICKER_BRIGHTNESS_CONSTANT
-
-/* update various camera modes and settings */
-static void dispatch_commands(struct cam_data *cam)
-{
-	mutex_lock(&cam->param_lock);
-	if (cam->cmd_queue==COMMAND_NONE) {
-		mutex_unlock(&cam->param_lock);
-		return;
-	}
-	DEB_BYTE(cam->cmd_queue);
-	DEB_BYTE(cam->cmd_queue>>8);
-	if (cam->cmd_queue & COMMAND_SETFORMAT) {
-		do_command(cam, CPIA_COMMAND_SetFormat,
-			   cam->params.format.videoSize,
-			   cam->params.format.subSample,
-			   cam->params.format.yuvOrder, 0);
-		do_command(cam, CPIA_COMMAND_SetROI,
-			   cam->params.roi.colStart, cam->params.roi.colEnd,
-			   cam->params.roi.rowStart, cam->params.roi.rowEnd);
-		cam->first_frame = 1;
-	}
-
-	if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS)
-		do_command(cam, CPIA_COMMAND_SetColourParams,
-			   cam->params.colourParams.brightness,
-			   cam->params.colourParams.contrast,
-			   cam->params.colourParams.saturation, 0);
-
-	if (cam->cmd_queue & COMMAND_SETAPCOR)
-		do_command(cam, CPIA_COMMAND_SetApcor,
-			   cam->params.apcor.gain1,
-			   cam->params.apcor.gain2,
-			   cam->params.apcor.gain4,
-			   cam->params.apcor.gain8);
-
-	if (cam->cmd_queue & COMMAND_SETVLOFFSET)
-		do_command(cam, CPIA_COMMAND_SetVLOffset,
-			   cam->params.vlOffset.gain1,
-			   cam->params.vlOffset.gain2,
-			   cam->params.vlOffset.gain4,
-			   cam->params.vlOffset.gain8);
-
-	if (cam->cmd_queue & COMMAND_SETEXPOSURE) {
-		do_command_extended(cam, CPIA_COMMAND_SetExposure,
-				    cam->params.exposure.gainMode,
-				    1,
-				    cam->params.exposure.compMode,
-				    cam->params.exposure.centreWeight,
-				    cam->params.exposure.gain,
-				    cam->params.exposure.fineExp,
-				    cam->params.exposure.coarseExpLo,
-				    cam->params.exposure.coarseExpHi,
-				    cam->params.exposure.redComp,
-				    cam->params.exposure.green1Comp,
-				    cam->params.exposure.green2Comp,
-				    cam->params.exposure.blueComp);
-		if(cam->params.exposure.expMode != 1) {
-			do_command_extended(cam, CPIA_COMMAND_SetExposure,
-					    0,
-					    cam->params.exposure.expMode,
-					    0, 0,
-					    cam->params.exposure.gain,
-					    cam->params.exposure.fineExp,
-					    cam->params.exposure.coarseExpLo,
-					    cam->params.exposure.coarseExpHi,
-					    0, 0, 0, 0);
-		}
-	}
-
-	if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) {
-		if (cam->params.colourBalance.balanceMode == 1) {
-			do_command(cam, CPIA_COMMAND_SetColourBalance,
-				   1,
-				   cam->params.colourBalance.redGain,
-				   cam->params.colourBalance.greenGain,
-				   cam->params.colourBalance.blueGain);
-			do_command(cam, CPIA_COMMAND_SetColourBalance,
-				   3, 0, 0, 0);
-		}
-		if (cam->params.colourBalance.balanceMode == 2) {
-			do_command(cam, CPIA_COMMAND_SetColourBalance,
-				   2, 0, 0, 0);
-		}
-		if (cam->params.colourBalance.balanceMode == 3) {
-			do_command(cam, CPIA_COMMAND_SetColourBalance,
-				   3, 0, 0, 0);
-		}
-	}
-
-	if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET)
-		do_command(cam, CPIA_COMMAND_SetCompressionTarget,
-			   cam->params.compressionTarget.frTargeting,
-			   cam->params.compressionTarget.targetFR,
-			   cam->params.compressionTarget.targetQ, 0);
-
-	if (cam->cmd_queue & COMMAND_SETYUVTHRESH)
-		do_command(cam, CPIA_COMMAND_SetYUVThresh,
-			   cam->params.yuvThreshold.yThreshold,
-			   cam->params.yuvThreshold.uvThreshold, 0, 0);
-
-	if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS)
-		do_command_extended(cam, CPIA_COMMAND_SetCompressionParams,
-			    0, 0, 0, 0,
-			    cam->params.compressionParams.hysteresis,
-			    cam->params.compressionParams.threshMax,
-			    cam->params.compressionParams.smallStep,
-			    cam->params.compressionParams.largeStep,
-			    cam->params.compressionParams.decimationHysteresis,
-			    cam->params.compressionParams.frDiffStepThresh,
-			    cam->params.compressionParams.qDiffStepThresh,
-			    cam->params.compressionParams.decimationThreshMod);
-
-	if (cam->cmd_queue & COMMAND_SETCOMPRESSION)
-		do_command(cam, CPIA_COMMAND_SetCompression,
-			   cam->params.compression.mode,
-			   cam->params.compression.decimation, 0, 0);
-
-	if (cam->cmd_queue & COMMAND_SETSENSORFPS)
-		do_command(cam, CPIA_COMMAND_SetSensorFPS,
-			   cam->params.sensorFps.divisor,
-			   cam->params.sensorFps.baserate, 0, 0);
-
-	if (cam->cmd_queue & COMMAND_SETFLICKERCTRL)
-		do_command(cam, CPIA_COMMAND_SetFlickerCtrl,
-			   cam->params.flickerControl.flickerMode,
-			   cam->params.flickerControl.coarseJump,
-			   abs(cam->params.flickerControl.allowableOverExposure),
-			   0);
-
-	if (cam->cmd_queue & COMMAND_SETECPTIMING)
-		do_command(cam, CPIA_COMMAND_SetECPTiming,
-			   cam->params.ecpTiming, 0, 0, 0);
-
-	if (cam->cmd_queue & COMMAND_PAUSE)
-		do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
-
-	if (cam->cmd_queue & COMMAND_RESUME)
-		init_stream_cap(cam);
-
-	if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected)
-	  {
-	    int p1 = (cam->params.qx3.bottomlight == 0) << 1;
-	    int p2 = (cam->params.qx3.toplight == 0) << 3;
-	    do_command(cam, CPIA_COMMAND_WriteVCReg,  0x90, 0x8F, 0x50, 0);
-	    do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0);
-	  }
-
-	cam->cmd_queue = COMMAND_NONE;
-	mutex_unlock(&cam->param_lock);
-	return;
-}
-
-
-
-static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
-			int on)
-{
-	/* Everything in here is from the Windows driver */
-#define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \
-			       params->version.firmwareRevision == (y))
-/* define for compgain calculation */
-#if 0
-#define COMPGAIN(base, curexp, newexp) \
-    (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
-#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
-    (u16)((float)curexp * (float)(u8)(curcomp + 128) / (float)(u8)(basecomp - 128))
-#else
-  /* equivalent functions without floating point math */
-#define COMPGAIN(base, curexp, newexp) \
-    (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2* newexp)) )
-#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
-     (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
-#endif
-
-
-	int currentexp = params->exposure.coarseExpLo +
-			 params->exposure.coarseExpHi*256;
-	int startexp;
-	if (on) {
-		int cj = params->flickerControl.coarseJump;
-		params->flickerControl.flickerMode = 1;
-		params->flickerControl.disabled = 0;
-		if(params->exposure.expMode != 2)
-			*command_flags |= COMMAND_SETEXPOSURE;
-		params->exposure.expMode = 2;
-		currentexp = currentexp << params->exposure.gain;
-		params->exposure.gain = 0;
-		/* round down current exposure to nearest value */
-		startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
-		if(startexp < 1)
-			startexp = 1;
-		startexp = (startexp * cj) - 1;
-		if(FIRMWARE_VERSION(1,2))
-			while(startexp > MAX_EXP_102)
-				startexp -= cj;
-		else
-			while(startexp > MAX_EXP)
-				startexp -= cj;
-		params->exposure.coarseExpLo = startexp & 0xff;
-		params->exposure.coarseExpHi = startexp >> 8;
-		if (currentexp > startexp) {
-			if (currentexp > (2 * startexp))
-				currentexp = 2 * startexp;
-			params->exposure.redComp = COMPGAIN (COMP_RED, currentexp, startexp);
-			params->exposure.green1Comp = COMPGAIN (COMP_GREEN1, currentexp, startexp);
-			params->exposure.green2Comp = COMPGAIN (COMP_GREEN2, currentexp, startexp);
-			params->exposure.blueComp = COMPGAIN (COMP_BLUE, currentexp, startexp);
-		} else {
-			params->exposure.redComp = COMP_RED;
-			params->exposure.green1Comp = COMP_GREEN1;
-			params->exposure.green2Comp = COMP_GREEN2;
-			params->exposure.blueComp = COMP_BLUE;
-		}
-		if(FIRMWARE_VERSION(1,2))
-			params->exposure.compMode = 0;
-		else
-			params->exposure.compMode = 1;
-
-		params->apcor.gain1 = 0x18;
-		params->apcor.gain2 = 0x18;
-		params->apcor.gain4 = 0x16;
-		params->apcor.gain8 = 0x14;
-		*command_flags |= COMMAND_SETAPCOR;
-	} else {
-		params->flickerControl.flickerMode = 0;
-		params->flickerControl.disabled = 1;
-		/* Coarse = average of equivalent coarse for each comp channel */
-		startexp = EXP_FROM_COMP(COMP_RED, params->exposure.redComp, currentexp);
-		startexp += EXP_FROM_COMP(COMP_GREEN1, params->exposure.green1Comp, currentexp);
-		startexp += EXP_FROM_COMP(COMP_GREEN2, params->exposure.green2Comp, currentexp);
-		startexp += EXP_FROM_COMP(COMP_BLUE, params->exposure.blueComp, currentexp);
-		startexp = startexp >> 2;
-		while(startexp > MAX_EXP &&
-		      params->exposure.gain < params->exposure.gainMode-1) {
-			startexp = startexp >> 1;
-			++params->exposure.gain;
-		}
-		if(FIRMWARE_VERSION(1,2) && startexp > MAX_EXP_102)
-			startexp = MAX_EXP_102;
-		if(startexp > MAX_EXP)
-			startexp = MAX_EXP;
-		params->exposure.coarseExpLo = startexp&0xff;
-		params->exposure.coarseExpHi = startexp >> 8;
-		params->exposure.redComp = COMP_RED;
-		params->exposure.green1Comp = COMP_GREEN1;
-		params->exposure.green2Comp = COMP_GREEN2;
-		params->exposure.blueComp = COMP_BLUE;
-		params->exposure.compMode = 1;
-		*command_flags |= COMMAND_SETEXPOSURE;
-		params->apcor.gain1 = 0x18;
-		params->apcor.gain2 = 0x16;
-		params->apcor.gain4 = 0x24;
-		params->apcor.gain8 = 0x34;
-		*command_flags |= COMMAND_SETAPCOR;
-	}
-	params->vlOffset.gain1 = 20;
-	params->vlOffset.gain2 = 24;
-	params->vlOffset.gain4 = 26;
-	params->vlOffset.gain8 = 26;
-	*command_flags |= COMMAND_SETVLOFFSET;
-#undef FIRMWARE_VERSION
-#undef EXP_FROM_COMP
-#undef COMPGAIN
-}
-
-#define FIRMWARE_VERSION(x,y) (cam->params.version.firmwareVersion == (x) && \
-			       cam->params.version.firmwareRevision == (y))
-/* monitor the exposure and adjust the sensor frame rate if needed */
-static void monitor_exposure(struct cam_data *cam)
-{
-	u8 exp_acc, bcomp, gain, coarseL, cmd[8], data[8];
-	int retval, light_exp, dark_exp, very_dark_exp;
-	int old_exposure, new_exposure, framerate;
-
-	/* get necessary stats and register settings from camera */
-	/* do_command can't handle this, so do it ourselves */
-	cmd[0] = CPIA_COMMAND_ReadVPRegs>>8;
-	cmd[1] = CPIA_COMMAND_ReadVPRegs&0xff;
-	cmd[2] = 30;
-	cmd[3] = 4;
-	cmd[4] = 9;
-	cmd[5] = 8;
-	cmd[6] = 8;
-	cmd[7] = 0;
-	retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
-	if (retval) {
-		LOG("ReadVPRegs(30,4,9,8) - failed, retval=%d\n",
-		    retval);
-		return;
-	}
-	exp_acc = data[0];
-	bcomp = data[1];
-	gain = data[2];
-	coarseL = data[3];
-
-	mutex_lock(&cam->param_lock);
-	light_exp = cam->params.colourParams.brightness +
-		    TC - 50 + EXP_ACC_LIGHT;
-	if(light_exp > 255)
-		light_exp = 255;
-	dark_exp = cam->params.colourParams.brightness +
-		   TC - 50 - EXP_ACC_DARK;
-	if(dark_exp < 0)
-		dark_exp = 0;
-	very_dark_exp = dark_exp/2;
-
-	old_exposure = cam->params.exposure.coarseExpHi * 256 +
-		       cam->params.exposure.coarseExpLo;
-
-	if(!cam->params.flickerControl.disabled) {
-		/* Flicker control on */
-		int max_comp = FIRMWARE_VERSION(1,2) ? MAX_COMP : HIGH_COMP_102;
-		bcomp += 128;	/* decode */
-		if(bcomp >= max_comp && exp_acc < dark_exp) {
-			/* dark */
-			if(exp_acc < very_dark_exp) {
-				/* very dark */
-				if(cam->exposure_status == EXPOSURE_VERY_DARK)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_VERY_DARK;
-					cam->exposure_count = 1;
-				}
-			} else {
-				/* just dark */
-				if(cam->exposure_status == EXPOSURE_DARK)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_DARK;
-					cam->exposure_count = 1;
-				}
-			}
-		} else if(old_exposure <= LOW_EXP || exp_acc > light_exp) {
-			/* light */
-			if(old_exposure <= VERY_LOW_EXP) {
-				/* very light */
-				if(cam->exposure_status == EXPOSURE_VERY_LIGHT)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_VERY_LIGHT;
-					cam->exposure_count = 1;
-				}
-			} else {
-				/* just light */
-				if(cam->exposure_status == EXPOSURE_LIGHT)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_LIGHT;
-					cam->exposure_count = 1;
-				}
-			}
-		} else {
-			/* not dark or light */
-			cam->exposure_status = EXPOSURE_NORMAL;
-		}
-	} else {
-		/* Flicker control off */
-		if(old_exposure >= MAX_EXP && exp_acc < dark_exp) {
-			/* dark */
-			if(exp_acc < very_dark_exp) {
-				/* very dark */
-				if(cam->exposure_status == EXPOSURE_VERY_DARK)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_VERY_DARK;
-					cam->exposure_count = 1;
-				}
-			} else {
-				/* just dark */
-				if(cam->exposure_status == EXPOSURE_DARK)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_DARK;
-					cam->exposure_count = 1;
-				}
-			}
-		} else if(old_exposure <= LOW_EXP || exp_acc > light_exp) {
-			/* light */
-			if(old_exposure <= VERY_LOW_EXP) {
-				/* very light */
-				if(cam->exposure_status == EXPOSURE_VERY_LIGHT)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_VERY_LIGHT;
-					cam->exposure_count = 1;
-				}
-			} else {
-				/* just light */
-				if(cam->exposure_status == EXPOSURE_LIGHT)
-					++cam->exposure_count;
-				else {
-					cam->exposure_status = EXPOSURE_LIGHT;
-					cam->exposure_count = 1;
-				}
-			}
-		} else {
-			/* not dark or light */
-			cam->exposure_status = EXPOSURE_NORMAL;
-		}
-	}
-
-	framerate = cam->fps;
-	if(framerate > 30 || framerate < 1)
-		framerate = 1;
-
-	if(!cam->params.flickerControl.disabled) {
-		/* Flicker control on */
-		if((cam->exposure_status == EXPOSURE_VERY_DARK ||
-		    cam->exposure_status == EXPOSURE_DARK) &&
-		   cam->exposure_count >= DARK_TIME*framerate &&
-		   cam->params.sensorFps.divisor < 3) {
-
-			/* dark for too long */
-			++cam->params.sensorFps.divisor;
-			cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
-			cam->params.flickerControl.coarseJump =
-				flicker_jumps[cam->mainsFreq]
-					     [cam->params.sensorFps.baserate]
-					     [cam->params.sensorFps.divisor];
-			cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
-
-			new_exposure = cam->params.flickerControl.coarseJump-1;
-			while(new_exposure < old_exposure/2)
-				new_exposure += cam->params.flickerControl.coarseJump;
-			cam->params.exposure.coarseExpLo = new_exposure & 0xff;
-			cam->params.exposure.coarseExpHi = new_exposure >> 8;
-			cam->cmd_queue |= COMMAND_SETEXPOSURE;
-			cam->exposure_status = EXPOSURE_NORMAL;
-			LOG("Automatically decreasing sensor_fps\n");
-
-		} else if((cam->exposure_status == EXPOSURE_VERY_LIGHT ||
-		    cam->exposure_status == EXPOSURE_LIGHT) &&
-		   cam->exposure_count >= LIGHT_TIME*framerate &&
-		   cam->params.sensorFps.divisor > 0) {
-
-			/* light for too long */
-			int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ;
-
-			--cam->params.sensorFps.divisor;
-			cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
-			cam->params.flickerControl.coarseJump =
-				flicker_jumps[cam->mainsFreq]
-					     [cam->params.sensorFps.baserate]
-					     [cam->params.sensorFps.divisor];
-			cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
-
-			new_exposure = cam->params.flickerControl.coarseJump-1;
-			while(new_exposure < 2*old_exposure &&
-			      new_exposure+
-			      cam->params.flickerControl.coarseJump < max_exp)
-				new_exposure += cam->params.flickerControl.coarseJump;
-			cam->params.exposure.coarseExpLo = new_exposure & 0xff;
-			cam->params.exposure.coarseExpHi = new_exposure >> 8;
-			cam->cmd_queue |= COMMAND_SETEXPOSURE;
-			cam->exposure_status = EXPOSURE_NORMAL;
-			LOG("Automatically increasing sensor_fps\n");
-		}
-	} else {
-		/* Flicker control off */
-		if((cam->exposure_status == EXPOSURE_VERY_DARK ||
-		    cam->exposure_status == EXPOSURE_DARK) &&
-		   cam->exposure_count >= DARK_TIME*framerate &&
-		   cam->params.sensorFps.divisor < 3) {
-
-			/* dark for too long */
-			++cam->params.sensorFps.divisor;
-			cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
-			if(cam->params.exposure.gain > 0) {
-				--cam->params.exposure.gain;
-				cam->cmd_queue |= COMMAND_SETEXPOSURE;
-			}
-			cam->exposure_status = EXPOSURE_NORMAL;
-			LOG("Automatically decreasing sensor_fps\n");
-
-		} else if((cam->exposure_status == EXPOSURE_VERY_LIGHT ||
-		    cam->exposure_status == EXPOSURE_LIGHT) &&
-		   cam->exposure_count >= LIGHT_TIME*framerate &&
-		   cam->params.sensorFps.divisor > 0) {
-
-			/* light for too long */
-			--cam->params.sensorFps.divisor;
-			cam->cmd_queue |= COMMAND_SETSENSORFPS;
-
-			if(cam->params.exposure.gain <
-			   cam->params.exposure.gainMode-1) {
-				++cam->params.exposure.gain;
-				cam->cmd_queue |= COMMAND_SETEXPOSURE;
-			}
-			cam->exposure_status = EXPOSURE_NORMAL;
-			LOG("Automatically increasing sensor_fps\n");
-		}
-	}
-	mutex_unlock(&cam->param_lock);
-}
-
-/*-----------------------------------------------------------------*/
-/* if flicker is switched off, this function switches it back on.It checks,
-   however, that conditions are suitable before restarting it.
-   This should only be called for firmware version 1.2.
-
-   It also adjust the colour balance when an exposure step is detected - as
-   long as flicker is running
-*/
-static void restart_flicker(struct cam_data *cam)
-{
-	int cam_exposure, old_exp;
-	if(!FIRMWARE_VERSION(1,2))
-		return;
-	mutex_lock(&cam->param_lock);
-	if(cam->params.flickerControl.flickerMode == 0 ||
-	   cam->raw_image[39] == 0) {
-		mutex_unlock(&cam->param_lock);
-		return;
-	}
-	cam_exposure = cam->raw_image[39]*2;
-	old_exp = cam->params.exposure.coarseExpLo +
-		  cam->params.exposure.coarseExpHi*256;
-	/*
-	  see how far away camera exposure is from a valid
-	  flicker exposure value
-	*/
-	cam_exposure %= cam->params.flickerControl.coarseJump;
-	if(!cam->params.flickerControl.disabled &&
-	   cam_exposure <= cam->params.flickerControl.coarseJump - 3) {
-		/* Flicker control auto-disabled */
-		cam->params.flickerControl.disabled = 1;
-	}
-
-	if(cam->params.flickerControl.disabled &&
-	   cam->params.flickerControl.flickerMode &&
-	   old_exp > cam->params.flickerControl.coarseJump +
-		     ROUND_UP_EXP_FOR_FLICKER) {
-		/* exposure is now high enough to switch
-		   flicker control back on */
-		set_flicker(&cam->params, &cam->cmd_queue, 1);
-		if((cam->cmd_queue & COMMAND_SETEXPOSURE) &&
-		   cam->params.exposure.expMode == 2)
-			cam->exposure_status = EXPOSURE_NORMAL;
-
-	}
-	mutex_unlock(&cam->param_lock);
-}
-#undef FIRMWARE_VERSION
-
-static int clear_stall(struct cam_data *cam)
-{
-	/* FIXME: Does this actually work? */
-	LOG("Clearing stall\n");
-
-	cam->ops->streamRead(cam->lowlevel_data, cam->raw_image, 0);
-	do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0);
-	return cam->params.status.streamState != STREAM_PAUSED;
-}
-
-/* kernel thread function to read image from camera */
-static int fetch_frame(void *data)
-{
-	int image_size, retry;
-	struct cam_data *cam = (struct cam_data *)data;
-	unsigned long oldjif, rate, diff;
-
-	/* Allow up to two bad images in a row to be read and
-	 * ignored before an error is reported */
-	for (retry = 0; retry < 3; ++retry) {
-		if (retry)
-			DBG("retry=%d\n", retry);
-
-		if (!cam->ops)
-			continue;
-
-		/* load first frame always uncompressed */
-		if (cam->first_frame &&
-		    cam->params.compression.mode != CPIA_COMPRESSION_NONE) {
-			do_command(cam, CPIA_COMMAND_SetCompression,
-				   CPIA_COMPRESSION_NONE,
-				   NO_DECIMATION, 0, 0);
-			/* Trial & error - Discarding a frame prevents the
-			   first frame from having an error in the data. */
-			do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
-		}
-
-		/* init camera upload */
-		if (do_command(cam, CPIA_COMMAND_GrabFrame, 0,
-			       cam->params.streamStartLine, 0, 0))
-			continue;
-
-		if (cam->ops->wait_for_stream_ready) {
-			/* loop until image ready */
-			int count = 0;
-			do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0);
-			while (cam->params.status.streamState != STREAM_READY) {
-				if(++count > READY_TIMEOUT)
-					break;
-				if(cam->params.status.streamState ==
-				   STREAM_PAUSED) {
-					/* Bad news */
-					if(!clear_stall(cam))
-						return -EIO;
-				}
-
-				cond_resched();
-
-				/* sleep for 10 ms, hopefully ;) */
-				msleep_interruptible(10);
-				if (signal_pending(current))
-					return -EINTR;
-
-				do_command(cam, CPIA_COMMAND_GetCameraStatus,
-					   0, 0, 0, 0);
-			}
-			if(cam->params.status.streamState != STREAM_READY) {
-				continue;
-			}
-		}
-
-		cond_resched();
-
-		/* grab image from camera */
-		oldjif = jiffies;
-		image_size = cam->ops->streamRead(cam->lowlevel_data,
-						  cam->raw_image, 0);
-		if (image_size <= 0) {
-			DBG("streamRead failed: %d\n", image_size);
-			continue;
-		}
-
-		rate = image_size * HZ / 1024;
-		diff = jiffies-oldjif;
-		cam->transfer_rate = diff==0 ? rate : rate/diff;
-			/* diff==0 ? unlikely but possible */
-
-		/* Switch flicker control back on if it got turned off */
-		restart_flicker(cam);
-
-		/* If AEC is enabled, monitor the exposure and
-		   adjust the sensor frame rate if needed */
-		if(cam->params.exposure.expMode == 2)
-			monitor_exposure(cam);
-
-		/* camera idle now so dispatch queued commands */
-		dispatch_commands(cam);
-
-		/* Update our knowledge of the camera state */
-		do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
-		do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
-		do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
-
-		/* decompress and convert image to by copying it from
-		 * raw_image to decompressed_frame
-		 */
-
-		cond_resched();
-
-		cam->image_size = parse_picture(cam, image_size);
-		if (cam->image_size <= 0) {
-			DBG("parse_picture failed %d\n", cam->image_size);
-			if(cam->params.compression.mode !=
-			   CPIA_COMPRESSION_NONE) {
-				/* Compression may not work right if we
-				   had a bad frame, get the next one
-				   uncompressed. */
-				cam->first_frame = 1;
-				do_command(cam, CPIA_COMMAND_SetGrabMode,
-					   CPIA_GRAB_SINGLE, 0, 0, 0);
-				/* FIXME: Trial & error - need up to 70ms for
-				   the grab mode change to complete ? */
-				msleep_interruptible(70);
-				if (signal_pending(current))
-					return -EINTR;
-			}
-		} else
-			break;
-	}
-
-	if (retry < 3) {
-		/* FIXME: this only works for double buffering */
-		if (cam->frame[cam->curframe].state == FRAME_READY) {
-			memcpy(cam->frame[cam->curframe].data,
-			       cam->decompressed_frame.data,
-			       cam->decompressed_frame.count);
-			cam->frame[cam->curframe].state = FRAME_DONE;
-		} else
-			cam->decompressed_frame.state = FRAME_DONE;
-
-		if (cam->first_frame) {
-			cam->first_frame = 0;
-			do_command(cam, CPIA_COMMAND_SetCompression,
-				   cam->params.compression.mode,
-				   cam->params.compression.decimation, 0, 0);
-
-			/* Switch from single-grab to continuous grab */
-			do_command(cam, CPIA_COMMAND_SetGrabMode,
-				   CPIA_GRAB_CONTINUOUS, 0, 0, 0);
-		}
-		return 0;
-	}
-	return -EIO;
-}
-
-static int capture_frame(struct cam_data *cam, struct video_mmap *vm)
-{
-	if (!cam->frame_buf) {
-		/* we do lazy allocation */
-		int err;
-		if ((err = allocate_frame_buf(cam)))
-			return err;
-	}
-
-	cam->curframe = vm->frame;
-	cam->frame[cam->curframe].state = FRAME_READY;
-	return fetch_frame(cam);
-}
-
-static int goto_high_power(struct cam_data *cam)
-{
-	if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0))
-		return -EIO;
-	msleep_interruptible(40);	/* windows driver does it too */
-	if(signal_pending(current))
-		return -EINTR;
-	if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
-		return -EIO;
-	if (cam->params.status.systemState == HI_POWER_STATE) {
-		DBG("camera now in HIGH power state\n");
-		return 0;
-	}
-	printstatus(cam);
-	return -EIO;
-}
-
-static int goto_low_power(struct cam_data *cam)
-{
-	if (do_command(cam, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0))
-		return -1;
-	if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
-		return -1;
-	if (cam->params.status.systemState == LO_POWER_STATE) {
-		DBG("camera now in LOW power state\n");
-		return 0;
-	}
-	printstatus(cam);
-	return -1;
-}
-
-static void save_camera_state(struct cam_data *cam)
-{
-	if(!(cam->cmd_queue & COMMAND_SETCOLOURBALANCE))
-		do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
-	if(!(cam->cmd_queue & COMMAND_SETEXPOSURE))
-		do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
-
-	DBG("%d/%d/%d/%d/%d/%d/%d/%d\n",
-	     cam->params.exposure.gain,
-	     cam->params.exposure.fineExp,
-	     cam->params.exposure.coarseExpLo,
-	     cam->params.exposure.coarseExpHi,
-	     cam->params.exposure.redComp,
-	     cam->params.exposure.green1Comp,
-	     cam->params.exposure.green2Comp,
-	     cam->params.exposure.blueComp);
-	DBG("%d/%d/%d\n",
-	     cam->params.colourBalance.redGain,
-	     cam->params.colourBalance.greenGain,
-	     cam->params.colourBalance.blueGain);
-}
-
-static int set_camera_state(struct cam_data *cam)
-{
-	cam->cmd_queue = COMMAND_SETCOMPRESSION |
-			 COMMAND_SETCOMPRESSIONTARGET |
-			 COMMAND_SETCOLOURPARAMS |
-			 COMMAND_SETFORMAT |
-			 COMMAND_SETYUVTHRESH |
-			 COMMAND_SETECPTIMING |
-			 COMMAND_SETCOMPRESSIONPARAMS |
-			 COMMAND_SETEXPOSURE |
-			 COMMAND_SETCOLOURBALANCE |
-			 COMMAND_SETSENSORFPS |
-			 COMMAND_SETAPCOR |
-			 COMMAND_SETFLICKERCTRL |
-			 COMMAND_SETVLOFFSET;
-
-	do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_SINGLE,0,0,0);
-	dispatch_commands(cam);
-
-	/* Wait 6 frames for the sensor to get all settings and
-	   AEC/ACB to settle */
-	msleep_interruptible(6*(cam->params.sensorFps.baserate ? 33 : 40) *
-			       (1 << cam->params.sensorFps.divisor) + 10);
-
-	if(signal_pending(current))
-		return -EINTR;
-
-	save_camera_state(cam);
-
-	return 0;
-}
-
-static void get_version_information(struct cam_data *cam)
-{
-	/* GetCPIAVersion */
-	do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
-
-	/* GetPnPID */
-	do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
-}
-
-/* initialize camera */
-static int reset_camera(struct cam_data *cam)
-{
-	int err;
-	/* Start the camera in low power mode */
-	if (goto_low_power(cam)) {
-		if (cam->params.status.systemState != WARM_BOOT_STATE)
-			return -ENODEV;
-
-		/* FIXME: this is just dirty trial and error */
-		err = goto_high_power(cam);
-		if(err)
-			return err;
-		do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
-		if (goto_low_power(cam))
-			return -ENODEV;
-	}
-
-	/* procedure described in developer's guide p3-28 */
-
-	/* Check the firmware version. */
-	cam->params.version.firmwareVersion = 0;
-	get_version_information(cam);
-	if (cam->params.version.firmwareVersion != 1)
-		return -ENODEV;
-
-	/* A bug in firmware 1-02 limits gainMode to 2 */
-	if(cam->params.version.firmwareRevision <= 2 &&
-	   cam->params.exposure.gainMode > 2) {
-		cam->params.exposure.gainMode = 2;
-	}
-
-	/* set QX3 detected flag */
-	cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 &&
-					cam->params.pnpID.product == 0x0001);
-
-	/* The fatal error checking should be done after
-	 * the camera powers up (developer's guide p 3-38) */
-
-	/* Set streamState before transition to high power to avoid bug
-	 * in firmware 1-02 */
-	do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0,
-		   STREAM_NOT_READY, 0);
-
-	/* GotoHiPower */
-	err = goto_high_power(cam);
-	if (err)
-		return err;
-
-	/* Check the camera status */
-	if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
-		return -EIO;
-
-	if (cam->params.status.fatalError) {
-		DBG("fatal_error:              %#04x\n",
-		    cam->params.status.fatalError);
-		DBG("vp_status:                %#04x\n",
-		    cam->params.status.vpStatus);
-		if (cam->params.status.fatalError & ~(COM_FLAG|CPIA_FLAG)) {
-			/* Fatal error in camera */
-			return -EIO;
-		} else if (cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)) {
-			/* Firmware 1-02 may do this for parallel port cameras,
-			 * just clear the flags (developer's guide p 3-38) */
-			do_command(cam, CPIA_COMMAND_ModifyCameraStatus,
-				   FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
-		}
-	}
-
-	/* Check the camera status again */
-	if (cam->params.status.fatalError) {
-		if (cam->params.status.fatalError)
-			return -EIO;
-	}
-
-	/* VPVersion can't be retrieved before the camera is in HiPower,
-	 * so get it here instead of in get_version_information. */
-	do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
-
-	/* set camera to a known state */
-	return set_camera_state(cam);
-}
-
-static void put_cam(struct cpia_camera_ops* ops)
-{
-	module_put(ops->owner);
-}
-
-/* ------------------------- V4L interface --------------------- */
-static int cpia_open(struct file *file)
-{
-	struct video_device *dev = video_devdata(file);
-	struct cam_data *cam = video_get_drvdata(dev);
-	int err;
-
-	if (!cam) {
-		DBG("Internal error, cam_data not found!\n");
-		return -ENODEV;
-	}
-
-	if (cam->open_count > 0) {
-		DBG("Camera already open\n");
-		return -EBUSY;
-	}
-
-	if (!try_module_get(cam->ops->owner))
-		return -ENODEV;
-
-	mutex_lock(&cam->busy_lock);
-	err = -ENOMEM;
-	if (!cam->raw_image) {
-		cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
-		if (!cam->raw_image)
-			goto oops;
-	}
-
-	if (!cam->decompressed_frame.data) {
-		cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE);
-		if (!cam->decompressed_frame.data)
-			goto oops;
-	}
-
-	/* open cpia */
-	err = -ENODEV;
-	if (cam->ops->open(cam->lowlevel_data))
-		goto oops;
-
-	/* reset the camera */
-	if ((err = reset_camera(cam)) != 0) {
-		cam->ops->close(cam->lowlevel_data);
-		goto oops;
-	}
-
-	/* Set ownership of /proc/cpia/videoX to current user */
-	if(cam->proc_entry)
-		cam->proc_entry->uid = current_euid();
-
-	/* set mark for loading first frame uncompressed */
-	cam->first_frame = 1;
-
-	/* init it to something */
-	cam->mmap_kludge = 0;
-
-	++cam->open_count;
-	file->private_data = dev;
-	mutex_unlock(&cam->busy_lock);
-	return 0;
-
- oops:
-	if (cam->decompressed_frame.data) {
-		rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
-		cam->decompressed_frame.data = NULL;
-	}
-	if (cam->raw_image) {
-		rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
-		cam->raw_image = NULL;
-	}
-	mutex_unlock(&cam->busy_lock);
-	put_cam(cam->ops);
-	return err;
-}
-
-static int cpia_close(struct file *file)
-{
-	struct  video_device *dev = file->private_data;
-	struct cam_data *cam = video_get_drvdata(dev);
-
-	if (cam->ops) {
-		/* Return ownership of /proc/cpia/videoX to root */
-		if(cam->proc_entry)
-			cam->proc_entry->uid = 0;
-
-		/* save camera state for later open (developers guide ch 3.5.3) */
-		save_camera_state(cam);
-
-		/* GotoLoPower */
-		goto_low_power(cam);
-
-		/* Update the camera status */
-		do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
-
-		/* cleanup internal state stuff */
-		free_frames(cam->frame);
-
-		/* close cpia */
-		cam->ops->close(cam->lowlevel_data);
-
-		put_cam(cam->ops);
-	}
-
-	if (--cam->open_count == 0) {
-		/* clean up capture-buffers */
-		if (cam->raw_image) {
-			rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
-			cam->raw_image = NULL;
-		}
-
-		if (cam->decompressed_frame.data) {
-			rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
-			cam->decompressed_frame.data = NULL;
-		}
-
-		if (cam->frame_buf)
-			free_frame_buf(cam);
-
-		if (!cam->ops)
-			kfree(cam);
-	}
-	file->private_data = NULL;
-
-	return 0;
-}
-
-static ssize_t cpia_read(struct file *file, char __user *buf,
-			 size_t count, loff_t *ppos)
-{
-	struct video_device *dev = file->private_data;
-	struct cam_data *cam = video_get_drvdata(dev);
-	int err;
-
-	/* make this _really_ smp and multithread-safe */
-	if (mutex_lock_interruptible(&cam->busy_lock))
-		return -EINTR;
-
-	if (!buf) {
-		DBG("buf NULL\n");
-		mutex_unlock(&cam->busy_lock);
-		return -EINVAL;
-	}
-
-	if (!count) {
-		DBG("count 0\n");
-		mutex_unlock(&cam->busy_lock);
-		return 0;
-	}
-
-	if (!cam->ops) {
-		DBG("ops NULL\n");
-		mutex_unlock(&cam->busy_lock);
-		return -ENODEV;
-	}
-
-	/* upload frame */
-	cam->decompressed_frame.state = FRAME_READY;
-	cam->mmap_kludge=0;
-	if((err = fetch_frame(cam)) != 0) {
-		DBG("ERROR from fetch_frame: %d\n", err);
-		mutex_unlock(&cam->busy_lock);
-		return err;
-	}
-	cam->decompressed_frame.state = FRAME_UNUSED;
-
-	/* copy data to user space */
-	if (cam->decompressed_frame.count > count) {
-		DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count,
-		    (unsigned long) count);
-		mutex_unlock(&cam->busy_lock);
-		return -EFAULT;
-	}
-	if (copy_to_user(buf, cam->decompressed_frame.data,
-			cam->decompressed_frame.count)) {
-		DBG("copy_to_user failed\n");
-		mutex_unlock(&cam->busy_lock);
-		return -EFAULT;
-	}
-
-	mutex_unlock(&cam->busy_lock);
-	return cam->decompressed_frame.count;
-}
-
-static long cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
-	struct video_device *dev = file->private_data;
-	struct cam_data *cam = video_get_drvdata(dev);
-	int retval = 0;
-
-	if (!cam || !cam->ops)
-		return -ENODEV;
-
-	/* make this _really_ smp-safe */
-	if (mutex_lock_interruptible(&cam->busy_lock))
-		return -EINTR;
-
-	/* DBG("cpia_ioctl: %u\n", cmd); */
-
-	switch (cmd) {
-	/* query capabilities */
-	case VIDIOCGCAP:
-	{
-		struct video_capability *b = arg;
-
-		DBG("VIDIOCGCAP\n");
-		strcpy(b->name, "CPiA Camera");
-		b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
-		b->channels = 1;
-		b->audios = 0;
-		b->maxwidth = 352;	/* VIDEOSIZE_CIF */
-		b->maxheight = 288;
-		b->minwidth = 48;	/* VIDEOSIZE_48_48 */
-		b->minheight = 48;
-		break;
-	}
-
-	/* get/set video source - we are a camera and nothing else */
-	case VIDIOCGCHAN:
-	{
-		struct video_channel *v = arg;
-
-		DBG("VIDIOCGCHAN\n");
-		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;
-		break;
-	}
-
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *v = arg;
-
-		DBG("VIDIOCSCHAN\n");
-		if (v->channel != 0)
-			retval = -EINVAL;
-		break;
-	}
-
-	/* image properties */
-	case VIDIOCGPICT:
-	{
-		struct video_picture *pic = arg;
-		DBG("VIDIOCGPICT\n");
-		*pic = cam->vp;
-		break;
-	}
-
-	case VIDIOCSPICT:
-	{
-		struct video_picture *vp = arg;
-
-		DBG("VIDIOCSPICT\n");
-
-		/* check validity */
-		DBG("palette: %d\n", vp->palette);
-		DBG("depth: %d\n", vp->depth);
-		if (!valid_mode(vp->palette, vp->depth)) {
-			retval = -EINVAL;
-			break;
-		}
-
-		mutex_lock(&cam->param_lock);
-		/* brightness, colour, contrast need no check 0-65535 */
-		cam->vp = *vp;
-		/* update cam->params.colourParams */
-		cam->params.colourParams.brightness = vp->brightness*100/65535;
-		cam->params.colourParams.contrast = vp->contrast*100/65535;
-		cam->params.colourParams.saturation = vp->colour*100/65535;
-		/* contrast is in steps of 8, so round */
-		cam->params.colourParams.contrast =
-			((cam->params.colourParams.contrast + 3) / 8) * 8;
-		if (cam->params.version.firmwareVersion == 1 &&
-		    cam->params.version.firmwareRevision == 2 &&
-		    cam->params.colourParams.contrast > 80) {
-			/* 1-02 firmware limits contrast to 80 */
-			cam->params.colourParams.contrast = 80;
-		}
-
-		/* Adjust flicker control if necessary */
-		if(cam->params.flickerControl.allowableOverExposure < 0)
-			cam->params.flickerControl.allowableOverExposure =
-				-find_over_exposure(cam->params.colourParams.brightness);
-		if(cam->params.flickerControl.flickerMode != 0)
-			cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
-
-
-		/* queue command to update camera */
-		cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
-		mutex_unlock(&cam->param_lock);
-		DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n",
-		    vp->depth, vp->palette, vp->brightness, vp->hue, vp->colour,
-		    vp->contrast);
-		break;
-	}
-
-	/* get/set capture window */
-	case VIDIOCGWIN:
-	{
-		struct video_window *vw = arg;
-		DBG("VIDIOCGWIN\n");
-
-		*vw = cam->vw;
-		break;
-	}
-
-	case VIDIOCSWIN:
-	{
-		/* copy_from_user, check validity, copy to internal structure */
-		struct video_window *vw = arg;
-		DBG("VIDIOCSWIN\n");
-
-		if (vw->clipcount != 0) {    /* clipping not supported */
-			retval = -EINVAL;
-			break;
-		}
-		if (vw->clips != NULL) {     /* clipping not supported */
-			retval = -EINVAL;
-			break;
-		}
-
-		/* we set the video window to something smaller or equal to what
-		* is requested by the user???
-		*/
-		mutex_lock(&cam->param_lock);
-		if (vw->width != cam->vw.width || vw->height != cam->vw.height) {
-			int video_size = match_videosize(vw->width, vw->height);
-
-			if (video_size < 0) {
-				retval = -EINVAL;
-				mutex_unlock(&cam->param_lock);
-				break;
-			}
-			cam->video_size = video_size;
-
-			/* video size is changing, reset the subcapture area */
-			memset(&cam->vc, 0, sizeof(cam->vc));
-
-			set_vw_size(cam);
-			DBG("%d / %d\n", cam->vw.width, cam->vw.height);
-			cam->cmd_queue |= COMMAND_SETFORMAT;
-		}
-
-		mutex_unlock(&cam->param_lock);
-
-		/* setformat ignored by camera during streaming,
-		 * so stop/dispatch/start */
-		if (cam->cmd_queue & COMMAND_SETFORMAT) {
-			DBG("\n");
-			dispatch_commands(cam);
-		}
-		DBG("%d/%d:%d\n", cam->video_size,
-		    cam->vw.width, cam->vw.height);
-		break;
-	}
-
-	/* mmap interface */
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *vm = arg;
-		int i;
-
-		DBG("VIDIOCGMBUF\n");
-		memset(vm, 0, sizeof(*vm));
-		vm->size = CPIA_MAX_FRAME_SIZE*FRAME_NUM;
-		vm->frames = FRAME_NUM;
-		for (i = 0; i < FRAME_NUM; i++)
-			vm->offsets[i] = CPIA_MAX_FRAME_SIZE * i;
-		break;
-	}
-
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap *vm = arg;
-		int video_size;
-
-		DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm->format, vm->frame,
-		    vm->width, vm->height);
-		if (vm->frame<0||vm->frame>=FRAME_NUM) {
-			retval = -EINVAL;
-			break;
-		}
-
-		/* set video format */
-		cam->vp.palette = vm->format;
-		switch(vm->format) {
-		case VIDEO_PALETTE_GREY:
-			cam->vp.depth=8;
-			break;
-		case VIDEO_PALETTE_RGB555:
-		case VIDEO_PALETTE_RGB565:
-		case VIDEO_PALETTE_YUV422:
-		case VIDEO_PALETTE_YUYV:
-		case VIDEO_PALETTE_UYVY:
-			cam->vp.depth = 16;
-			break;
-		case VIDEO_PALETTE_RGB24:
-			cam->vp.depth = 24;
-			break;
-		case VIDEO_PALETTE_RGB32:
-			cam->vp.depth = 32;
-			break;
-		default:
-			retval = -EINVAL;
-			break;
-		}
-		if (retval)
-			break;
-
-		/* set video size */
-		video_size = match_videosize(vm->width, vm->height);
-		if (video_size < 0) {
-			retval = -EINVAL;
-			break;
-		}
-		if (video_size != cam->video_size) {
-			cam->video_size = video_size;
-
-			/* video size is changing, reset the subcapture area */
-			memset(&cam->vc, 0, sizeof(cam->vc));
-
-			set_vw_size(cam);
-			cam->cmd_queue |= COMMAND_SETFORMAT;
-			dispatch_commands(cam);
-		}
-		/* according to v4l-spec we must start streaming here */
-		cam->mmap_kludge = 1;
-		retval = capture_frame(cam, vm);
-
-		break;
-	}
-
-	case VIDIOCSYNC:
-	{
-		int *frame = arg;
-
-		//DBG("VIDIOCSYNC: %d\n", *frame);
-
-		if (*frame<0 || *frame >= FRAME_NUM) {
-			retval = -EINVAL;
-			break;
-		}
-
-		switch (cam->frame[*frame].state) {
-		case FRAME_UNUSED:
-		case FRAME_READY:
-		case FRAME_GRABBING:
-			DBG("sync to unused frame %d\n", *frame);
-			retval = -EINVAL;
-			break;
-
-		case FRAME_DONE:
-			cam->frame[*frame].state = FRAME_UNUSED;
-			//DBG("VIDIOCSYNC: %d synced\n", *frame);
-			break;
-		}
-		if (retval == -EINTR) {
-			/* FIXME - xawtv does not handle this nice */
-			retval = 0;
-		}
-		break;
-	}
-
-	case VIDIOCGCAPTURE:
-	{
-		struct video_capture *vc = arg;
-
-		DBG("VIDIOCGCAPTURE\n");
-
-		*vc = cam->vc;
-
-		break;
-	}
-
-	case VIDIOCSCAPTURE:
-	{
-		struct video_capture *vc = arg;
-
-		DBG("VIDIOCSCAPTURE\n");
-
-		if (vc->decimation != 0) {    /* How should this be used? */
-			retval = -EINVAL;
-			break;
-		}
-		if (vc->flags != 0) {     /* Even/odd grab not supported */
-			retval = -EINVAL;
-			break;
-		}
-
-		/* Clip to the resolution we can set for the ROI
-		   (every 8 columns and 4 rows) */
-		vc->x      = vc->x      & ~(__u32)7;
-		vc->y      = vc->y      & ~(__u32)3;
-		vc->width  = vc->width  & ~(__u32)7;
-		vc->height = vc->height & ~(__u32)3;
-
-		if(vc->width == 0 || vc->height == 0 ||
-		   vc->x + vc->width  > cam->vw.width ||
-		   vc->y + vc->height > cam->vw.height) {
-			retval = -EINVAL;
-			break;
-		}
-
-		DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height);
-
-		mutex_lock(&cam->param_lock);
-
-		cam->vc.x      = vc->x;
-		cam->vc.y      = vc->y;
-		cam->vc.width  = vc->width;
-		cam->vc.height = vc->height;
-
-		set_vw_size(cam);
-		cam->cmd_queue |= COMMAND_SETFORMAT;
-
-		mutex_unlock(&cam->param_lock);
-
-		/* setformat ignored by camera during streaming,
-		 * so stop/dispatch/start */
-		dispatch_commands(cam);
-		break;
-	}
-
-	case VIDIOCGUNIT:
-	{
-		struct video_unit *vu = arg;
-
-		DBG("VIDIOCGUNIT\n");
-
-		vu->video    = cam->vdev.minor;
-		vu->vbi      = VIDEO_NO_UNIT;
-		vu->radio    = VIDEO_NO_UNIT;
-		vu->audio    = VIDEO_NO_UNIT;
-		vu->teletext = VIDEO_NO_UNIT;
-
-		break;
-	}
-
-
-	/* pointless to implement overlay with this camera */
-	case VIDIOCCAPTURE:
-	case VIDIOCGFBUF:
-	case VIDIOCSFBUF:
-	case VIDIOCKEY:
-	/* tuner interface - we have none */
-	case VIDIOCGTUNER:
-	case VIDIOCSTUNER:
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-	/* audio interface - we have none */
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-		retval = -EINVAL;
-		break;
-	default:
-		retval = -ENOIOCTLCMD;
-		break;
-	}
-
-	mutex_unlock(&cam->busy_lock);
-	return retval;
-}
-
-static long cpia_ioctl(struct file *file,
-		     unsigned int cmd, unsigned long arg)
-{
-	return video_usercopy(file, cmd, arg, cpia_do_ioctl);
-}
-
-
-/* FIXME */
-static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *dev = file->private_data;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end - vma->vm_start;
-	unsigned long page, pos;
-	struct cam_data *cam = video_get_drvdata(dev);
-	int retval;
-
-	if (!cam || !cam->ops)
-		return -ENODEV;
-
-	DBG("cpia_mmap: %ld\n", size);
-
-	if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE)
-		return -EINVAL;
-
-	/* make this _really_ smp-safe */
-	if (mutex_lock_interruptible(&cam->busy_lock))
-		return -EINTR;
-
-	if (!cam->frame_buf) {	/* we do lazy allocation */
-		if ((retval = allocate_frame_buf(cam))) {
-			mutex_unlock(&cam->busy_lock);
-			return retval;
-		}
-	}
-
-	pos = (unsigned long)(cam->frame_buf);
-	while (size > 0) {
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			mutex_unlock(&cam->busy_lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	DBG("cpia_mmap: %ld\n", size);
-	mutex_unlock(&cam->busy_lock);
-
-	return 0;
-}
-
-static const struct v4l2_file_operations cpia_fops = {
-	.owner		= THIS_MODULE,
-	.open		= cpia_open,
-	.release       	= cpia_close,
-	.read		= cpia_read,
-	.mmap		= cpia_mmap,
-	.ioctl          = cpia_ioctl,
-};
-
-static struct video_device cpia_template = {
-	.name		= "CPiA Camera",
-	.fops           = &cpia_fops,
-	.release 	= video_device_release_empty,
-};
-
-/* initialise cam_data structure  */
-static void reset_camera_struct(struct cam_data *cam)
-{
-	/* The following parameter values are the defaults from
-	 * "Software Developer's Guide for CPiA Cameras".  Any changes
-	 * to the defaults are noted in comments. */
-	cam->params.colourParams.brightness = 50;
-	cam->params.colourParams.contrast = 48;
-	cam->params.colourParams.saturation = 50;
-	cam->params.exposure.gainMode = 4;
-	cam->params.exposure.expMode = 2;		/* AEC */
-	cam->params.exposure.compMode = 1;
-	cam->params.exposure.centreWeight = 1;
-	cam->params.exposure.gain = 0;
-	cam->params.exposure.fineExp = 0;
-	cam->params.exposure.coarseExpLo = 185;
-	cam->params.exposure.coarseExpHi = 0;
-	cam->params.exposure.redComp = COMP_RED;
-	cam->params.exposure.green1Comp = COMP_GREEN1;
-	cam->params.exposure.green2Comp = COMP_GREEN2;
-	cam->params.exposure.blueComp = COMP_BLUE;
-	cam->params.colourBalance.balanceMode = 2;	/* ACB */
-	cam->params.colourBalance.redGain = 32;
-	cam->params.colourBalance.greenGain = 6;
-	cam->params.colourBalance.blueGain = 92;
-	cam->params.apcor.gain1 = 0x18;
-	cam->params.apcor.gain2 = 0x16;
-	cam->params.apcor.gain4 = 0x24;
-	cam->params.apcor.gain8 = 0x34;
-	cam->params.flickerControl.flickerMode = 0;
-	cam->params.flickerControl.disabled = 1;
-
-	cam->params.flickerControl.coarseJump =
-		flicker_jumps[cam->mainsFreq]
-			     [cam->params.sensorFps.baserate]
-			     [cam->params.sensorFps.divisor];
-	cam->params.flickerControl.allowableOverExposure =
-		-find_over_exposure(cam->params.colourParams.brightness);
-	cam->params.vlOffset.gain1 = 20;
-	cam->params.vlOffset.gain2 = 24;
-	cam->params.vlOffset.gain4 = 26;
-	cam->params.vlOffset.gain8 = 26;
-	cam->params.compressionParams.hysteresis = 3;
-	cam->params.compressionParams.threshMax = 11;
-	cam->params.compressionParams.smallStep = 1;
-	cam->params.compressionParams.largeStep = 3;
-	cam->params.compressionParams.decimationHysteresis = 2;
-	cam->params.compressionParams.frDiffStepThresh = 5;
-	cam->params.compressionParams.qDiffStepThresh = 3;
-	cam->params.compressionParams.decimationThreshMod = 2;
-	/* End of default values from Software Developer's Guide */
-
-	cam->transfer_rate = 0;
-	cam->exposure_status = EXPOSURE_NORMAL;
-
-	/* Set Sensor FPS to 15fps. This seems better than 30fps
-	 * for indoor lighting. */
-	cam->params.sensorFps.divisor = 1;
-	cam->params.sensorFps.baserate = 1;
-
-	cam->params.yuvThreshold.yThreshold = 6; /* From windows driver */
-	cam->params.yuvThreshold.uvThreshold = 6; /* From windows driver */
-
-	cam->params.format.subSample = SUBSAMPLE_422;
-	cam->params.format.yuvOrder = YUVORDER_YUYV;
-
-	cam->params.compression.mode = CPIA_COMPRESSION_AUTO;
-	cam->params.compressionTarget.frTargeting =
-		CPIA_COMPRESSION_TARGET_QUALITY;
-	cam->params.compressionTarget.targetFR = 15; /* From windows driver */
-	cam->params.compressionTarget.targetQ = 5; /* From windows driver */
-
-	cam->params.qx3.qx3_detected = 0;
-	cam->params.qx3.toplight = 0;
-	cam->params.qx3.bottomlight = 0;
-	cam->params.qx3.button = 0;
-	cam->params.qx3.cradled = 0;
-
-	cam->video_size = VIDEOSIZE_CIF;
-
-	cam->vp.colour = 32768;      /* 50% */
-	cam->vp.hue = 32768;         /* 50% */
-	cam->vp.brightness = 32768;  /* 50% */
-	cam->vp.contrast = 32768;    /* 50% */
-	cam->vp.whiteness = 0;       /* not used -> grayscale only */
-	cam->vp.depth = 24;          /* to be set by user */
-	cam->vp.palette = VIDEO_PALETTE_RGB24; /* to be set by user */
-
-	cam->vc.x = 0;
-	cam->vc.y = 0;
-	cam->vc.width = 0;
-	cam->vc.height = 0;
-
-	cam->vw.x = 0;
-	cam->vw.y = 0;
-	set_vw_size(cam);
-	cam->vw.chromakey = 0;
-	cam->vw.flags = 0;
-	cam->vw.clipcount = 0;
-	cam->vw.clips = NULL;
-
-	cam->cmd_queue = COMMAND_NONE;
-	cam->first_frame = 1;
-
-	return;
-}
-
-/* initialize cam_data structure  */
-static void init_camera_struct(struct cam_data *cam,
-			       struct cpia_camera_ops *ops )
-{
-	int i;
-
-	/* Default everything to 0 */
-	memset(cam, 0, sizeof(struct cam_data));
-
-	cam->ops = ops;
-	mutex_init(&cam->param_lock);
-	mutex_init(&cam->busy_lock);
-
-	reset_camera_struct(cam);
-
-	cam->proc_entry = NULL;
-
-	memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
-	video_set_drvdata(&cam->vdev, cam);
-
-	cam->curframe = 0;
-	for (i = 0; i < FRAME_NUM; i++) {
-		cam->frame[i].width = 0;
-		cam->frame[i].height = 0;
-		cam->frame[i].state = FRAME_UNUSED;
-		cam->frame[i].data = NULL;
-	}
-	cam->decompressed_frame.width = 0;
-	cam->decompressed_frame.height = 0;
-	cam->decompressed_frame.state = FRAME_UNUSED;
-	cam->decompressed_frame.data = NULL;
-}
-
-struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel)
-{
-	struct cam_data *camera;
-
-	if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL)
-		return NULL;
-
-
-	init_camera_struct( camera, ops );
-	camera->lowlevel_data = lowlevel;
-
-	/* register v4l device */
-	if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-		kfree(camera);
-		printk(KERN_DEBUG "video_register_device failed\n");
-		return NULL;
-	}
-
-	/* get version information from camera: open/reset/close */
-
-	/* open cpia */
-	if (camera->ops->open(camera->lowlevel_data))
-		return camera;
-
-	/* reset the camera */
-	if (reset_camera(camera) != 0) {
-		camera->ops->close(camera->lowlevel_data);
-		return camera;
-	}
-
-	/* close cpia */
-	camera->ops->close(camera->lowlevel_data);
-
-#ifdef CONFIG_PROC_FS
-	create_proc_cpia_cam(camera);
-#endif
-
-	printk(KERN_INFO "  CPiA Version: %d.%02d (%d.%d)\n",
-	       camera->params.version.firmwareVersion,
-	       camera->params.version.firmwareRevision,
-	       camera->params.version.vcVersion,
-	       camera->params.version.vcRevision);
-	printk(KERN_INFO "  CPiA PnP-ID: %04x:%04x:%04x\n",
-	       camera->params.pnpID.vendor,
-	       camera->params.pnpID.product,
-	       camera->params.pnpID.deviceRevision);
-	printk(KERN_INFO "  VP-Version: %d.%d %04x\n",
-	       camera->params.vpVersion.vpVersion,
-	       camera->params.vpVersion.vpRevision,
-	       camera->params.vpVersion.cameraHeadID);
-
-	return camera;
-}
-
-void cpia_unregister_camera(struct cam_data *cam)
-{
-	DBG("unregistering video\n");
-	video_unregister_device(&cam->vdev);
-	if (cam->open_count) {
-		put_cam(cam->ops);
-		DBG("camera open -- setting ops to NULL\n");
-		cam->ops = NULL;
-	}
-
-#ifdef CONFIG_PROC_FS
-	DBG("destroying /proc/cpia/%s\n", video_device_node_name(&cam->vdev));
-	destroy_proc_cpia_cam(cam);
-#endif
-	if (!cam->open_count) {
-		DBG("freeing camera\n");
-		kfree(cam);
-	}
-}
-
-static int __init cpia_init(void)
-{
-	printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
-	       CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
-
-	printk(KERN_WARNING "Since in-kernel colorspace conversion is not "
-	       "allowed, it is disabled by default now. Users should fix the "
-	       "applications in case they don't work without conversion "
-	       "reenabled by setting the 'colorspace_conv' module "
-	       "parameter to 1\n");
-
-#ifdef CONFIG_PROC_FS
-	proc_cpia_create();
-#endif
-
-	return 0;
-}
-
-static void __exit cpia_exit(void)
-{
-#ifdef CONFIG_PROC_FS
-	proc_cpia_destroy();
-#endif
-}
-
-module_init(cpia_init);
-module_exit(cpia_exit);
-
-/* Exported symbols for modules. */
-
-EXPORT_SYMBOL(cpia_register_camera);
-EXPORT_SYMBOL(cpia_unregister_camera);
diff --git a/drivers/staging/cpia/cpia.h b/drivers/staging/cpia/cpia.h
deleted file mode 100644
index 8f0cfee..0000000
--- a/drivers/staging/cpia/cpia.h
+++ /dev/null
@@ -1,432 +0,0 @@
-#ifndef cpia_h
-#define cpia_h
-
-/*
- * CPiA Parallel Port Video4Linux driver
- *
- * Supports CPiA based parallel port Video Camera's.
- *
- * (C) Copyright 1999 Bas Huisman,
- *                    Peter Pregler,
- *                    Scott J. Bertin,
- *                    VLSI Vision Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define CPIA_MAJ_VER	1
-#define CPIA_MIN_VER   2
-#define CPIA_PATCH_VER	3
-
-#define CPIA_PP_MAJ_VER       CPIA_MAJ_VER
-#define CPIA_PP_MIN_VER       CPIA_MIN_VER
-#define CPIA_PP_PATCH_VER     CPIA_PATCH_VER
-
-#define CPIA_USB_MAJ_VER      CPIA_MAJ_VER
-#define CPIA_USB_MIN_VER      CPIA_MIN_VER
-#define CPIA_USB_PATCH_VER    CPIA_PATCH_VER
-
-#define CPIA_MAX_FRAME_SIZE_UNALIGNED	(352 * 288 * 4)   /* CIF at RGB32 */
-#define CPIA_MAX_FRAME_SIZE	((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */
-
-#ifdef __KERNEL__
-
-#include <asm/uaccess.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-
-struct cpia_camera_ops
-{
-	/* open sets privdata to point to structure for this camera.
-	 * Returns negative value on error, otherwise 0.
-	 */
-	int (*open)(void *privdata);
-
-	/* Registers callback function cb to be called with cbdata
-	 * when an image is ready.  If cb is NULL, only single image grabs
-	 * should be used.  cb should immediately call streamRead to read
-	 * the data or data may be lost. Returns negative value on error,
-	 * otherwise 0.
-	 */
-	int (*registerCallback)(void *privdata, void (*cb)(void *cbdata),
-				void *cbdata);
-
-	/* transferCmd sends commands to the camera.  command MUST point to
-	 * an  8 byte buffer in kernel space. data can be NULL if no extra
-	 * data is needed.  The size of the data is given by the last 2
-	 * bytes of command.  data must also point to memory in kernel space.
-	 * Returns negative value on error, otherwise 0.
-	 */
-	int (*transferCmd)(void *privdata, u8 *command, u8 *data);
-
-	/* streamStart initiates stream capture mode.
-	 * Returns negative value on error, otherwise 0.
-	 */
-	int (*streamStart)(void *privdata);
-
-	/* streamStop terminates stream capture mode.
-	 * Returns negative value on error, otherwise 0.
-	 */
-	int (*streamStop)(void *privdata);
-
-	/* streamRead reads a frame from the camera.  buffer points to a
-	 * buffer large enough to hold a complete frame in kernel space.
-	 * noblock indicates if this should be a non blocking read.
-	 * Returns the number of bytes read, or negative value on error.
-	 */
-	int (*streamRead)(void *privdata, u8 *buffer, int noblock);
-
-	/* close disables the device until open() is called again.
-	 * Returns negative value on error, otherwise 0.
-	 */
-	int (*close)(void *privdata);
-
-	/* If wait_for_stream_ready is non-zero, wait until the streamState
-	 * is STREAM_READY before calling streamRead.
-	 */
-	int wait_for_stream_ready;
-
-	/*
-	 * Used to maintain lowlevel module usage counts
-	 */
-	struct module *owner;
-};
-
-struct cpia_frame {
-	u8 *data;
-	int count;
-	int width;
-	int height;
-	volatile int state;
-};
-
-struct cam_params {
-	struct {
-		u8 firmwareVersion;
-		u8 firmwareRevision;
-		u8 vcVersion;
-		u8 vcRevision;
-	} version;
-	struct {
-		u16 vendor;
-		u16 product;
-		u16 deviceRevision;
-	} pnpID;
-	struct {
-		u8 vpVersion;
-		u8 vpRevision;
-		u16 cameraHeadID;
-	} vpVersion;
-	struct {
-		u8 systemState;
-		u8 grabState;
-		u8 streamState;
-		u8 fatalError;
-		u8 cmdError;
-		u8 debugFlags;
-		u8 vpStatus;
-		u8 errorCode;
-	} status;
-	struct {
-		u8 brightness;
-		u8 contrast;
-		u8 saturation;
-	} colourParams;
-	struct {
-		u8 gainMode;
-		u8 expMode;
-		u8 compMode;
-		u8 centreWeight;
-		u8 gain;
-		u8 fineExp;
-		u8 coarseExpLo;
-		u8 coarseExpHi;
-		u8 redComp;
-		u8 green1Comp;
-		u8 green2Comp;
-		u8 blueComp;
-	} exposure;
-	struct {
-		u8 balanceMode;
-		u8 redGain;
-		u8 greenGain;
-		u8 blueGain;
-	} colourBalance;
-	struct {
-		u8 divisor;
-		u8 baserate;
-	} sensorFps;
-	struct {
-		u8 gain1;
-		u8 gain2;
-		u8 gain4;
-		u8 gain8;
-	} apcor;
-	struct {
-		u8 disabled;
-		u8 flickerMode;
-		u8 coarseJump;
-		int allowableOverExposure;
-	} flickerControl;
-	struct {
-		u8 gain1;
-		u8 gain2;
-		u8 gain4;
-		u8 gain8;
-	} vlOffset;
-	struct {
-		u8 mode;
-		u8 decimation;
-	} compression;
-	struct {
-		u8 frTargeting;
-		u8 targetFR;
-		u8 targetQ;
-	} compressionTarget;
-	struct {
-		u8 yThreshold;
-		u8 uvThreshold;
-	} yuvThreshold;
-	struct {
-		u8 hysteresis;
-		u8 threshMax;
-		u8 smallStep;
-		u8 largeStep;
-		u8 decimationHysteresis;
-		u8 frDiffStepThresh;
-		u8 qDiffStepThresh;
-		u8 decimationThreshMod;
-	} compressionParams;
-	struct {
-		u8 videoSize;		/* CIF/QCIF */
-		u8 subSample;
-		u8 yuvOrder;
-	} format;
-	struct {                        /* Intel QX3 specific data */
-		u8 qx3_detected;        /* a QX3 is present */
-		u8 toplight;            /* top light lit , R/W */
-		u8 bottomlight;         /* bottom light lit, R/W */
-		u8 button;              /* snapshot button pressed (R/O) */
-		u8 cradled;             /* microscope is in cradle (R/O) */
-	} qx3;
-	struct {
-		u8 colStart;		/* skip first 8*colStart pixels */
-		u8 colEnd;		/* finish at 8*colEnd pixels */
-		u8 rowStart;		/* skip first 4*rowStart lines */
-		u8 rowEnd;		/* finish at 4*rowEnd lines */
-	} roi;
-	u8 ecpTiming;
-	u8 streamStartLine;
-};
-
-enum v4l_camstates {
-	CPIA_V4L_IDLE = 0,
-	CPIA_V4L_ERROR,
-	CPIA_V4L_COMMAND,
-	CPIA_V4L_GRABBING,
-	CPIA_V4L_STREAMING,
-	CPIA_V4L_STREAMING_PAUSED,
-};
-
-#define FRAME_NUM	2	/* double buffering for now */
-
-struct cam_data {
-	struct list_head cam_data_list;
-
-	struct mutex busy_lock;		/* guard against SMP multithreading */
-	struct cpia_camera_ops *ops;	/* lowlevel driver operations */
-	void *lowlevel_data;		/* private data for lowlevel driver */
-	u8 *raw_image;			/* buffer for raw image data */
-	struct cpia_frame decompressed_frame;
-					/* buffer to hold decompressed frame */
-	int image_size;			/* sizeof last decompressed image */
-	int open_count;			/* # of process that have camera open */
-
-				/* camera status */
-	int fps;			/* actual fps reported by the camera */
-	int transfer_rate;		/* transfer rate from camera in kB/s */
-	u8 mainsFreq;			/* for flicker control */
-
-				/* proc interface */
-	struct mutex param_lock;	/* params lock for this camera */
-	struct cam_params params;	/* camera settings */
-	struct proc_dir_entry *proc_entry;	/* /proc/cpia/videoX */
-
-					/* v4l */
-	int video_size;			/* VIDEO_SIZE_ */
-	volatile enum v4l_camstates camstate;	/* v4l layer status */
-	struct video_device vdev;	/* v4l videodev */
-	struct video_picture vp;	/* v4l camera settings */
-	struct video_window vw;		/* v4l capture area */
-	struct video_capture vc;       	/* v4l subcapture area */
-
-				/* mmap interface */
-	int curframe;			/* the current frame to grab into */
-	u8 *frame_buf;			/* frame buffer data */
-	struct cpia_frame frame[FRAME_NUM];
-				/* FRAME_NUM-buffering, so we need a array */
-
-	int first_frame;
-	int mmap_kludge;		/* 'wrong' byte order for mmap */
-	volatile u32 cmd_queue;		/* queued commands */
-	int exposure_status;		/* EXPOSURE_* */
-	int exposure_count;		/* number of frames at this status */
-};
-
-/* cpia_register_camera is called by low level driver for each camera.
- * A unique camera number is returned, or a negative value on error */
-struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel);
-
-/* cpia_unregister_camera is called by low level driver when a camera
- * is removed.  This must not fail. */
-void cpia_unregister_camera(struct cam_data *cam);
-
-/* raw CIF + 64 byte header + (2 bytes line_length + EOL) per line + 4*EOI +
- * one byte 16bit DMA alignment
- */
-#define CPIA_MAX_IMAGE_SIZE ((352*288*2)+64+(288*3)+5)
-
-/* constant value's */
-#define MAGIC_0		0x19
-#define MAGIC_1		0x68
-#define DATA_IN		0xC0
-#define DATA_OUT	0x40
-#define VIDEOSIZE_QCIF	0	/* 176x144 */
-#define VIDEOSIZE_CIF	1	/* 352x288 */
-#define VIDEOSIZE_SIF	2	/* 320x240 */
-#define VIDEOSIZE_QSIF	3	/* 160x120 */
-#define VIDEOSIZE_48_48		4 /* where no one has gone before, iconsize! */
-#define VIDEOSIZE_64_48		5
-#define VIDEOSIZE_128_96	6
-#define VIDEOSIZE_160_120	VIDEOSIZE_QSIF
-#define VIDEOSIZE_176_144	VIDEOSIZE_QCIF
-#define VIDEOSIZE_192_144	7
-#define VIDEOSIZE_224_168	8
-#define VIDEOSIZE_256_192	9
-#define VIDEOSIZE_288_216	10
-#define VIDEOSIZE_320_240	VIDEOSIZE_SIF
-#define VIDEOSIZE_352_288	VIDEOSIZE_CIF
-#define VIDEOSIZE_88_72		11 /* quarter CIF */
-#define SUBSAMPLE_420	0
-#define SUBSAMPLE_422	1
-#define YUVORDER_YUYV	0
-#define YUVORDER_UYVY	1
-#define NOT_COMPRESSED	0
-#define COMPRESSED	1
-#define NO_DECIMATION	0
-#define DECIMATION_ENAB	1
-#define EOI		0xff	/* End Of Image */
-#define EOL		0xfd	/* End Of Line */
-#define FRAME_HEADER_SIZE	64
-
-/* Image grab modes */
-#define CPIA_GRAB_SINGLE	0
-#define CPIA_GRAB_CONTINUOUS	1
-
-/* Compression parameters */
-#define CPIA_COMPRESSION_NONE	0
-#define CPIA_COMPRESSION_AUTO	1
-#define CPIA_COMPRESSION_MANUAL	2
-#define CPIA_COMPRESSION_TARGET_QUALITY         0
-#define CPIA_COMPRESSION_TARGET_FRAMERATE       1
-
-/* Return offsets for GetCameraState */
-#define SYSTEMSTATE	0
-#define GRABSTATE	1
-#define STREAMSTATE	2
-#define FATALERROR	3
-#define CMDERROR	4
-#define DEBUGFLAGS	5
-#define VPSTATUS	6
-#define ERRORCODE	7
-
-/* SystemState */
-#define UNINITIALISED_STATE	0
-#define PASS_THROUGH_STATE	1
-#define LO_POWER_STATE		2
-#define HI_POWER_STATE		3
-#define WARM_BOOT_STATE		4
-
-/* GrabState */
-#define GRAB_IDLE		0
-#define GRAB_ACTIVE		1
-#define GRAB_DONE		2
-
-/* StreamState */
-#define STREAM_NOT_READY	0
-#define STREAM_READY		1
-#define STREAM_OPEN		2
-#define STREAM_PAUSED		3
-#define STREAM_FINISHED		4
-
-/* Fatal Error, CmdError, and DebugFlags */
-#define CPIA_FLAG	  1
-#define SYSTEM_FLAG	  2
-#define INT_CTRL_FLAG	  4
-#define PROCESS_FLAG	  8
-#define COM_FLAG	 16
-#define VP_CTRL_FLAG	 32
-#define CAPTURE_FLAG	 64
-#define DEBUG_FLAG	128
-
-/* VPStatus */
-#define VP_STATE_OK			0x00
-
-#define VP_STATE_FAILED_VIDEOINIT	0x01
-#define VP_STATE_FAILED_AECACBINIT	0x02
-#define VP_STATE_AEC_MAX		0x04
-#define VP_STATE_ACB_BMAX		0x08
-
-#define VP_STATE_ACB_RMIN		0x10
-#define VP_STATE_ACB_GMIN		0x20
-#define VP_STATE_ACB_RMAX		0x40
-#define VP_STATE_ACB_GMAX		0x80
-
-/* default (minimum) compensation values */
-#define COMP_RED        220
-#define COMP_GREEN1     214
-#define COMP_GREEN2     COMP_GREEN1
-#define COMP_BLUE       230
-
-/* exposure status */
-#define EXPOSURE_VERY_LIGHT 0
-#define EXPOSURE_LIGHT      1
-#define EXPOSURE_NORMAL     2
-#define EXPOSURE_DARK       3
-#define EXPOSURE_VERY_DARK  4
-
-/* ErrorCode */
-#define ERROR_FLICKER_BELOW_MIN_EXP     0x01 /*flicker exposure got below minimum exposure */
-#define ALOG(fmt,args...) printk(fmt, ##args)
-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
-
-#ifdef _CPIA_DEBUG_
-#define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
-#else
-#define DBG(fmn,args...) do {} while(0)
-#endif
-
-#define DEB_BYTE(p)\
-  DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\
-      (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\
-	(p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
-
-#endif /* __KERNEL__ */
-
-#endif /* cpia_h */
diff --git a/drivers/staging/cpia/cpia_pp.c b/drivers/staging/cpia/cpia_pp.c
deleted file mode 100644
index f5604c1..0000000
--- a/drivers/staging/cpia/cpia_pp.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
- * cpia_pp CPiA Parallel Port driver
- *
- * Supports CPiA based parallel port Video Camera's.
- *
- * (C) Copyright 1999 Bas Huisman <bhuism@cs.utwente.nl>
- * (C) Copyright 1999-2000 Scott J. Bertin <sbertin@securenym.net>,
- * (C) Copyright 1999-2000 Peter Pregler <Peter_Pregler@email.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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 _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_  1 */
-
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/kernel.h>
-#include <linux/parport.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <linux/kmod.h>
-
-/* #define _CPIA_DEBUG_		define for verbose debug output */
-#include "cpia.h"
-
-static int cpia_pp_open(void *privdata);
-static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
-				    void *cbdata);
-static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
-static int cpia_pp_streamStart(void *privdata);
-static int cpia_pp_streamStop(void *privdata);
-static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
-static int cpia_pp_close(void *privdata);
-
-
-#define ABOUT "Parallel port driver for Vision CPiA based cameras"
-
-#define PACKET_LENGTH  8
-
-/* Magic numbers for defining port-device mappings */
-#define PPCPIA_PARPORT_UNSPEC -4
-#define PPCPIA_PARPORT_AUTO -3
-#define PPCPIA_PARPORT_OFF -2
-#define PPCPIA_PARPORT_NONE -1
-
-static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};
-static char *parport[PARPORT_MAX] = {NULL,};
-
-MODULE_AUTHOR("B. Huisman <bhuism@cs.utwente.nl> & Peter Pregler <Peter_Pregler@email.com>");
-MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras");
-MODULE_LICENSE("GPL");
-
-module_param_array(parport, charp, NULL, 0);
-MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp.");
-
-struct pp_cam_entry {
-	struct pardevice *pdev;
-	struct parport *port;
-	struct work_struct cb_task;
-	void (*cb_func)(void *cbdata);
-	void *cb_data;
-	int open_count;
-	wait_queue_head_t wq_stream;
-	/* image state flags */
-	int image_ready;	/* we got an interrupt */
-	int image_complete;	/* we have seen 4 EOI */
-
-	int streaming; /* we are in streaming mode */
-	int stream_irq;
-};
-
-static struct cpia_camera_ops cpia_pp_ops =
-{
-	cpia_pp_open,
-	cpia_pp_registerCallback,
-	cpia_pp_transferCmd,
-	cpia_pp_streamStart,
-	cpia_pp_streamStop,
-	cpia_pp_streamRead,
-	cpia_pp_close,
-	1,
-	THIS_MODULE
-};
-
-static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_pp;
-
-/* FIXME */
-static void cpia_parport_enable_irq( struct parport *port ) {
-	parport_enable_irq(port);
-	mdelay(10);
-	return;
-}
-
-static void cpia_parport_disable_irq( struct parport *port ) {
-	parport_disable_irq(port);
-	mdelay(10);
-	return;
-}
-
-/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility
- * Link Flag during negotiation */
-#define UPLOAD_FLAG  0x08
-#define NIBBLE_TRANSFER 0x01
-#define ECP_TRANSFER 0x03
-
-#define PARPORT_CHUNK_SIZE	PAGE_SIZE
-
-
-static void cpia_pp_run_callback(struct work_struct *work)
-{
-	void (*cb_func)(void *cbdata);
-	void *cb_data;
-	struct pp_cam_entry *cam;
-
-	cam = container_of(work, struct pp_cam_entry, cb_task);
-	cb_func = cam->cb_func;
-	cb_data = cam->cb_data;
-
-	cb_func(cb_data);
-}
-
-/****************************************************************************
- *
- *  CPiA-specific  low-level parport functions for nibble uploads
- *
- ***************************************************************************/
-/*  CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */
-/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */
-
-static size_t cpia_read_nibble (struct parport *port,
-			 void *buffer, size_t len,
-			 int flags)
-{
-	/* adapted verbatim, with one change, from
-	   parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */
-
-	unsigned char *buf = buffer;
-	int i;
-	unsigned char byte = 0;
-
-	len *= 2; /* in nibbles */
-	for (i=0; i < len; i++) {
-		unsigned char nibble;
-
-		/* The CPiA firmware suppresses the use of nDataAvail (nFault LO)
-		 * after every second nibble to signal that more
-		 * data is available.  (the total number of Bytes that
-		 * should be sent is known; if too few are received, an error
-		 * will be recorded after a timeout).
-		 * This is incompatible with parport_ieee1284_read_nibble(),
-		 * which expects to find nFault LO after every second nibble.
-		 */
-
-		/* Solution: modify cpia_read_nibble to only check for
-		 * nDataAvail before the first nibble is sent.
-		 */
-
-		/* Does the error line indicate end of data? */
-		if (((i /*& 1*/) == 0) &&
-		    (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
-			DBG("%s: No more nibble data (%d bytes)\n",
-			    port->name, i/2);
-			goto end_of_data;
-		}
-
-		/* Event 7: Set nAutoFd low. */
-		parport_frob_control (port,
-				      PARPORT_CONTROL_AUTOFD,
-				      PARPORT_CONTROL_AUTOFD);
-
-		/* Event 9: nAck goes low. */
-		port->ieee1284.phase = IEEE1284_PH_REV_DATA;
-		if (parport_wait_peripheral (port,
-					     PARPORT_STATUS_ACK, 0)) {
-			/* Timeout -- no more data? */
-				 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
-				 port->name, i/2);
-			parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-			break;
-		}
-
-
-		/* Read a nibble. */
-		nibble = parport_read_status (port) >> 3;
-		nibble &= ~8;
-		if ((nibble & 0x10) == 0)
-			nibble |= 8;
-		nibble &= 0xf;
-
-		/* Event 10: Set nAutoFd high. */
-		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
-		/* Event 11: nAck goes high. */
-		if (parport_wait_peripheral (port,
-					     PARPORT_STATUS_ACK,
-					     PARPORT_STATUS_ACK)) {
-			/* Timeout -- no more data? */
-			DBG("%s: Nibble timeout at event 11\n",
-				 port->name);
-			break;
-		}
-
-		if (i & 1) {
-			/* Second nibble */
-			byte |= nibble << 4;
-			*buf++ = byte;
-		} else
-			byte = nibble;
-	}
-
-	if (i == len) {
-		/* Read the last nibble without checking data avail. */
-		if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
-		end_of_data:
-			/* Go to reverse idle phase. */
-			parport_frob_control (port,
-					      PARPORT_CONTROL_AUTOFD,
-					      PARPORT_CONTROL_AUTOFD);
-			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-		}
-		else
-			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
-	}
-
-	return i/2;
-}
-
-/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
- * (See CPiA Data sheet p. 31)
- *
- * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a
- * nonstandard variant of nibble mode which allows the same (mediocre)
- * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable
- * parallel ports, but works also for  non-TRISTATE-capable ports.
- * (Standard nibble mode only send 4 bits per cycle)
- *
- */
-
-static size_t cpia_read_nibble_stream(struct parport *port,
-			       void *buffer, size_t len,
-			       int flags)
-{
-	int i;
-	unsigned char *buf = buffer;
-	int endseen = 0;
-
-	for (i=0; i < len; i++) {
-		unsigned char nibble[2], byte = 0;
-		int j;
-
-		/* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */
-		if (endseen > 3 )
-			break;
-
-		/* Event 7: Set nAutoFd low. */
-		parport_frob_control (port,
-				      PARPORT_CONTROL_AUTOFD,
-				      PARPORT_CONTROL_AUTOFD);
-
-		/* Event 9: nAck goes low. */
-		port->ieee1284.phase = IEEE1284_PH_REV_DATA;
-		if (parport_wait_peripheral (port,
-					     PARPORT_STATUS_ACK, 0)) {
-			/* Timeout -- no more data? */
-				 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
-				 port->name, i/2);
-			parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-			break;
-		}
-
-		/* Read lower nibble */
-		nibble[0] = parport_read_status (port) >>3;
-
-		/* Event 10: Set nAutoFd high. */
-		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
-		/* Event 11: nAck goes high. */
-		if (parport_wait_peripheral (port,
-					     PARPORT_STATUS_ACK,
-					     PARPORT_STATUS_ACK)) {
-			/* Timeout -- no more data? */
-			DBG("%s: Nibble timeout at event 11\n",
-				 port->name);
-			break;
-		}
-
-		/* Read upper nibble */
-		nibble[1] = parport_read_status (port) >>3;
-
-		/* reassemble the byte */
-		for (j = 0; j < 2 ; j++ ) {
-			nibble[j] &= ~8;
-			if ((nibble[j] & 0x10) == 0)
-				nibble[j] |= 8;
-			nibble[j] &= 0xf;
-		}
-		byte = (nibble[0] |(nibble[1] << 4));
-		*buf++ = byte;
-
-		if(byte == EOI)
-		  endseen++;
-		else
-		  endseen = 0;
-	}
-	return i;
-}
-
-/****************************************************************************
- *
- *  EndTransferMode
- *
- ***************************************************************************/
-static void EndTransferMode(struct pp_cam_entry *cam)
-{
-	parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
-}
-
-/****************************************************************************
- *
- *  ForwardSetup
- *
- ***************************************************************************/
-static int ForwardSetup(struct pp_cam_entry *cam)
-{
-	int retry;
-
-	/* The CPiA uses ECP protocol for Downloads from the Host to the camera.
-	 * This will be software-emulated if ECP hardware is not present
-	 */
-
-	/* the usual camera maximum response time is 10ms, but after receiving
-	 * some commands, it needs up to 40ms. (Data Sheet p. 32)*/
-
-	for(retry = 0; retry < 4; ++retry) {
-		if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {
-			break;
-		}
-		mdelay(10);
-	}
-	if(retry == 4) {
-		DBG("Unable to negotiate IEEE1284 ECP Download mode\n");
-		return -1;
-	}
-	return 0;
-}
-/****************************************************************************
- *
- *  ReverseSetup
- *
- ***************************************************************************/
-static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
-{
-	int retry;
-	int upload_mode, mode = IEEE1284_MODE_ECP;
-	int transfer_mode = ECP_TRANSFER;
-
-	if (!(cam->port->modes & PARPORT_MODE_ECP) &&
-	     !(cam->port->modes & PARPORT_MODE_TRISTATE)) {
-		mode = IEEE1284_MODE_NIBBLE;
-		transfer_mode = NIBBLE_TRANSFER;
-	}
-
-	upload_mode = mode;
-	if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;
-
-	/* the usual camera maximum response time is 10ms, but after
-	 * receiving some commands, it needs up to 40ms. */
-
-	for(retry = 0; retry < 4; ++retry) {
-		if(!parport_negotiate(cam->port, mode)) {
-			break;
-		}
-		mdelay(10);
-	}
-	if(retry == 4) {
-		if(extensibility)
-			DBG("Unable to negotiate upload extensibility mode\n");
-		else
-			DBG("Unable to negotiate upload mode\n");
-		return -1;
-	}
-	if(extensibility) cam->port->ieee1284.mode = upload_mode;
-	return 0;
-}
-
-/****************************************************************************
- *
- *  WritePacket
- *
- ***************************************************************************/
-static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size)
-{
-	int retval=0;
-	int size_written;
-
-	if (packet == NULL) {
-		return -EINVAL;
-	}
-	if (ForwardSetup(cam)) {
-		DBG("Write failed in setup\n");
-		return -EIO;
-	}
-	size_written = parport_write(cam->port, packet, size);
-	if(size_written != size) {
-		DBG("Write failed, wrote %d/%d\n", size_written, size);
-		retval = -EIO;
-	}
-	EndTransferMode(cam);
-	return retval;
-}
-
-/****************************************************************************
- *
- *  ReadPacket
- *
- ***************************************************************************/
-static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
-{
-	int retval=0;
-
-	if (packet == NULL) {
-		return -EINVAL;
-	}
-	if (ReverseSetup(cam, 0)) {
-		return -EIO;
-	}
-
-	/* support for CPiA variant nibble reads */
-	if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) {
-		if(cpia_read_nibble(cam->port, packet, size, 0) != size)
-			retval = -EIO;
-	} else {
-		if(parport_read(cam->port, packet, size) != size)
-			retval = -EIO;
-	}
-	EndTransferMode(cam);
-	return retval;
-}
-
-/****************************************************************************
- *
- *  cpia_pp_streamStart
- *
- ***************************************************************************/
-static int cpia_pp_streamStart(void *privdata)
-{
-	struct pp_cam_entry *cam = privdata;
-	DBG("\n");
-	cam->streaming=1;
-	cam->image_ready=0;
-	//if (ReverseSetup(cam,1)) return -EIO;
-	if(cam->stream_irq) cpia_parport_enable_irq(cam->port);
-	return 0;
-}
-
-/****************************************************************************
- *
- *  cpia_pp_streamStop
- *
- ***************************************************************************/
-static int cpia_pp_streamStop(void *privdata)
-{
-	struct pp_cam_entry *cam = privdata;
-
-	DBG("\n");
-	cam->streaming=0;
-	cpia_parport_disable_irq(cam->port);
-	//EndTransferMode(cam);
-
-	return 0;
-}
-
-/****************************************************************************
- *
- *  cpia_pp_streamRead
- *
- ***************************************************************************/
-static int cpia_pp_read(struct parport *port, u8 *buffer, int len)
-{
-	int bytes_read;
-
-	/* support for CPiA variant "nibble stream" reads */
-	if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE)
-		bytes_read = cpia_read_nibble_stream(port,buffer,len,0);
-	else {
-		int new_bytes;
-		for(bytes_read=0; bytes_read<len; bytes_read += new_bytes) {
-			new_bytes = parport_read(port, buffer+bytes_read,
-						 len-bytes_read);
-			if(new_bytes < 0) break;
-		}
-	}
-	return bytes_read;
-}
-
-static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
-{
-	struct pp_cam_entry *cam = privdata;
-	int read_bytes = 0;
-	int i, endseen, block_size, new_bytes;
-
-	if(cam == NULL) {
-		DBG("Internal driver error: cam is NULL\n");
-		return -EINVAL;
-	}
-	if(buffer == NULL) {
-		DBG("Internal driver error: buffer is NULL\n");
-		return -EINVAL;
-	}
-	//if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock);
-	if( cam->stream_irq ) {
-		DBG("%d\n", cam->image_ready);
-		cam->image_ready--;
-	}
-	cam->image_complete=0;
-	if (0/*cam->streaming*/) {
-		if(!cam->image_ready) {
-			if(noblock) return -EWOULDBLOCK;
-			interruptible_sleep_on(&cam->wq_stream);
-			if( signal_pending(current) ) return -EINTR;
-			DBG("%d\n", cam->image_ready);
-		}
-	} else {
-		if (ReverseSetup(cam, 1)) {
-			DBG("unable to ReverseSetup\n");
-			return -EIO;
-		}
-	}
-	endseen = 0;
-	block_size = PARPORT_CHUNK_SIZE;
-	while( !cam->image_complete ) {
-		cond_resched();
-
-		new_bytes = cpia_pp_read(cam->port, buffer, block_size );
-		if( new_bytes <= 0 ) {
-			break;
-		}
-		i=-1;
-		while(++i<new_bytes && endseen<4) {
-			if(*buffer==EOI) {
-				endseen++;
-			} else {
-				endseen=0;
-			}
-			buffer++;
-		}
-		read_bytes += i;
-		if( endseen==4 ) {
-			cam->image_complete=1;
-			break;
-		}
-		if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) {
-			block_size=CPIA_MAX_IMAGE_SIZE-read_bytes;
-		}
-	}
-	EndTransferMode(cam);
-	return cam->image_complete ? read_bytes : -EIO;
-}
-/****************************************************************************
- *
- *  cpia_pp_transferCmd
- *
- ***************************************************************************/
-static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
-{
-	int err;
-	int retval=0;
-	int databytes;
-	struct pp_cam_entry *cam = privdata;
-
-	if(cam == NULL) {
-		DBG("Internal driver error: cam is NULL\n");
-		return -EINVAL;
-	}
-	if(command == NULL) {
-		DBG("Internal driver error: command is NULL\n");
-		return -EINVAL;
-	}
-	databytes = (((int)command[7])<<8) | command[6];
-	if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) {
-		DBG("Error writing command\n");
-		return err;
-	}
-	if(command[0] == DATA_IN) {
-		u8 buffer[8];
-		if(data == NULL) {
-			DBG("Internal driver error: data is NULL\n");
-			return -EINVAL;
-		}
-		if((err = ReadPacket(cam, buffer, 8)) < 0) {
-			DBG("Error reading command result\n");
-		       return err;
-		}
-		memcpy(data, buffer, databytes);
-	} else if(command[0] == DATA_OUT) {
-		if(databytes > 0) {
-			if(data == NULL) {
-				DBG("Internal driver error: data is NULL\n");
-				retval = -EINVAL;
-			} else {
-				if((err=WritePacket(cam, data, databytes)) < 0){
-					DBG("Error writing command data\n");
-					return err;
-				}
-			}
-		}
-	} else {
-		DBG("Unexpected first byte of command: %x\n", command[0]);
-		retval = -EINVAL;
-	}
-	return retval;
-}
-
-/****************************************************************************
- *
- *  cpia_pp_open
- *
- ***************************************************************************/
-static int cpia_pp_open(void *privdata)
-{
-	struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;
-
-	if (cam == NULL)
-		return -EINVAL;
-
-	if(cam->open_count == 0) {
-		if (parport_claim(cam->pdev)) {
-			DBG("failed to claim the port\n");
-			return -EBUSY;
-		}
-		parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
-		parport_data_forward(cam->port);
-		parport_write_control(cam->port, PARPORT_CONTROL_SELECT);
-		udelay(50);
-		parport_write_control(cam->port,
-				      PARPORT_CONTROL_SELECT
-				      | PARPORT_CONTROL_INIT);
-	}
-
-	++cam->open_count;
-
-	return 0;
-}
-
-/****************************************************************************
- *
- *  cpia_pp_registerCallback
- *
- ***************************************************************************/
-static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata)
-{
-	struct pp_cam_entry *cam = privdata;
-	int retval = 0;
-
-	if(cam->port->irq != PARPORT_IRQ_NONE) {
-		cam->cb_func = cb;
-		cam->cb_data = cbdata;
-		INIT_WORK(&cam->cb_task, cpia_pp_run_callback);
-	} else {
-		retval = -1;
-	}
-	return retval;
-}
-
-/****************************************************************************
- *
- *  cpia_pp_close
- *
- ***************************************************************************/
-static int cpia_pp_close(void *privdata)
-{
-	struct pp_cam_entry *cam = privdata;
-	if (--cam->open_count == 0) {
-		parport_release(cam->pdev);
-	}
-	return 0;
-}
-
-/****************************************************************************
- *
- *  cpia_pp_register
- *
- ***************************************************************************/
-static int cpia_pp_register(struct parport *port)
-{
-	struct pardevice *pdev = NULL;
-	struct pp_cam_entry *cam;
-	struct cam_data *cpia;
-
-	if (!(port->modes & PARPORT_MODE_PCSPP)) {
-		LOG("port is not supported by CPiA driver\n");
-		return -ENXIO;
-	}
-
-	cam = kzalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
-	if (cam == NULL) {
-		LOG("failed to allocate camera structure\n");
-		return -ENOMEM;
-	}
-
-	pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
-				       NULL, 0, cam);
-
-	if (!pdev) {
-		LOG("failed to parport_register_device\n");
-		kfree(cam);
-		return -ENXIO;
-	}
-
-	cam->pdev = pdev;
-	cam->port = port;
-	init_waitqueue_head(&cam->wq_stream);
-
-	cam->streaming = 0;
-	cam->stream_irq = 0;
-
-	if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) {
-		LOG("failed to cpia_register_camera\n");
-		parport_unregister_device(pdev);
-		kfree(cam);
-		return -ENXIO;
-	}
-	spin_lock( &cam_list_lock_pp );
-	list_add( &cpia->cam_data_list, &cam_list );
-	spin_unlock( &cam_list_lock_pp );
-
-	return 0;
-}
-
-static void cpia_pp_detach (struct parport *port)
-{
-	struct list_head *tmp;
-	struct cam_data *cpia = NULL;
-	struct pp_cam_entry *cam;
-
-	spin_lock( &cam_list_lock_pp );
-	list_for_each (tmp, &cam_list) {
-		cpia = list_entry(tmp, struct cam_data, cam_data_list);
-		cam = (struct pp_cam_entry *) cpia->lowlevel_data;
-		if (cam && cam->port->number == port->number) {
-			list_del(&cpia->cam_data_list);
-			break;
-		}
-		cpia = NULL;
-	}
-	spin_unlock( &cam_list_lock_pp );
-
-	if (!cpia) {
-		DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
-		return;
-	}
-
-	cam = (struct pp_cam_entry *) cpia->lowlevel_data;
-	cpia_unregister_camera(cpia);
-	if(cam->open_count > 0)
-		cpia_pp_close(cam);
-	parport_unregister_device(cam->pdev);
-	cpia->lowlevel_data = NULL;
-	kfree(cam);
-}
-
-static void cpia_pp_attach (struct parport *port)
-{
-	unsigned int i;
-
-	switch (parport_nr[0])
-	{
-	case PPCPIA_PARPORT_UNSPEC:
-	case PPCPIA_PARPORT_AUTO:
-		if (port->probe_info[0].class != PARPORT_CLASS_MEDIA ||
-		    port->probe_info[0].cmdset == NULL ||
-		    strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0)
-			return;
-
-		cpia_pp_register(port);
-
-		break;
-
-	default:
-		for (i = 0; i < PARPORT_MAX; ++i) {
-			if (port->number == parport_nr[i]) {
-				cpia_pp_register(port);
-				break;
-			}
-		}
-		break;
-	}
-}
-
-static struct parport_driver cpia_pp_driver = {
-	.name = "cpia_pp",
-	.attach = cpia_pp_attach,
-	.detach = cpia_pp_detach,
-};
-
-static int __init cpia_pp_init(void)
-{
-	printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
-	       CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
-
-	if(parport_nr[0] == PPCPIA_PARPORT_OFF) {
-		printk("  disabled\n");
-		return 0;
-	}
-
-	spin_lock_init( &cam_list_lock_pp );
-
-	if (parport_register_driver (&cpia_pp_driver)) {
-		LOG ("unable to register with parport\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-static int __init cpia_init(void)
-{
-	if (parport[0]) {
-		/* The user gave some parameters.  Let's see what they were. */
-		if (!strncmp(parport[0], "auto", 4)) {
-			parport_nr[0] = PPCPIA_PARPORT_AUTO;
-		} else {
-			int n;
-			for (n = 0; n < PARPORT_MAX && parport[n]; n++) {
-				if (!strncmp(parport[n], "none", 4)) {
-					parport_nr[n] = PPCPIA_PARPORT_NONE;
-				} else {
-					char *ep;
-					unsigned long r = simple_strtoul(parport[n], &ep, 0);
-					if (ep != parport[n]) {
-						parport_nr[n] = r;
-					} else {
-						LOG("bad port specifier `%s'\n", parport[n]);
-						return -ENODEV;
-					}
-				}
-			}
-		}
-	}
-	return cpia_pp_init();
-}
-
-static void __exit cpia_cleanup(void)
-{
-	parport_unregister_driver(&cpia_pp_driver);
-	return;
-}
-
-module_init(cpia_init);
-module_exit(cpia_cleanup);
diff --git a/drivers/staging/cpia/cpia_usb.c b/drivers/staging/cpia/cpia_usb.c
deleted file mode 100644
index 58d193f..0000000
--- a/drivers/staging/cpia/cpia_usb.c
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * cpia_usb CPiA USB driver
- *
- * Supports CPiA based parallel port Video Camera's.
- *
- * Copyright (C) 1999        Jochen Scharrlach <Jochen.Scharrlach@schwaben.de>
- * Copyright (C) 1999, 2000  Johannes Erdfelt <johannes@erdfelt.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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 _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_  1 */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/usb.h>
-
-#include "cpia.h"
-
-#define USB_REQ_CPIA_GRAB_FRAME			0xC1
-#define USB_REQ_CPIA_UPLOAD_FRAME		0xC2
-#define  WAIT_FOR_NEXT_FRAME			0
-#define  FORCE_FRAME_UPLOAD			1
-
-#define FRAMES_PER_DESC		10
-#define FRAME_SIZE_PER_DESC	960	/* Shouldn't be hardcoded */
-#define CPIA_NUMSBUF		2
-#define STREAM_BUF_SIZE		(PAGE_SIZE * 4)
-#define SCRATCH_BUF_SIZE	(STREAM_BUF_SIZE * 2)
-
-struct cpia_sbuf {
-	char *data;
-	struct urb *urb;
-};
-
-#define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100)
-enum framebuf_status {
-	FRAME_EMPTY,
-	FRAME_READING,
-	FRAME_READY,
-	FRAME_ERROR,
-};
-
-struct framebuf {
-	int length;
-	enum framebuf_status status;
-	u8 data[FRAMEBUF_LEN];
-	struct framebuf *next;
-};
-
-struct usb_cpia {
-	/* Device structure */
-	struct usb_device *dev;
-
-	unsigned char iface;
-	wait_queue_head_t wq_stream;
-
-	int cursbuf;		/* Current receiving sbuf */
-	struct cpia_sbuf sbuf[CPIA_NUMSBUF];		/* Double buffering */
-
-	int streaming;
-	int open;
-	int present;
-	struct framebuf *buffers[3];
-	struct framebuf *curbuff, *workbuff;
-};
-
-static int cpia_usb_open(void *privdata);
-static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
-				     void *cbdata);
-static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data);
-static int cpia_usb_streamStart(void *privdata);
-static int cpia_usb_streamStop(void *privdata);
-static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock);
-static int cpia_usb_close(void *privdata);
-
-#define ABOUT "USB driver for Vision CPiA based cameras"
-
-static struct cpia_camera_ops cpia_usb_ops = {
-	cpia_usb_open,
-	cpia_usb_registerCallback,
-	cpia_usb_transferCmd,
-	cpia_usb_streamStart,
-	cpia_usb_streamStop,
-	cpia_usb_streamRead,
-	cpia_usb_close,
-	0,
-	THIS_MODULE
-};
-
-static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_usb;
-
-static void cpia_usb_complete(struct urb *urb)
-{
-	int i;
-	char *cdata;
-	struct usb_cpia *ucpia;
-
-	if (!urb || !urb->context)
-		return;
-
-	ucpia = (struct usb_cpia *) urb->context;
-
-	if (!ucpia->dev || !ucpia->streaming || !ucpia->present || !ucpia->open)
-		return;
-
-	if (ucpia->workbuff->status == FRAME_EMPTY) {
-		ucpia->workbuff->status = FRAME_READING;
-		ucpia->workbuff->length = 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;
-
-		if (st)
-			printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", i, n, st);
-
-		if (FRAMEBUF_LEN < ucpia->workbuff->length + n) {
-			printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n);
-			return;
-		}
-
-		if (n) {
-			if ((ucpia->workbuff->length > 0) ||
-			    (0x19 == cdata[0] && 0x68 == cdata[1])) {
-				memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n);
-				ucpia->workbuff->length += n;
-			} else
-				DBG("Ignoring packet!\n");
-		} else {
-			if (ucpia->workbuff->length > 4 &&
-			    0xff == ucpia->workbuff->data[ucpia->workbuff->length-1] &&
-			    0xff == ucpia->workbuff->data[ucpia->workbuff->length-2] &&
-			    0xff == ucpia->workbuff->data[ucpia->workbuff->length-3] &&
-			    0xff == ucpia->workbuff->data[ucpia->workbuff->length-4]) {
-				ucpia->workbuff->status = FRAME_READY;
-				ucpia->curbuff = ucpia->workbuff;
-				ucpia->workbuff = ucpia->workbuff->next;
-				ucpia->workbuff->status = FRAME_EMPTY;
-				ucpia->workbuff->length = 0;
-
-				if (waitqueue_active(&ucpia->wq_stream))
-					wake_up_interruptible(&ucpia->wq_stream);
-			}
-		}
-	}
-
-	/* resubmit */
-	urb->dev = ucpia->dev;
-	if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
-		printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__,  i);
-}
-
-static int cpia_usb_open(void *privdata)
-{
-	struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
-	struct urb *urb;
-	int ret, retval = 0, fx, err;
-
-	if (!ucpia)
-		return -EINVAL;
-
-	ucpia->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
-	if (!ucpia->sbuf[0].data)
-		return -EINVAL;
-
-	ucpia->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
-	if (!ucpia->sbuf[1].data) {
-		retval = -EINVAL;
-		goto error_0;
-	}
-
-	ret = usb_set_interface(ucpia->dev, ucpia->iface, 3);
-	if (ret < 0) {
-		printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret);
-		retval = -EBUSY;
-		goto error_1;
-	}
-
-	ucpia->buffers[0]->status = FRAME_EMPTY;
-	ucpia->buffers[0]->length = 0;
-	ucpia->buffers[1]->status = FRAME_EMPTY;
-	ucpia->buffers[1]->length = 0;
-	ucpia->buffers[2]->status = FRAME_EMPTY;
-	ucpia->buffers[2]->length = 0;
-	ucpia->curbuff = ucpia->buffers[0];
-	ucpia->workbuff = ucpia->buffers[1];
-
-	/* We double buffer the Iso lists, and also know the polling
-	 * interval is every frame (1 == (1 << (bInterval -1))).
-	 */
-	urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-	if (!urb) {
-		printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n");
-		retval = -ENOMEM;
-		goto error_1;
-	}
-
-	ucpia->sbuf[0].urb = urb;
-	urb->dev = ucpia->dev;
-	urb->context = ucpia;
-	urb->pipe = usb_rcvisocpipe(ucpia->dev, 1);
-	urb->transfer_flags = URB_ISO_ASAP;
-	urb->transfer_buffer = ucpia->sbuf[0].data;
-	urb->complete = cpia_usb_complete;
-	urb->number_of_packets = FRAMES_PER_DESC;
-	urb->interval = 1;
-	urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
-	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
-		urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx;
-		urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
-	}
-
-	urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-	if (!urb) {
-		printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 1\n");
-		retval = -ENOMEM;
-		goto error_urb0;
-	}
-
-	ucpia->sbuf[1].urb = urb;
-	urb->dev = ucpia->dev;
-	urb->context = ucpia;
-	urb->pipe = usb_rcvisocpipe(ucpia->dev, 1);
-	urb->transfer_flags = URB_ISO_ASAP;
-	urb->transfer_buffer = ucpia->sbuf[1].data;
-	urb->complete = cpia_usb_complete;
-	urb->number_of_packets = FRAMES_PER_DESC;
-	urb->interval = 1;
-	urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
-	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
-		urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx;
-		urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
-	}
-
-	/* queue the ISO urbs, and resubmit in the completion handler */
-	err = usb_submit_urb(ucpia->sbuf[0].urb, GFP_KERNEL);
-	if (err) {
-		printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n",
-			err);
-		goto error_urb1;
-	}
-	err = usb_submit_urb(ucpia->sbuf[1].urb, GFP_KERNEL);
-	if (err) {
-		printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n",
-			err);
-		goto error_urb1;
-	}
-
-	ucpia->streaming = 1;
-	ucpia->open = 1;
-
-	return 0;
-
-error_urb1:		/* free urb 1 */
-	usb_free_urb(ucpia->sbuf[1].urb);
-	ucpia->sbuf[1].urb = NULL;
-error_urb0:		/* free urb 0 */
-	usb_free_urb(ucpia->sbuf[0].urb);
-	ucpia->sbuf[0].urb = NULL;
-error_1:
-	kfree (ucpia->sbuf[1].data);
-	ucpia->sbuf[1].data = NULL;
-error_0:
-	kfree (ucpia->sbuf[0].data);
-	ucpia->sbuf[0].data = NULL;
-
-	return retval;
-}
-
-//
-// convenience functions
-//
-
-/****************************************************************************
- *
- *  WritePacket
- *
- ***************************************************************************/
-static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_t size)
-{
-	if (!packet)
-		return -EINVAL;
-
-	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-			 packet[1] + (packet[0] << 8),
-			 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			 packet[2] + (packet[3] << 8),
-			 packet[4] + (packet[5] << 8), buf, size, 1000);
-}
-
-/****************************************************************************
- *
- *  ReadPacket
- *
- ***************************************************************************/
-static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size)
-{
-	if (!packet || size <= 0)
-		return -EINVAL;
-
-	return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-			 packet[1] + (packet[0] << 8),
-			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			 packet[2] + (packet[3] << 8),
-			 packet[4] + (packet[5] << 8), buf, size, 1000);
-}
-
-static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data)
-{
-	int err = 0;
-	int databytes;
-	struct usb_cpia *ucpia = (struct usb_cpia *)privdata;
-	struct usb_device *udev = ucpia->dev;
-
-	if (!udev) {
-		DBG("Internal driver error: udev is NULL\n");
-		return -EINVAL;
-	}
-
-	if (!command) {
-		DBG("Internal driver error: command is NULL\n");
-		return -EINVAL;
-	}
-
-	databytes = (((int)command[7])<<8) | command[6];
-
-	if (command[0] == DATA_IN) {
-		u8 buffer[8];
-
-		if (!data) {
-			DBG("Internal driver error: data is NULL\n");
-			return -EINVAL;
-		}
-
-		err = ReadPacket(udev, command, buffer, 8);
-		if (err < 0)
-			return err;
-
-		memcpy(data, buffer, databytes);
-	} else if(command[0] == DATA_OUT)
-		WritePacket(udev, command, data, databytes);
-	else {
-		DBG("Unexpected first byte of command: %x\n", command[0]);
-		err = -EINVAL;
-	}
-
-	return 0;
-}
-
-static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
-	void *cbdata)
-{
-	return -ENODEV;
-}
-
-static int cpia_usb_streamStart(void *privdata)
-{
-	return -ENODEV;
-}
-
-static int cpia_usb_streamStop(void *privdata)
-{
-	return -ENODEV;
-}
-
-static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
-{
-	struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
-	struct framebuf *mybuff;
-
-	if (!ucpia || !ucpia->present)
-		return -1;
-
-	if (ucpia->curbuff->status != FRAME_READY)
-		interruptible_sleep_on(&ucpia->wq_stream);
-	else
-		DBG("Frame already waiting!\n");
-
-	mybuff = ucpia->curbuff;
-
-	if (!mybuff)
-		return -1;
-
-	if (mybuff->status != FRAME_READY || mybuff->length < 4) {
-		DBG("Something went wrong!\n");
-		return -1;
-	}
-
-	memcpy(frame, mybuff->data, mybuff->length);
-	mybuff->status = FRAME_EMPTY;
-
-/*   DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n",  */
-/*       mybuff->length, frame[0], frame[1], */
-/*       frame[mybuff->length-4], frame[mybuff->length-3],  */
-/*       frame[mybuff->length-2], frame[mybuff->length-1]); */
-
-	return mybuff->length;
-}
-
-static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
-{
-	if (!ucpia->streaming)
-		return;
-
-	ucpia->streaming = 0;
-
-	/* Set packet size to 0 */
-	if (try) {
-		int ret;
-
-		ret = usb_set_interface(ucpia->dev, ucpia->iface, 0);
-		if (ret < 0) {
-			printk(KERN_ERR "usb_set_interface error (ret = %d)\n", ret);
-			return;
-		}
-	}
-
-	/* Unschedule all of the iso td's */
-	if (ucpia->sbuf[1].urb) {
-		usb_kill_urb(ucpia->sbuf[1].urb);
-		usb_free_urb(ucpia->sbuf[1].urb);
-		ucpia->sbuf[1].urb = NULL;
-	}
-
-	kfree(ucpia->sbuf[1].data);
-	ucpia->sbuf[1].data = NULL;
-
-	if (ucpia->sbuf[0].urb) {
-		usb_kill_urb(ucpia->sbuf[0].urb);
-		usb_free_urb(ucpia->sbuf[0].urb);
-		ucpia->sbuf[0].urb = NULL;
-	}
-
-	kfree(ucpia->sbuf[0].data);
-	ucpia->sbuf[0].data = NULL;
-}
-
-static int cpia_usb_close(void *privdata)
-{
-	struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
-
-	if(!ucpia)
-		return -ENODEV;
-
-	ucpia->open = 0;
-
-	/* ucpia->present = 0 protects against trying to reset the
-	 * alt setting if camera is physically disconnected while open */
-	cpia_usb_free_resources(ucpia, ucpia->present);
-
-	return 0;
-}
-
-/* Probing and initializing */
-
-static int cpia_probe(struct usb_interface *intf,
-		      const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_host_interface *interface;
-	struct usb_cpia *ucpia;
-	struct cam_data *cam;
-	int ret;
-
-	/* A multi-config CPiA camera? */
-	if (udev->descriptor.bNumConfigurations != 1)
-		return -ENODEV;
-
-	interface = intf->cur_altsetting;
-
-	printk(KERN_INFO "USB CPiA camera found\n");
-
-	ucpia = kzalloc(sizeof(*ucpia), GFP_KERNEL);
-	if (!ucpia) {
-		printk(KERN_ERR "couldn't kmalloc cpia struct\n");
-		return -ENOMEM;
-	}
-
-	ucpia->dev = udev;
-	ucpia->iface = interface->desc.bInterfaceNumber;
-	init_waitqueue_head(&ucpia->wq_stream);
-
-	ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0]));
-	if (!ucpia->buffers[0]) {
-		printk(KERN_ERR "couldn't vmalloc frame buffer 0\n");
-		goto fail_alloc_0;
-	}
-
-	ucpia->buffers[1] = vmalloc(sizeof(*ucpia->buffers[1]));
-	if (!ucpia->buffers[1]) {
-		printk(KERN_ERR "couldn't vmalloc frame buffer 1\n");
-		goto fail_alloc_1;
-	}
-
-	ucpia->buffers[2] = vmalloc(sizeof(*ucpia->buffers[2]));
-	if (!ucpia->buffers[2]) {
-		printk(KERN_ERR "couldn't vmalloc frame buffer 2\n");
-		goto fail_alloc_2;
-	}
-
-	ucpia->buffers[0]->next = ucpia->buffers[1];
-	ucpia->buffers[1]->next = ucpia->buffers[2];
-	ucpia->buffers[2]->next = ucpia->buffers[0];
-
-	ret = usb_set_interface(udev, ucpia->iface, 0);
-	if (ret < 0) {
-		printk(KERN_ERR "cpia_probe: usb_set_interface error (ret = %d)\n", ret);
-		/* goto fail_all; */
-	}
-
-	/* Before register_camera, important */
-	ucpia->present = 1;
-
-	cam = cpia_register_camera(&cpia_usb_ops, ucpia);
-	if (!cam) {
-		LOG("failed to cpia_register_camera\n");
-		goto fail_all;
-	}
-
-	spin_lock( &cam_list_lock_usb );
-	list_add( &cam->cam_data_list, &cam_list );
-	spin_unlock( &cam_list_lock_usb );
-
-	usb_set_intfdata(intf, cam);
-	return 0;
-
-fail_all:
-	vfree(ucpia->buffers[2]);
-	ucpia->buffers[2] = NULL;
-fail_alloc_2:
-	vfree(ucpia->buffers[1]);
-	ucpia->buffers[1] = NULL;
-fail_alloc_1:
-	vfree(ucpia->buffers[0]);
-	ucpia->buffers[0] = NULL;
-fail_alloc_0:
-	kfree(ucpia);
-	return -EIO;
-}
-
-static void cpia_disconnect(struct usb_interface *intf);
-
-static struct usb_device_id cpia_id_table [] = {
-	{ USB_DEVICE(0x0553, 0x0002) },
-	{ USB_DEVICE(0x0813, 0x0001) },
-	{ }					/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, cpia_id_table);
-MODULE_LICENSE("GPL");
-
-
-static struct usb_driver cpia_driver = {
-	.name		= "cpia",
-	.probe		= cpia_probe,
-	.disconnect	= cpia_disconnect,
-	.id_table	= cpia_id_table,
-};
-
-static void cpia_disconnect(struct usb_interface *intf)
-{
-	struct cam_data *cam = usb_get_intfdata(intf);
-	struct usb_cpia *ucpia;
-
-	usb_set_intfdata(intf, NULL);
-	if (!cam)
-		return;
-
-	ucpia = (struct usb_cpia *) cam->lowlevel_data;
-	spin_lock( &cam_list_lock_usb );
-	list_del(&cam->cam_data_list);
-	spin_unlock( &cam_list_lock_usb );
-
-	ucpia->present = 0;
-
-	cpia_unregister_camera(cam);
-	if(ucpia->open)
-		cpia_usb_close(cam->lowlevel_data);
-
-	ucpia->curbuff->status = FRAME_ERROR;
-
-	if (waitqueue_active(&ucpia->wq_stream))
-		wake_up_interruptible(&ucpia->wq_stream);
-
-	ucpia->curbuff = ucpia->workbuff = NULL;
-
-	vfree(ucpia->buffers[2]);
-	ucpia->buffers[2] = NULL;
-
-	vfree(ucpia->buffers[1]);
-	ucpia->buffers[1] = NULL;
-
-	vfree(ucpia->buffers[0]);
-	ucpia->buffers[0] = NULL;
-
-	cam->lowlevel_data = NULL;
-	kfree(ucpia);
-}
-
-static int __init usb_cpia_init(void)
-{
-	printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
-	       CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER);
-
-	spin_lock_init(&cam_list_lock_usb);
-	return usb_register(&cpia_driver);
-}
-
-static void __exit usb_cpia_cleanup(void)
-{
-	usb_deregister(&cpia_driver);
-}
-
-
-module_init (usb_cpia_init);
-module_exit (usb_cpia_cleanup);
-
diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig
index 1d73334..b265695 100644
--- a/drivers/staging/cx25821/Kconfig
+++ b/drivers/staging/cx25821/Kconfig
@@ -1,11 +1,11 @@
 config VIDEO_CX25821
 	tristate "Conexant cx25821 support"
-	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+	depends on DVB_CORE && VIDEO_DEV && PCI && I2C
 	depends on BKL # please fix
 	select I2C_ALGOBIT
 	select VIDEO_BTCX
 	select VIDEO_TVEEPROM
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEOBUF_DVB
 	select VIDEOBUF_DMA_SG
 	select VIDEO_CX25840
diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c
index 2a01dc0..9a205a3 100644
--- a/drivers/staging/cx25821/cx25821-alsa.c
+++ b/drivers/staging/cx25821/cx25821-alsa.c
@@ -20,6 +20,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -42,11 +44,16 @@
 
 #define AUDIO_SRAM_CHANNEL	SRAM_CH08
 
-#define dprintk(level, fmt, arg...)	if (debug >= level) \
-	printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg)
-
-#define dprintk_core(level, fmt, arg...)	if (debug >= level) \
-	printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg)
+#define dprintk(level, fmt, arg...)				\
+do {								\
+	if (debug >= level)					\
+		pr_info("%s/1: " fmt, chip->dev->name, ##arg);	\
+} while (0)
+#define dprintk_core(level, fmt, arg...)				\
+do {									\
+	if (debug >= level)						\
+		printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \
+} while (0)
 
 /****************************************************************************
 	Data type declarations - Can be moded to a header file later
@@ -173,12 +180,11 @@
 		 tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
 		 FLD_AUD_CLK_ENABLE);
 
-	/* printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line,"
-				"cmds_start(0x%x)= %d lines/FIFO, %d periods, "
-				"%d byte buffer\n", buf->bpl,
-				audio_ch->cmds_start,
-				cx_read(audio_ch->cmds_start + 12)>>1,
-				chip->num_periods, buf->bpl *chip->num_periods);
+	/*
+	pr_info("DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d byte buffer\n",
+		buf->bpl, audio_ch->cmds_start,
+		cx_read(audio_ch->cmds_start + 12)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
 	*/
 
 	/* Enables corresponding bits at AUD_INT_STAT */
@@ -259,8 +265,7 @@
 
 	/* risc op code error */
 	if (status & AUD_INT_OPC_ERR) {
-		printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n",
-		       dev->name);
+		pr_warn("WARNING %s/1: Audio risc op code error\n", dev->name);
 
 		cx_clear(AUD_INT_DMA_CTL,
 			 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
@@ -269,8 +274,7 @@
 						[AUDIO_SRAM_CHANNEL]);
 	}
 	if (status & AUD_INT_DN_SYNC) {
-		printk(KERN_WARNING "WARNING %s: Downstream sync error!\n",
-		       dev->name);
+		pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
 		cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
 		return;
 	}
@@ -388,8 +392,7 @@
 	unsigned int bpl = 0;
 
 	if (!chip) {
-		printk(KERN_ERR "DEBUG: cx25821 can't find device struct."
-		       " Can't proceed with open\n");
+		pr_err("DEBUG: cx25821 can't find device struct. Can't proceed with open\n");
 		return -ENODEV;
 	}
 
@@ -479,8 +482,7 @@
 					  chip->period_size, chip->num_periods,
 					  1);
 	if (ret < 0) {
-		printk(KERN_INFO
-			"DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
+		pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
 		goto error;
 	}
 
@@ -608,8 +610,7 @@
 
 	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
 	if (err < 0) {
-		printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n",
-		       __func__);
+		pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__);
 		return err;
 	}
 	pcm->private_data = chip;
@@ -674,23 +675,21 @@
 	int err;
 
 	if (devno >= SNDRV_CARDS) {
-		printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n",
-		       __func__);
+		pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
 		return -ENODEV;
 	}
 
 	if (!enable[devno]) {
 		++devno;
-		printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__);
+		pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__);
 		return -ENOENT;
 	}
 
 	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
 			 sizeof(struct cx25821_audio_dev), &card);
 	if (err < 0) {
-		printk(KERN_INFO
-		       "DEBUG ERROR: cannot create snd_card_new in %s\n",
-		       __func__);
+		pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
+			__func__);
 		return err;
 	}
 
@@ -712,16 +711,15 @@
 			  IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip);
 
 	if (err < 0) {
-		printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n",
+		pr_err("ERROR %s: can't get IRQ %d for ALSA\n",
 		       chip->dev->name, dev->pci->irq);
 		goto error;
 	}
 
 	err = snd_cx25821_pcm(chip, 0, "cx25821 Digital");
 	if (err < 0) {
-		printk(KERN_INFO
-		       "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
-		       __func__);
+		pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
+			__func__);
 		goto error;
 	}
 
@@ -732,13 +730,13 @@
 		chip->iobase, chip->irq);
 	strcpy(card->mixername, "CX25821");
 
-	printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n",
-	       card->driver, devno);
+	pr_info("%s/%i: ALSA support for cx25821 boards\n",
+		card->driver, devno);
 
 	err = snd_card_register(card);
 	if (err < 0) {
-		printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n",
-		       __func__);
+		pr_info("DEBUG ERROR: cannot register sound card %s\n",
+			__func__);
 		goto error;
 	}
 
@@ -778,8 +776,7 @@
 	}
 
 	if (dev == NULL)
-		printk(KERN_INFO
-		       "cx25821 ERROR ALSA: no cx25821 cards found\n");
+		pr_info("ERROR ALSA: no cx25821 cards found\n");
 
 	return 0;
 
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c
index 1607b0d..7992a3b 100644
--- a/drivers/staging/cx25821/cx25821-audio-upstream.c
+++ b/drivers/staging/cx25821/cx25821-audio-upstream.c
@@ -20,6 +20,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "cx25821-video.h"
 #include "cx25821-audio-upstream.h"
 
@@ -221,7 +223,7 @@
 
 	if (!dev->_audio_is_running) {
 		printk(KERN_DEBUG
-		    "cx25821: No audio file is currently running so return!\n");
+		       pr_fmt("No audio file is currently running so return!\n"));
 		return;
 	}
 	/* Disable RISC interrupts */
@@ -281,19 +283,19 @@
 
 	if (IS_ERR(myfile)) {
 		const int open_errno = -PTR_ERR(myfile);
-		printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n",
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
 		       __func__, dev->_audiofilename, open_errno);
 		return PTR_ERR(myfile);
 	} else {
 		if (!(myfile->f_op)) {
-			printk(KERN_ERR "%s: File has no file operations registered!\n",
+			pr_err("%s(): File has no file operations registered!\n",
 			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
 
 		if (!myfile->f_op->read) {
-			printk(KERN_ERR "%s: File has no READ operations registered!\n",
+			pr_err("%s(): File has no READ operations registered!\n",
 			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
@@ -320,9 +322,8 @@
 			frame_offset += vfs_read_retval;
 
 			if (vfs_read_retval < line_size) {
-				printk(KERN_INFO
-				       "Done: exit %s() since no more bytes to read from Audio file.\n",
-				       __func__);
+				pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+					__func__);
 				break;
 			}
 		}
@@ -346,7 +347,7 @@
 	    container_of(work, struct cx25821_dev, _audio_work_entry);
 
 	if (!dev) {
-		printk(KERN_ERR "ERROR %s(): since container_of(work_struct) FAILED!\n",
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
 		       __func__);
 		return;
 	}
@@ -373,19 +374,19 @@
 
 	if (IS_ERR(myfile)) {
 		const int open_errno = -PTR_ERR(myfile);
-		printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n",
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
 		       __func__, dev->_audiofilename, open_errno);
 		return PTR_ERR(myfile);
 	} else {
 		if (!(myfile->f_op)) {
-			printk(KERN_ERR "%s: File has no file operations registered!\n",
+			pr_err("%s(): File has no file operations registered!\n",
 			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
 
 		if (!myfile->f_op->read) {
-			printk(KERN_ERR "%s: File has no READ operations registered!\n",
+			pr_err("%s(): File has no READ operations registered!\n",
 			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
@@ -414,9 +415,8 @@
 				offset += vfs_read_retval;
 
 				if (vfs_read_retval < line_size) {
-					printk(KERN_INFO
-					       "Done: exit %s() since no more bytes to read from Audio file.\n",
-					       __func__);
+					pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+						__func__);
 					break;
 				}
 			}
@@ -459,7 +459,7 @@
 
 	if (!dev->_risc_virt_addr) {
 		printk(KERN_DEBUG
-			"cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n");
+		       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
 		return -ENOMEM;
 	}
 	/* Clear out memory at address */
@@ -474,7 +474,7 @@
 
 	if (!dev->_audiodata_buf_virt_addr) {
 		printk(KERN_DEBUG
-			"cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning.\n");
+		       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
 		return -ENOMEM;
 	}
 	/* Clear out memory at address */
@@ -490,7 +490,7 @@
 					       dev->_audio_lines_count);
 	if (ret < 0) {
 		printk(KERN_DEBUG
-		      "cx25821 ERROR creating audio upstream RISC programs!\n");
+		       pr_fmt("ERROR creating audio upstream RISC programs!\n"));
 		goto error;
 	}
 
@@ -569,16 +569,16 @@
 		spin_unlock(&dev->slock);
 	} else {
 		if (status & FLD_AUD_SRC_OF)
-			printk(KERN_WARNING "%s: Audio Received Overflow Error Interrupt!\n",
-			       __func__);
+			pr_warn("%s(): Audio Received Overflow Error Interrupt!\n",
+				__func__);
 
 		if (status & FLD_AUD_SRC_SYNC)
-			printk(KERN_WARNING "%s: Audio Received Sync Error Interrupt!\n",
-			       __func__);
+			pr_warn("%s(): Audio Received Sync Error Interrupt!\n",
+				__func__);
 
 		if (status & FLD_AUD_SRC_OPC_ERR)
-			printk(KERN_WARNING "%s: Audio Received OpCode Error Interrupt!\n",
-			       __func__);
+			pr_warn("%s(): Audio Received OpCode Error Interrupt!\n",
+				__func__);
 
 		/* Read and write back the interrupt status register to clear
 		 * our bits */
@@ -586,8 +586,8 @@
 	}
 
 	if (dev->_audiofile_status == END_OF_FILE) {
-		printk(KERN_WARNING "cx25821: EOF Channel Audio Framecount = %d\n",
-		       dev->_audioframe_count);
+		pr_warn("EOF Channel Audio Framecount = %d\n",
+			dev->_audioframe_count);
 		return -1;
 	}
 	/* ElSE, set the interrupt mask register, re-enable irq. */
@@ -644,9 +644,8 @@
 
 		/* 10 millisecond timeout */
 		if (count++ > 1000) {
-			printk(KERN_ERR
-			       "cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n",
-			     __func__);
+			pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
+			       __func__);
 			return;
 		}
 
@@ -696,8 +695,8 @@
 	    request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
 			IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
 	if (err < 0) {
-		printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name,
-		       dev->pci->irq);
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
 		goto fail_irq;
 	}
 
@@ -726,7 +725,7 @@
 	int str_length = 0;
 
 	if (dev->_audio_is_running) {
-		printk(KERN_WARNING "Audio Channel is still running so return!\n");
+		pr_warn("Audio Channel is still running so return!\n");
 		return 0;
 	}
 
@@ -740,7 +739,7 @@
 
 	if (!dev->_irq_audio_queues) {
 		printk(KERN_DEBUG
-			"cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n");
+		       pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
 		return -ENOMEM;
 	}
 
@@ -787,8 +786,7 @@
 	retval =
 	    cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size);
 	if (retval < 0) {
-		printk(KERN_ERR
-		       "%s: Failed to set up Audio upstream buffers!\n",
+		pr_err("%s: Failed to set up Audio upstream buffers!\n",
 		       dev->name);
 		goto error;
 	}
diff --git a/drivers/staging/cx25821/cx25821-cards.c b/drivers/staging/cx25821/cx25821-cards.c
index da0f56d..94e8d68 100644
--- a/drivers/staging/cx25821/cx25821-cards.c
+++ b/drivers/staging/cx25821/cx25821-cards.c
@@ -21,6 +21,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/pci.h>
diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c
index 300da31..a216b62 100644
--- a/drivers/staging/cx25821/cx25821-core.c
+++ b/drivers/staging/cx25821/cx25821-core.c
@@ -21,6 +21,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include "cx25821.h"
@@ -332,7 +334,7 @@
 
 static int cx25821_risc_decode(u32 risc)
 {
-	static char *instr[16] = {
+	static const char * const instr[16] = {
 		[RISC_SYNC >> 28] = "sync",
 		[RISC_WRITE >> 28] = "write",
 		[RISC_WRITEC >> 28] = "writec",
@@ -344,7 +346,7 @@
 		[RISC_WRITECM >> 28] = "writecm",
 		[RISC_WRITECR >> 28] = "writecr",
 	};
-	static int incr[16] = {
+	static const int incr[16] = {
 		[RISC_WRITE >> 28] = 3,
 		[RISC_JUMP >> 28] = 3,
 		[RISC_SKIP >> 28] = 1,
@@ -353,7 +355,7 @@
 		[RISC_WRITECM >> 28] = 3,
 		[RISC_WRITECR >> 28] = 4,
 	};
-	static char *bits[] = {
+	static const char * const bits[] = {
 		"12", "13", "14", "resync",
 		"cnt0", "cnt1", "18", "19",
 		"20", "21", "22", "23",
@@ -361,13 +363,13 @@
 	};
 	int i;
 
-	printk("0x%08x [ %s", risc,
-	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+	pr_cont("0x%08x [ %s",
+		risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
 	for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
 		if (risc & (1 << (i + 12)))
-			printk(" %s", bits[i]);
+			pr_cont(" %s", bits[i]);
 	}
-	printk(" count=%d ]\n", risc & 0xfff);
+	pr_cont(" count=%d ]\n", risc & 0xfff);
 	return incr[risc >> 28] ? incr[risc >> 28] : 1;
 }
 
@@ -620,16 +622,15 @@
 	u32 risc;
 	unsigned int i, j, n;
 
-	printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name,
-	       ch->name);
+	pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name);
 	for (i = 0; i < ARRAY_SIZE(name); i++)
-		printk(KERN_WARNING "cmds + 0x%2x:   %-15s: 0x%08x\n", i * 4,
-		       name[i], cx_read(ch->cmds_start + 4 * i));
+		pr_warn("cmds + 0x%2x:   %-15s: 0x%08x\n",
+			i * 4, name[i], cx_read(ch->cmds_start + 4 * i));
 
 	j = i * 4;
 	for (i = 0; i < 4;) {
 		risc = cx_read(ch->cmds_start + 4 * (i + 14));
-		printk(KERN_WARNING "cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
 		i += cx25821_risc_decode(risc);
 	}
 
@@ -637,36 +638,35 @@
 		risc = cx_read(ch->ctrl_start + 4 * i);
 		/* No consideration for bits 63-32 */
 
-		printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4,
-		       ch->ctrl_start + 4 * i, i);
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
 		n = cx25821_risc_decode(risc);
 		for (j = 1; j < n; j++) {
 			risc = cx_read(ch->ctrl_start + 4 * (i + j));
-			printk(KERN_WARNING
-			       "ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
-			       4 * (i + j), i + j, risc, j);
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
 		}
 	}
 
-	printk(KERN_WARNING "        :   fifo: 0x%08x -> 0x%x\n",
-	       ch->fifo_start, ch->fifo_start + ch->fifo_size);
-	printk(KERN_WARNING "        :   ctrl: 0x%08x -> 0x%x\n",
-	       ch->ctrl_start, ch->ctrl_start + 6 * 16);
-	printk(KERN_WARNING "        :   ptr1_reg: 0x%08x\n",
-	       cx_read(ch->ptr1_reg));
-	printk(KERN_WARNING "        :   ptr2_reg: 0x%08x\n",
-	       cx_read(ch->ptr2_reg));
-	printk(KERN_WARNING "        :   cnt1_reg: 0x%08x\n",
-	       cx_read(ch->cnt1_reg));
-	printk(KERN_WARNING "        :   cnt2_reg: 0x%08x\n",
-	       cx_read(ch->cnt2_reg));
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
 }
 EXPORT_SYMBOL(cx25821_sram_channel_dump);
 
 void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
 				     struct sram_channel *ch)
 {
-	static char *name[] = {
+	static const char * const name[] = {
 		"init risc lo",
 		"init risc hi",
 		"cdt base",
@@ -686,18 +686,18 @@
 	u32 risc, value, tmp;
 	unsigned int i, j, n;
 
-	printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n",
-	       dev->name, ch->name);
+	pr_info("\n%s: %s - dma Audio channel status dump\n",
+		dev->name, ch->name);
 
 	for (i = 0; i < ARRAY_SIZE(name); i++)
-		printk(KERN_INFO "%s: cmds + 0x%2x:   %-15s: 0x%08x\n",
-		       dev->name, i * 4, name[i],
-		       cx_read(ch->cmds_start + 4 * i));
+		pr_info("%s: cmds + 0x%2x:   %-15s: 0x%08x\n",
+			dev->name, i * 4, name[i],
+			cx_read(ch->cmds_start + 4 * i));
 
 	j = i * 4;
 	for (i = 0; i < 4;) {
 		risc = cx_read(ch->cmds_start + 4 * (i + 14));
-		printk(KERN_WARNING "cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
 		i += cx25821_risc_decode(risc);
 	}
 
@@ -705,44 +705,43 @@
 		risc = cx_read(ch->ctrl_start + 4 * i);
 		/* No consideration for bits 63-32 */
 
-		printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4,
-		       ch->ctrl_start + 4 * i, i);
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
 		n = cx25821_risc_decode(risc);
 
 		for (j = 1; j < n; j++) {
 			risc = cx_read(ch->ctrl_start + 4 * (i + j));
-			printk(KERN_WARNING
-			       "ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
-			       4 * (i + j), i + j, risc, j);
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
 		}
 	}
 
-	printk(KERN_WARNING "        :   fifo: 0x%08x -> 0x%x\n",
-	       ch->fifo_start, ch->fifo_start + ch->fifo_size);
-	printk(KERN_WARNING "        :   ctrl: 0x%08x -> 0x%x\n",
-	       ch->ctrl_start, ch->ctrl_start + 6 * 16);
-	printk(KERN_WARNING "        :   ptr1_reg: 0x%08x\n",
-	       cx_read(ch->ptr1_reg));
-	printk(KERN_WARNING "        :   ptr2_reg: 0x%08x\n",
-	       cx_read(ch->ptr2_reg));
-	printk(KERN_WARNING "        :   cnt1_reg: 0x%08x\n",
-	       cx_read(ch->cnt1_reg));
-	printk(KERN_WARNING "        :   cnt2_reg: 0x%08x\n",
-	       cx_read(ch->cnt2_reg));
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
 
 	for (i = 0; i < 4; i++) {
 		risc = cx_read(ch->cmds_start + 56 + (i * 4));
-		printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc);
+		pr_warn("instruction %d = 0x%x\n", i, risc);
 	}
 
 	/* read data from the first cdt buffer */
 	risc = cx_read(AUD_A_CDT);
-	printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc);
+	pr_warn("\nread cdt loc=0x%x\n", risc);
 	for (i = 0; i < 8; i++) {
 		n = cx_read(risc + i * 4);
-		printk(KERN_WARNING "0x%x ", n);
+		pr_cont("0x%x ", n);
 	}
-	printk(KERN_WARNING "\n\n");
+	pr_cont("\n\n");
 
 	value = cx_read(CLK_RST);
 	CX25821_INFO(" CLK_RST = 0x%x\n\n", value);
@@ -870,7 +869,7 @@
 	     dev->name))
 		return 0;
 
-	printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+	pr_err("%s: can't get MMIO memory @ 0x%llx\n",
 	       dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
 
 	return -EBUSY;
@@ -880,8 +879,8 @@
 {
 	dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
 
-	printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__,
-	       dev->hwrevision);
+	pr_info("%s(): Hardware revision = 0x%02x\n",
+		__func__, dev->hwrevision);
 }
 
 static void cx25821_iounmap(struct cx25821_dev *dev)
@@ -901,9 +900,9 @@
 {
 	int io_size = 0, i;
 
-	printk(KERN_INFO "\n***********************************\n");
-	printk(KERN_INFO "cx25821 set up\n");
-	printk(KERN_INFO "***********************************\n\n");
+	pr_info("\n***********************************\n");
+	pr_info("cx25821 set up\n");
+	pr_info("***********************************\n\n");
 
 	mutex_init(&dev->lock);
 
@@ -920,13 +919,11 @@
 	strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821");
 
 	if (dev->pci->device != 0x8210) {
-		printk(KERN_INFO
-		       "%s() Exiting. Incorrect Hardware device = 0x%02x\n",
-		       __func__, dev->pci->device);
+		pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
+			__func__, dev->pci->device);
 		return -1;
 	} else {
-		printk(KERN_INFO "Athena Hardware device = 0x%02x\n",
-		       dev->pci->device);
+		pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
 	}
 
 	/* Apply a sensible clock frequency for the PCIe bridge */
@@ -956,8 +953,7 @@
 	dev->i2c_bus[0].i2c_period = (0x07 << 24);	/* 1.95MHz */
 
 	if (cx25821_get_resources(dev) < 0) {
-		printk(KERN_ERR "%s No more PCIe resources for "
-		       "subsystem: %04x:%04x\n",
+		pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n",
 		       dev->name, dev->pci->subsystem_vendor,
 		       dev->pci->subsystem_device);
 
@@ -985,11 +981,11 @@
 
 	dev->bmmio = (u8 __iomem *) dev->lmmio;
 
-	printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-	       dev->name, dev->pci->subsystem_vendor,
-	       dev->pci->subsystem_device, cx25821_boards[dev->board].name,
-	       dev->board, card[dev->nr] == dev->board ?
-	       "insmod option" : "autodetected");
+	pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+		dev->name, dev->pci->subsystem_vendor,
+		dev->pci->subsystem_device, cx25821_boards[dev->board].name,
+		dev->board, card[dev->nr] == dev->board ?
+		"insmod option" : "autodetected");
 
 	/* init hardware */
 	cx25821_initialize(dev);
@@ -1004,8 +1000,7 @@
 	cx25821_card_setup(dev);
 
 	if (medusa_video_init(dev) < 0)
-		CX25821_ERR("%s() Failed to initialize medusa!\n"
-		, __func__);
+		CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__);
 
 	cx25821_video_register(dev);
 
@@ -1017,13 +1012,12 @@
 	if (video_register_device
 	    (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
 		cx25821_videoioctl_unregister(dev);
-		printk(KERN_ERR
-		   "%s() Failed to register video adapter for IOCTL, so \
-		   unregistering videoioctl device.\n", __func__);
+		pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n",
+		       __func__);
 	}
 
 	cx25821_dev_checkrevision(dev);
-	CX25821_INFO("cx25821 setup done!\n");
+	CX25821_INFO("setup done!\n");
 
 	return 0;
 }
@@ -1362,20 +1356,20 @@
 {
 	unsigned int i;
 
-	printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
+	printk(KERN_DEBUG pr_fmt("%s: %s [0x%x]"), name, tag, bits);
 
 	for (i = 0; i < len; i++) {
 		if (!(bits & (1 << i)))
 			continue;
 		if (strings[i])
-			printk(" %s", strings[i]);
+			pr_cont(" %s", strings[i]);
 		else
-			printk(" %d", i);
+			pr_cont(" %d", i);
 		if (!(mask & (1 << i)))
 			continue;
-		printk("*");
+		pr_cont("*");
 	}
-	printk("\n");
+	pr_cont("\n");
 }
 EXPORT_SYMBOL(cx25821_print_irqbits);
 
@@ -1405,12 +1399,12 @@
 	if (pci_enable_device(pci_dev)) {
 		err = -EIO;
 
-		printk(KERN_INFO "pci enable failed! ");
+		pr_info("pci enable failed!\n");
 
 		goto fail_unregister_device;
 	}
 
-	printk(KERN_INFO "cx25821 Athena pci enable !\n");
+	pr_info("Athena pci enable !\n");
 
 	err = cx25821_dev_setup(dev);
 	if (err) {
@@ -1423,14 +1417,13 @@
 	/* print pci info */
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
 	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
-	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
-	       "latency: %d, mmio: 0x%llx\n", dev->name,
-	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
-	       dev->pci_lat, (unsigned long long)dev->base_io_addr);
+	pr_info("%s/0: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
+		dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+		dev->pci_lat, (unsigned long long)dev->base_io_addr);
 
 	pci_set_master(pci_dev);
 	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
-		printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+		pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
 		err = -EIO;
 		goto fail_irq;
 	}
@@ -1440,15 +1433,14 @@
 			dev->name, dev);
 
 	if (err < 0) {
-		printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
-		       pci_dev->irq);
+		pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
 		goto fail_irq;
 	}
 
 	return 0;
 
 fail_irq:
-	printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ !\n");
+	pr_info("cx25821_initdev() can't get IRQ !\n");
 	cx25821_dev_unregister(dev);
 
 fail_unregister_pci:
@@ -1510,9 +1502,10 @@
 static int __init cx25821_init(void)
 {
 	INIT_LIST_HEAD(&cx25821_devlist);
-	printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n",
-	       (CX25821_VERSION_CODE >> 16) & 0xff,
-	       (CX25821_VERSION_CODE >> 8) & 0xff, CX25821_VERSION_CODE & 0xff);
+	pr_info("driver version %d.%d.%d loaded\n",
+		(CX25821_VERSION_CODE >> 16) & 0xff,
+		(CX25821_VERSION_CODE >> 8) & 0xff,
+		CX25821_VERSION_CODE & 0xff);
 	return pci_register_driver(&cx25821_pci_driver);
 }
 
diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c
index 2b14bcc..130dfeb 100644
--- a/drivers/staging/cx25821/cx25821-i2c.c
+++ b/drivers/staging/cx25821/cx25821-i2c.c
@@ -21,6 +21,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "cx25821.h"
 #include <linux/i2c.h>
 
@@ -32,10 +34,11 @@
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
-#define dprintk(level, fmt, arg...)\
-	do { if (i2c_debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
-	} while (0)
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (i2c_debug >= level)						\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
 
 #define I2C_WAIT_DELAY 32
 #define I2C_WAIT_RETRY 64
@@ -98,7 +101,7 @@
 		if (!i2c_slave_did_ack(i2c_adap))
 			return -EIO;
 
-		dprintk(1, "%s() returns 0\n", __func__);
+		dprintk(1, "%s(): returns 0\n", __func__);
 		return 0;
 	}
 
@@ -163,7 +166,7 @@
 	retval = -EIO;
 err:
 	if (i2c_debug)
-		printk(KERN_ERR " ERR: %d\n", retval);
+		pr_err(" ERR: %d\n", retval);
 	return retval;
 }
 
@@ -187,7 +190,7 @@
 		if (!i2c_slave_did_ack(i2c_adap))
 			return -EIO;
 
-		dprintk(1, "%s() returns 0\n", __func__);
+		dprintk(1, "%s(): returns 0\n", __func__);
 		return 0;
 	}
 
@@ -227,7 +230,7 @@
 	retval = -EIO;
 err:
 	if (i2c_debug)
-		printk(KERN_ERR " ERR: %d\n", retval);
+		pr_err(" ERR: %d\n", retval);
 	return retval;
 }
 
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c
index 1e11e0c..fc780d0 100644
--- a/drivers/staging/cx25821/cx25821-medusa-video.c
+++ b/drivers/staging/cx25821/cx25821-medusa-video.c
@@ -20,6 +20,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "cx25821.h"
 #include "cx25821-medusa-video.h"
 #include "cx25821-biffuncs.h"
@@ -499,9 +501,8 @@
 
 	/* validate the width - cannot be negative */
 	if (width > MAX_WIDTH) {
-		printk
-		    ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
-		     __func__, width, MAX_WIDTH);
+		pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
+			__func__, width, MAX_WIDTH);
 		width = MAX_WIDTH;
 	}
 
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
index 405e2db..e2efacd 100644
--- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
+++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
@@ -20,6 +20,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "cx25821-video.h"
 #include "cx25821-video-upstream-ch2.h"
 
@@ -211,8 +213,7 @@
 	u32 tmp = 0;
 
 	if (!dev->_is_running_ch2) {
-		printk
-		    ("cx25821: No video file is currently running so return!\n");
+		pr_info("No video file is currently running so return!\n");
 		return;
 	}
 	/* Disable RISC interrupts */
@@ -301,19 +302,19 @@
 	myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
 	if (IS_ERR(myfile)) {
 		const int open_errno = -PTR_ERR(myfile);
-		printk("%s(): ERROR opening file(%s) with errno = %d!\n",
-			__func__, dev->_filename_ch2, open_errno);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
 		return PTR_ERR(myfile);
 	} else {
 		if (!(myfile->f_op)) {
-			printk("%s: File has no file operations registered!",
+			pr_err("%s(): File has no file operations registered!\n",
 			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
 
 		if (!myfile->f_op->read) {
-			printk("%s: File has no READ operations registered!",
+			pr_err("%s(): File has no READ operations registered!\n",
 			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
@@ -340,9 +341,8 @@
 			frame_offset += vfs_read_retval;
 
 			if (vfs_read_retval < line_size) {
-				printk(KERN_INFO
-				       "Done: exit %s() since no more bytes to read from Video file.\n",
-				       __func__);
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
 				break;
 			}
 		}
@@ -366,8 +366,8 @@
 	    container_of(work, struct cx25821_dev, _irq_work_entry_ch2);
 
 	if (!dev) {
-		printk("ERROR %s(): since container_of(work_struct) FAILED!\n",
-			__func__);
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
 		return;
 	}
 
@@ -393,21 +393,20 @@
 
 	if (IS_ERR(myfile)) {
 		const int open_errno = -PTR_ERR(myfile);
-		printk("%s(): ERROR opening file(%s) with errno = %d!\n",
-			__func__, dev->_filename_ch2, open_errno);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
 		return PTR_ERR(myfile);
 	} else {
 		if (!(myfile->f_op)) {
-			printk("%s: File has no file operations registered!",
+			pr_err("%s(): File has no file operations registered!\n",
 			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
 
 		if (!myfile->f_op->read) {
-			printk
-			    ("%s: File has no READ operations registered!  Returning.",
-			     __func__);
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
@@ -435,9 +434,8 @@
 				offset += vfs_read_retval;
 
 				if (vfs_read_retval < line_size) {
-					printk(KERN_INFO
-					       "Done: exit %s() since no more bytes to read from Video file.\n",
-					       __func__);
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
 					break;
 				}
 			}
@@ -483,8 +481,7 @@
 	dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2;
 
 	if (!dev->_dma_virt_addr_ch2) {
-		printk
-		    ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n");
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
 		return -ENOMEM;
 	}
 
@@ -504,8 +501,7 @@
 	dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
 
 	if (!dev->_data_buf_virt_addr_ch2) {
-		printk
-		    ("cx25821: FAILED to allocate memory for data buffer! Returning.\n");
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
 		return -ENOMEM;
 	}
 
@@ -521,8 +517,7 @@
 	    cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl,
 					     dev->_lines_count_ch2);
 	if (ret < 0) {
-		printk(KERN_INFO
-			"cx25821: Failed creating Video Upstream Risc programs!\n");
+		pr_info("Failed creating Video Upstream Risc programs!\n");
 		goto error;
 	}
 
@@ -602,8 +597,8 @@
 	}
 
 	if (dev->_file_status_ch2 == END_OF_FILE) {
-		printk("cx25821: EOF Channel 2 Framecount = %d\n",
-		       dev->_frame_count_ch2);
+		pr_info("EOF Channel 2 Framecount = %d\n",
+			dev->_frame_count_ch2);
 		return -1;
 	}
 	/* ElSE, set the interrupt mask register, re-enable irq. */
@@ -714,8 +709,8 @@
 	    request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
 			IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
 	if (err < 0) {
-		printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name,
-		       dev->pci->irq);
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
 		goto fail_irq;
 	}
 	/* Start the DMA  engine */
@@ -744,7 +739,7 @@
 	int str_length = 0;
 
 	if (dev->_is_running_ch2) {
-		printk("Video Channel is still running so return!\n");
+		pr_info("Video Channel is still running so return!\n");
 		return 0;
 	}
 
@@ -756,8 +751,7 @@
 	    create_singlethread_workqueue("cx25821_workqueue2");
 
 	if (!dev->_irq_queues_ch2) {
-		printk
-		    ("cx25821: create_singlethread_workqueue() for Video FAILED!\n");
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
 		return -ENOMEM;
 	}
 	/*
@@ -829,8 +823,7 @@
 	    cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
 						dev->_line_size_ch2);
 	if (retval < 0) {
-		printk(KERN_ERR
-		       "%s: Failed to set up Video upstream buffers!\n",
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
 		       dev->name);
 		goto error;
 	}
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c
index 16bf74d..31b4e3c 100644
--- a/drivers/staging/cx25821/cx25821-video-upstream.c
+++ b/drivers/staging/cx25821/cx25821-video-upstream.c
@@ -20,6 +20,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "cx25821-video.h"
 #include "cx25821-video-upstream.h"
 
@@ -257,8 +259,7 @@
 	u32 tmp = 0;
 
 	if (!dev->_is_running) {
-		printk
-		   (KERN_INFO "cx25821: No video file is currently running so return!\n");
+		pr_info("No video file is currently running so return!\n");
 		return;
 	}
 	/* Disable RISC interrupts */
@@ -346,23 +347,20 @@
 
 	if (IS_ERR(myfile)) {
 		const int open_errno = -PTR_ERR(myfile);
-		printk(KERN_ERR
-		   "%s(): ERROR opening file(%s) with errno = %d!\n",
-		   __func__, dev->_filename, open_errno);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename, open_errno);
 		return PTR_ERR(myfile);
 	} else {
 		if (!(myfile->f_op)) {
-			printk(KERN_ERR
-			   "%s: File has no file operations registered!",
-			   __func__);
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
 
 		if (!myfile->f_op->read) {
-			printk(KERN_ERR
-			   "%s: File has no READ operations registered!",
-			   __func__);
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
@@ -388,10 +386,8 @@
 			frame_offset += vfs_read_retval;
 
 			if (vfs_read_retval < line_size) {
-				printk(KERN_INFO
-				      "Done: exit %s() since no more bytes to \
-				      read from Video file.\n",
-				       __func__);
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
 				break;
 			}
 		}
@@ -415,9 +411,8 @@
 	    container_of(work, struct cx25821_dev, _irq_work_entry);
 
 	if (!dev) {
-		printk(KERN_ERR
-		   "ERROR %s(): since container_of(work_struct) FAILED!\n",
-		   __func__);
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
 		return;
 	}
 
@@ -443,23 +438,20 @@
 
 	if (IS_ERR(myfile)) {
 		const int open_errno = -PTR_ERR(myfile);
-	       printk(KERN_ERR  "%s(): ERROR opening file(%s) with errno = %d!\n",
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
 		       __func__, dev->_filename, open_errno);
 		return PTR_ERR(myfile);
 	} else {
 		if (!(myfile->f_op)) {
-			printk(KERN_ERR
-			   "%s: File has no file operations registered!",
-			   __func__);
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
 
 		if (!myfile->f_op->read) {
-			printk(KERN_ERR
-			   "%s: File has no READ operations registered!  \
-			   Returning.",
-			     __func__);
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
 			filp_close(myfile, NULL);
 			return -EIO;
 		}
@@ -487,10 +479,8 @@
 				offset += vfs_read_retval;
 
 				if (vfs_read_retval < line_size) {
-					printk(KERN_INFO
-					    "Done: exit %s() since no more \
-					    bytes to read from Video file.\n",
-					       __func__);
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
 					break;
 				}
 			}
@@ -534,9 +524,7 @@
 	dev->_risc_size = dev->upstream_riscbuf_size;
 
 	if (!dev->_dma_virt_addr) {
-		printk
-		   (KERN_ERR "cx25821: FAILED to allocate memory for Risc \
-		   buffer! Returning.\n");
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
 		return -ENOMEM;
 	}
 
@@ -556,9 +544,7 @@
 	dev->_data_buf_size = dev->upstream_databuf_size;
 
 	if (!dev->_data_buf_virt_addr) {
-		printk
-		   (KERN_ERR "cx25821: FAILED to allocate memory for data \
-		   buffer! Returning.\n");
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
 		return -ENOMEM;
 	}
 
@@ -574,8 +560,7 @@
 	    cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
 					 dev->_lines_count);
 	if (ret < 0) {
-		printk(KERN_INFO
-		    "cx25821: Failed creating Video Upstream Risc programs!\n");
+		pr_info("Failed creating Video Upstream Risc programs!\n");
 		goto error;
 	}
 
@@ -652,22 +637,20 @@
 		spin_unlock(&dev->slock);
 	} else {
 		if (status & FLD_VID_SRC_UF)
-			printk
-			   (KERN_ERR "%s: Video Received Underflow Error \
-			   Interrupt!\n", __func__);
+			pr_err("%s(): Video Received Underflow Error Interrupt!\n",
+			       __func__);
 
 		if (status & FLD_VID_SRC_SYNC)
-			printk(KERN_ERR "%s: Video Received Sync Error \
-				Interrupt!\n", __func__);
+			pr_err("%s(): Video Received Sync Error Interrupt!\n",
+			       __func__);
 
 		if (status & FLD_VID_SRC_OPC_ERR)
-			printk(KERN_ERR "%s: Video Received OpCode Error \
-				Interrupt!\n", __func__);
+			pr_err("%s(): Video Received OpCode Error Interrupt!\n",
+			       __func__);
 	}
 
 	if (dev->_file_status == END_OF_FILE) {
-		printk(KERN_ERR "cx25821: EOF Channel 1 Framecount = %d\n",
-		       dev->_frame_count);
+		pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count);
 		return -1;
 	}
 	/* ElSE, set the interrupt mask register, re-enable irq. */
@@ -775,8 +758,8 @@
 	    request_irq(dev->pci->irq, cx25821_upstream_irq,
 			IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
 	if (err < 0) {
-		printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name,
-		       dev->pci->irq);
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
 		goto fail_irq;
 	}
 
@@ -806,7 +789,7 @@
 	int str_length = 0;
 
 	if (dev->_is_running) {
-		printk(KERN_INFO "Video Channel is still running so return!\n");
+		pr_info("Video Channel is still running so return!\n");
 		return 0;
 	}
 
@@ -817,9 +800,7 @@
 	dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
 
 	if (!dev->_irq_queues) {
-		printk
-		   (KERN_ERR "cx25821: create_singlethread_workqueue() for \
-		   Video FAILED!\n");
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
 		return -ENOMEM;
 	}
 	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
@@ -895,8 +876,7 @@
 	/* Allocating buffers and prepare RISC program */
 	retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
 	if (retval < 0) {
-		printk(KERN_ERR
-		       "%s: Failed to set up Video upstream buffers!\n",
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
 		       dev->name);
 		goto error;
 	}
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c
index 5238930..0d8d756 100644
--- a/drivers/staging/cx25821/cx25821-video.c
+++ b/drivers/staging/cx25821/cx25821-video.c
@@ -24,7 +24,10 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "cx25821-video.h"
+#include <linux/smp_lock.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
 MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
@@ -104,7 +107,7 @@
 		if (formats[i].fourcc == fourcc)
 			return formats + i;
 
-	printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+	pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc);
 	return NULL;
 }
 
@@ -159,15 +162,15 @@
 	else
 		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
 	if (bc != 1)
-		printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
+		pr_err("%s: %d buffers handled (should be 1)\n",
 		       __func__, bc);
 }
 
 #ifdef TUNER_FLAG
 int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
 {
-	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__,
-		(unsigned int)norm, v4l2_norm_to_name(norm));
+	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+		__func__, (unsigned int)norm, v4l2_norm_to_name(norm));
 
 	dev->tvnorm = norm;
 
@@ -267,7 +270,7 @@
 	struct v4l2_routing route;
 	memset(&route, 0, sizeof(route));
 
-	dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+	dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
 		__func__, input, INPUT(input)->vmux, INPUT(input)->gpio0,
 		INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3);
 	dev->input = input;
@@ -400,8 +403,8 @@
 
 	/* risc op code error */
 	if (status & (1 << 16)) {
-		printk(KERN_WARNING "%s, %s: video risc op code error\n",
-		       dev->name, channel->name);
+		pr_warn("%s, %s: video risc op code error\n",
+			dev->name, channel->name);
 		cx_clear(channel->dma_ctl, 0x11);
 		cx25821_sram_channel_dump(dev, channel);
 	}
@@ -458,7 +461,7 @@
 	       btcx_riscmem_free(dev->pci,
 		       &dev->channels[chan_num].vidq.stopper);
 
-		printk(KERN_WARNING "device %d released!\n", chan_num);
+		pr_warn("device %d released!\n", chan_num);
 	}
 
 }
@@ -590,7 +593,7 @@
 		init_buffer = 1;
 		rc = videobuf_iolock(q, &buf->vb, NULL);
 		if (0 != rc) {
-			printk(KERN_DEBUG "videobuf_iolock failed!\n");
+			printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n"));
 			goto fail;
 		}
 	}
@@ -1038,8 +1041,8 @@
        dev->channels[fh->channel_id].cif_width = fh->width;
        medusa_set_resolution(dev, fh->width, SRAM_CH00);
 
-       dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width,
-	       fh->height, fh->vidq.field);
+	dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width,
+		fh->height, fh->vidq.field);
 	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
 	cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
 
@@ -1070,14 +1073,14 @@
        u32 tmp = 0;
 
        snprintf(name, sizeof(name), "%s/2", dev->name);
-       printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
-	      dev->name);
+	pr_info("%s/2: ============  START LOG STATUS  ============\n",
+		dev->name);
        cx25821_call_all(dev, core, log_status);
        tmp = cx_read(sram_ch->dma_ctl);
-       printk(KERN_INFO "Video input 0 is %s\n",
-	      (tmp & 0x11) ? "streaming" : "stopped");
-       printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
-	      dev->name);
+	pr_info("Video input 0 is %s\n",
+		(tmp & 0x11) ? "streaming" : "stopped");
+	pr_info("%s/2: =============  END LOG STATUS  =============\n",
+		dev->name);
        return 0;
 }
 
@@ -1186,34 +1189,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-int cx25821_vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct cx25821_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
-
 int cx25821_vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p)
 {
 	struct cx25821_fh *fh = priv;
@@ -1298,8 +1273,6 @@
 	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]);
 
@@ -1319,7 +1292,7 @@
 	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
 
 	*i = dev->input;
-	dprintk(1, "%s() returns %d\n", __func__, *i);
+	dprintk(1, "%s(): returns %d\n", __func__, *i);
 	return 0;
 }
 
@@ -1339,7 +1312,7 @@
 	}
 
 	if (i > 2) {
-		dprintk(1, "%s() -EINVAL\n", __func__);
+		dprintk(1, "%s(): -EINVAL\n", __func__);
 		return -EINVAL;
 	}
 
@@ -1390,7 +1363,7 @@
 		if (0 != err)
 			return err;
        } else {
-	       printk(KERN_ERR "Invalid fh pointer!\n");
+	       pr_err("Invalid fh pointer!\n");
 	       return -EINVAL;
 	}
 
@@ -1733,12 +1706,10 @@
 
        data_from_user = (struct upstream_user_struct *)arg;
 
-       if (!data_from_user) {
-	       printk
-		   ("cx25821 in %s(): Upstream data is INVALID. Returning.\n",
-		    __func__);
-	       return 0;
-       }
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
 
        command = data_from_user->command;
 
@@ -1776,12 +1747,10 @@
 
        data_from_user = (struct upstream_user_struct *)arg;
 
-       if (!data_from_user) {
-	       printk
-		   ("cx25821 in %s(): Upstream data is INVALID. Returning.\n",
-		    __func__);
-	       return 0;
-       }
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
 
        command = data_from_user->command;
 
@@ -1819,12 +1788,10 @@
 
        data_from_user = (struct upstream_user_struct *)arg;
 
-       if (!data_from_user) {
-	       printk
-		   ("cx25821 in %s(): Upstream data is INVALID. Returning.\n",
-		    __func__);
-	       return 0;
-       }
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
 
        command = data_from_user->command;
 
@@ -1866,12 +1833,10 @@
 
        data_from_user = (struct downstream_user_struct *)arg;
 
-       if (!data_from_user) {
-	       printk(
-	       "cx25821 in %s(): User data is INVALID. Returning.\n",
-	       __func__);
-	       return 0;
-       }
+	if (!data_from_user) {
+		pr_err("%s(): User data is INVALID. Returning\n", __func__);
+		return 0;
+	}
 
        command = data_from_user->command;
 
@@ -2022,9 +1987,6 @@
        .vidioc_log_status = vidioc_log_status,
        .vidioc_g_priority = cx25821_vidioc_g_priority,
        .vidioc_s_priority = cx25821_vidioc_s_priority,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       .vidiocgmbuf = cx25821_vidiocgmbuf,
-#endif
 #ifdef TUNER_FLAG
        .vidioc_g_tuner = cx25821_vidioc_g_tuner,
        .vidioc_s_tuner = cx25821_vidioc_s_tuner,
diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h
index a2415d3..f4ee805 100644
--- a/drivers/staging/cx25821/cx25821-video.h
+++ b/drivers/staging/cx25821/cx25821-video.h
@@ -40,19 +40,15 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/* Include V4L1 specific functions. Should be removed soon */
-#include <linux/videodev.h>
-#endif
-
 #define TUNER_FLAG
 
 #define VIDEO_DEBUG 0
 
-#define dprintk(level, fmt, arg...)\
-    do { if (VIDEO_DEBUG >= level)\
-	printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
-    } while (0)
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (VIDEO_DEBUG >= level)					\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
 
 /* For IOCTL to identify running upstream */
 #define UPSTREAM_START_VIDEO        700
@@ -133,7 +129,6 @@
 			   struct v4l2_capability *cap);
 extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 				   struct v4l2_fmtdesc *f);
-extern int cx25821_vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf);
 extern int cx25821_vidioc_reqbufs(struct file *file, void *priv,
 			  struct v4l2_requestbuffers *p);
 extern int cx25821_vidioc_querybuf(struct file *file, void *priv,
diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h
index c940001..5511523 100644
--- a/drivers/staging/cx25821/cx25821.h
+++ b/drivers/staging/cx25821/cx25821.h
@@ -519,9 +519,12 @@
 #define Set_GPIO_Bit(Bit)                       (1 << Bit)
 #define Clear_GPIO_Bit(Bit)                     (~(1 << Bit))
 
-#define CX25821_ERR(fmt, args...)      printk(KERN_ERR  "cx25821(%d): " fmt, dev->board, ## args)
-#define CX25821_WARN(fmt, args...)     printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args)
-#define CX25821_INFO(fmt, args...)     printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args)
+#define CX25821_ERR(fmt, args...)			\
+	pr_err("(%d): " fmt, dev->board, ##args)
+#define CX25821_WARN(fmt, args...)			\
+	pr_warn("(%d): " fmt, dev->board, ##args)
+#define CX25821_INFO(fmt, args...)			\
+	pr_info("(%d): " fmt, dev->board, ##args)
 
 extern int cx25821_i2c_register(struct cx25821_i2c *bus);
 extern void cx25821_card_setup(struct cx25821_dev *dev);
diff --git a/drivers/staging/dabusb/Kconfig b/drivers/staging/dabusb/Kconfig
new file mode 100644
index 0000000..87bdc42
--- /dev/null
+++ b/drivers/staging/dabusb/Kconfig
@@ -0,0 +1,14 @@
+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.
+
diff --git a/drivers/staging/dabusb/Makefile b/drivers/staging/dabusb/Makefile
new file mode 100644
index 0000000..2ff2f22
--- /dev/null
+++ b/drivers/staging/dabusb/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_USB_DABUSB)        += dabusb.o
+
diff --git a/drivers/staging/dabusb/TODO b/drivers/staging/dabusb/TODO
new file mode 100644
index 0000000..f9c0314
--- /dev/null
+++ b/drivers/staging/dabusb/TODO
@@ -0,0 +1,5 @@
+This is a driver for an experimental sample developed in 2003. The driver
+never supported any commercial product, nor had any known user.
+If nobody takes care on it, the driver will be removed for 2.6.39.
+
+Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/media/video/dabusb.c b/drivers/staging/dabusb/dabusb.c
similarity index 100%
rename from drivers/media/video/dabusb.c
rename to drivers/staging/dabusb/dabusb.c
diff --git a/drivers/media/video/dabusb.h b/drivers/staging/dabusb/dabusb.h
similarity index 100%
rename from drivers/media/video/dabusb.h
rename to drivers/staging/dabusb/dabusb.h
diff --git a/drivers/staging/dt3155v4l/dt3155v4l.c b/drivers/staging/dt3155v4l/dt3155v4l.c
index b996697..15d7efe 100644
--- a/drivers/staging/dt3155v4l/dt3155v4l.c
+++ b/drivers/staging/dt3155v4l/dt3155v4l.c
@@ -876,9 +876,6 @@
 	.vidioc_s_crop = dt3155_ioc_s_crop,
 	.vidioc_enum_framesizes = dt3155_ioc_enum_framesizes,
 	.vidioc_enum_frameintervals = dt3155_ioc_enum_frameintervals,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf = iocgmbuf,
-#endif
 */
 };
 
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index 3aecd30..1da57df 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -1,10 +1,10 @@
 config VIDEO_GO7007
 	tristate "WIS GO7007 MPEG encoder support"
-	depends on VIDEO_DEV && PCI && I2C && INPUT
+	depends on VIDEO_DEV && PCI && I2C
 	depends on BKL # please fix
 	depends on SND
 	select VIDEOBUF_DMA_SG
-	depends on VIDEO_IR
+	depends on RC_CORE
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select SND_PCM
diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig
index fa790db..cdaff59 100644
--- a/drivers/staging/lirc/Kconfig
+++ b/drivers/staging/lirc/Kconfig
@@ -14,26 +14,19 @@
 
 config LIRC_BT829
         tristate "BT829 based hardware"
-	depends on LIRC_STAGING && PCI
+	depends on LIRC && PCI
 	help
 	  Driver for the IR interface on BT829-based hardware
 
-config LIRC_I2C
-	tristate "I2C Based IR Receivers"
-	depends on LIRC_STAGING && I2C
-	help
-	  Driver for I2C-based IR receivers, such as those commonly
-	  found onboard Hauppauge PVR-150/250/350 video capture cards
-
 config LIRC_IGORPLUGUSB
 	tristate "Igor Cesko's USB IR Receiver"
-	depends on LIRC_STAGING && USB
+	depends on LIRC && USB
 	help
 	  Driver for Igor Cesko's USB IR Receiver
 
 config LIRC_IMON
 	tristate "Legacy SoundGraph iMON Receiver and Display"
-	depends on LIRC_STAGING && USB
+	depends on LIRC && USB
 	help
 	  Driver for the original SoundGraph iMON IR Receiver and Display
 
@@ -41,31 +34,31 @@
 
 config LIRC_IT87
 	tristate "ITE IT87XX CIR Port Receiver"
-	depends on LIRC_STAGING && PNP
+	depends on LIRC && PNP
 	help
 	  Driver for the ITE IT87xx IR Receiver
 
 config LIRC_ITE8709
 	tristate "ITE8709 CIR Port Receiver"
-	depends on LIRC_STAGING && PNP
+	depends on LIRC && PNP
 	help
 	  Driver for the ITE8709 IR Receiver
 
 config LIRC_PARALLEL
 	tristate "Homebrew Parallel Port Receiver"
-	depends on LIRC_STAGING && PARPORT
+	depends on LIRC && PARPORT
 	help
 	  Driver for Homebrew Parallel Port Receivers
 
 config LIRC_SASEM
 	tristate "Sasem USB IR Remote"
-	depends on LIRC_STAGING && USB
+	depends on LIRC && USB
 	help
 	  Driver for the Sasem OnAir Remocon-V or Dign HV5 HTPC IR/VFD Module
 
 config LIRC_SERIAL
 	tristate "Homebrew Serial Port Receiver"
-	depends on LIRC_STAGING
+	depends on LIRC
 	help
 	  Driver for Homebrew Serial Port Receivers
 
@@ -78,19 +71,19 @@
 
 config LIRC_SIR
 	tristate "Built-in SIR IrDA port"
-	depends on LIRC_STAGING
+	depends on LIRC
 	help
 	  Driver for the SIR IrDA port
 
 config LIRC_TTUSBIR
 	tristate "Technotrend USB IR Receiver"
-	depends on LIRC_STAGING && USB
+	depends on LIRC && USB
 	help
 	  Driver for the Technotrend USB IR Receiver
 
 config LIRC_ZILOG
 	tristate "Zilog/Hauppauge IR Transmitter"
-	depends on LIRC_STAGING && I2C
+	depends on LIRC && I2C
 	help
 	  Driver for the Zilog/Hauppauge IR Transmitter, found on
 	  PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards
diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile
index 4da1f33..94af218 100644
--- a/drivers/staging/lirc/Makefile
+++ b/drivers/staging/lirc/Makefile
@@ -4,7 +4,6 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_LIRC_BT829)	+= lirc_bt829.o
-obj-$(CONFIG_LIRC_I2C)		+= lirc_i2c.o
 obj-$(CONFIG_LIRC_IGORPLUGUSB)	+= lirc_igorplugusb.o
 obj-$(CONFIG_LIRC_IMON)		+= lirc_imon.o
 obj-$(CONFIG_LIRC_IT87)		+= lirc_it87.o
diff --git a/drivers/staging/lirc/TODO.lirc_i2c b/drivers/staging/lirc/TODO.lirc_i2c
deleted file mode 100644
index 1f0a6ff..0000000
--- a/drivers/staging/lirc/TODO.lirc_i2c
+++ /dev/null
@@ -1,3 +0,0 @@
-lirc_i2c provides support for some drivers that have already a RC
-driver under drivers/media/video. It should be integrated into those
-drivers, in special with drivers/media/video/ir-kbd-i2c.c.
diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog
new file mode 100644
index 0000000..6aa312d
--- /dev/null
+++ b/drivers/staging/lirc/TODO.lirc_zilog
@@ -0,0 +1,13 @@
+The binding between hdpvr and lirc_zilog is currently disabled,
+due to an OOPS reported a few years ago when both the hdpvr and cx18
+drivers were loaded in his system. More details can be seen at:
+	http://www.mail-archive.com/linux-media@vger.kernel.org/msg09163.html
+More tests need to be done, in order to fix the reported issue.
+
+There's a conflict between ir-kbd-i2c: Both provide support for RX events.
+Such conflict needs to be fixed, before moving it out of staging.
+
+The way I2C probe works, it will try to register the driver twice, one
+for RX and another for TX. The logic needs to be fixed to avoid such
+issue.
+
diff --git a/drivers/staging/lirc/lirc_i2c.c b/drivers/staging/lirc/lirc_i2c.c
deleted file mode 100644
index 6df2c0e..0000000
--- a/drivers/staging/lirc/lirc_i2c.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * lirc_i2c.c
- *
- * i2c IR driver for the onboard IR port on many TV tuner cards, including:
- *  -Flavors of the Hauppauge PVR-150/250/350
- *  -Hauppauge HVR-1300
- *  -PixelView (BT878P+W/FM)
- *  -KNC ONE TV Station/Anubis Typhoon TView Tuner
- *  -Asus TV-Box and Creative/VisionTek BreakOut-Box
- *  -Leadtek Winfast PVR2000
- *
- * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- * modified for PixelView (BT878P+W/FM) by
- *      Michal Kochanowicz <mkochano@pld.org.pl>
- *      Christoph Bartelmus <lirc@bartelmus.de>
- * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by
- *      Ulrich Mueller <ulrich.mueller42@web.de>
- * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by
- *      Stefan Jahn <stefan@lkcc.org>
- * modified for inclusion into kernel sources by
- *      Jerome Brock <jbrock@users.sourceforge.net>
- * modified for Leadtek Winfast PVR2000 by
- *      Thomas Reitmayr (treitmayr@yahoo.com)
- * modified for Hauppauge HVR-1300 by
- *      Jan Frey (jfrey@gmx.de)
- *
- * parts are cut&pasted from the old lirc_haup.c driver
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/sched.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/i2c-algo-bit.h>
-
-#include <media/lirc_dev.h>
-
-struct IR {
-	struct lirc_driver l;
-	struct i2c_client  c;
-	int nextkey;
-	unsigned char b[3];
-	unsigned char bits;
-	unsigned char flag;
-};
-
-#define DEVICE_NAME "lirc_i2c"
-
-/* module parameters */
-static int debug;	/* debug output */
-static int minor = -1;	/* minor number */
-
-#define dprintk(fmt, args...)						\
-	do {								\
-		if (debug)						\
-			printk(KERN_DEBUG DEVICE_NAME ": " fmt,		\
-			       ## args);				\
-	} while (0)
-
-static int reverse(int data, int bits)
-{
-	int i;
-	int c;
-
-	for (c = 0, i = 0; i < bits; i++)
-		c |= ((data & (1<<i)) ? 1 : 0) << (bits-1-i);
-
-	return c;
-}
-
-static int add_to_buf_adap(void *data, struct lirc_buffer *buf)
-{
-	struct IR *ir = data;
-	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)) {
-		dprintk("read error\n");
-		return -EIO;
-	}
-
-	dprintk("key (0x%02x%02x%02x%02x)\n",
-		keybuf[0], keybuf[1], keybuf[2], keybuf[3]);
-
-	/* key pressed ? */
-	if (keybuf[2] == 0xff)
-		return -ENODATA;
-
-	/* remove repeat bit */
-	keybuf[2] &= 0x7f;
-	keybuf[3] |= 0x80;
-
-	lirc_buffer_write(buf, keybuf);
-	return 0;
-}
-
-static int add_to_buf_pcf8574(void *data, struct lirc_buffer *buf)
-{
-	struct IR *ir = data;
-	int rc;
-	unsigned char all, mask;
-	unsigned char key;
-
-	/* compute all valid bits (key code + pressed/release flag) */
-	all = ir->bits | ir->flag;
-
-	/* save IR writable mask bits */
-	mask = i2c_smbus_read_byte(&ir->c) & ~all;
-
-	/* send bit mask */
-	rc = i2c_smbus_write_byte(&ir->c, (0xff & all) | mask);
-
-	/* receive scan code */
-	rc = i2c_smbus_read_byte(&ir->c);
-
-	if (rc == -1) {
-		dprintk("%s read error\n", ir->c.name);
-		return -EIO;
-	}
-
-	/* drop duplicate polls */
-	if (ir->b[0] == (rc & all))
-		return -ENODATA;
-
-	ir->b[0] = rc & all;
-
-	dprintk("%s key 0x%02X %s\n", ir->c.name, rc & ir->bits,
-		(rc & ir->flag) ? "released" : "pressed");
-
-	/* ignore released buttons */
-	if (rc & ir->flag)
-		return -ENODATA;
-
-	/* set valid key code */
-	key  = rc & ir->bits;
-	lirc_buffer_write(buf, &key);
-	return 0;
-}
-
-/* common for Hauppauge IR receivers */
-static int add_to_buf_haup_common(void *data, struct lirc_buffer *buf,
-		unsigned char *keybuf, int size, int offset)
-{
-	struct IR *ir = data;
-	__u16 code;
-	unsigned char codes[2];
-	int ret;
-
-	/* poll IR chip */
-	ret = i2c_master_recv(&ir->c, keybuf, size);
-	if (ret == size) {
-		ir->b[0] = keybuf[offset];
-		ir->b[1] = keybuf[offset+1];
-		ir->b[2] = keybuf[offset+2];
-		if (ir->b[0] != 0x00 && ir->b[1] != 0x00)
-			dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]);
-	} else {
-		dprintk("read error (ret=%d)\n", ret);
-		/* keep last successful read buffer */
-	}
-
-	/* key pressed ? */
-	if ((ir->b[0] & 0x80) == 0)
-		return -ENODATA;
-
-	/* look what we have */
-	code = (((__u16)ir->b[0]&0x7f)<<6) | (ir->b[1]>>2);
-
-	codes[0] = (code >> 8) & 0xff;
-	codes[1] = code & 0xff;
-
-	/* return it */
-	dprintk("sending code 0x%02x%02x to lirc\n", codes[0], codes[1]);
-	lirc_buffer_write(buf, codes);
-	return 0;
-}
-
-/* specific for the Hauppauge PVR150 IR receiver */
-static int add_to_buf_haup_pvr150(void *data, struct lirc_buffer *buf)
-{
-	unsigned char keybuf[6];
-	/* fetch 6 bytes, first relevant is at offset 3 */
-	return add_to_buf_haup_common(data, buf, keybuf, 6, 3);
-}
-
-/* used for all Hauppauge IR receivers but the PVR150 */
-static int add_to_buf_haup(void *data, struct lirc_buffer *buf)
-{
-	unsigned char keybuf[3];
-	/* fetch 3 bytes, first relevant is at offset 0 */
-	return add_to_buf_haup_common(data, buf, keybuf, 3, 0);
-}
-
-
-static int add_to_buf_pvr2000(void *data, struct lirc_buffer *buf)
-{
-	struct IR *ir = data;
-	unsigned char key;
-	s32 flags;
-	s32 code;
-
-	/* poll IR chip */
-	flags = i2c_smbus_read_byte_data(&ir->c, 0x10);
-	if (-1 == flags) {
-		dprintk("read error\n");
-		return -ENODATA;
-	}
-	/* key pressed ? */
-	if (0 == (flags & 0x80))
-		return -ENODATA;
-
-	/* read actual key code */
-	code = i2c_smbus_read_byte_data(&ir->c, 0x00);
-	if (-1 == code) {
-		dprintk("read error\n");
-		return -ENODATA;
-	}
-
-	key = code & 0xFF;
-
-	dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", key, flags & 0xFF);
-
-	/* return it */
-	lirc_buffer_write(buf, &key);
-	return 0;
-}
-
-static int add_to_buf_pixelview(void *data, struct lirc_buffer *buf)
-{
-	struct IR *ir = data;
-	unsigned char key;
-
-	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c, &key, 1)) {
-		dprintk("read error\n");
-		return -1;
-	}
-	dprintk("key %02x\n", key);
-
-	/* return it */
-	lirc_buffer_write(buf, &key);
-	return 0;
-}
-
-static int add_to_buf_pv951(void *data, struct lirc_buffer *buf)
-{
-	struct IR *ir = data;
-	unsigned char key;
-	unsigned char codes[4];
-
-	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c, &key, 1)) {
-		dprintk("read error\n");
-		return -ENODATA;
-	}
-	/* ignore 0xaa */
-	if (key == 0xaa)
-		return -ENODATA;
-	dprintk("key %02x\n", key);
-
-	codes[0] = 0x61;
-	codes[1] = 0xD6;
-	codes[2] = reverse(key, 8);
-	codes[3] = (~codes[2])&0xff;
-
-	lirc_buffer_write(buf, codes);
-	return 0;
-}
-
-static int add_to_buf_knc1(void *data, struct lirc_buffer *buf)
-{
-	static unsigned char last_key = 0xFF;
-	struct IR *ir = data;
-	unsigned char key;
-
-	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c, &key, 1)) {
-		dprintk("read error\n");
-		return -ENODATA;
-	}
-
-	/*
-	 * it seems that 0xFE indicates that a button is still held
-	 * down, while 0xFF indicates that no button is held
-	 * down. 0xFE sequences are sometimes interrupted by 0xFF
-	 */
-
-	dprintk("key %02x\n", key);
-
-	if (key == 0xFF)
-		return -ENODATA;
-
-	if (key == 0xFE)
-		key = last_key;
-
-	last_key = key;
-	lirc_buffer_write(buf, &key);
-
-	return 0;
-}
-
-static int set_use_inc(void *data)
-{
-	struct IR *ir = data;
-
-	dprintk("%s called\n", __func__);
-
-	/* lock bttv in memory while /dev/lirc is in use  */
-	i2c_use_client(&ir->c);
-
-	return 0;
-}
-
-static void set_use_dec(void *data)
-{
-	struct IR *ir = data;
-
-	dprintk("%s called\n", __func__);
-
-	i2c_release_client(&ir->c);
-}
-
-static struct lirc_driver lirc_template = {
-	.name		= "lirc_i2c",
-	.set_use_inc	= set_use_inc,
-	.set_use_dec	= set_use_dec,
-	.dev		= NULL,
-	.owner		= THIS_MODULE,
-};
-
-static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
-static int ir_remove(struct i2c_client *client);
-static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg);
-
-static const struct i2c_device_id ir_receiver_id[] = {
-	/* Generic entry for any IR receiver */
-	{ "ir_video", 0 },
-	/* IR device specific entries could be added here */
-	{ }
-};
-
-static struct i2c_driver driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "i2c ir driver",
-	},
-	.probe		= ir_probe,
-	.remove		= ir_remove,
-	.id_table	= ir_receiver_id,
-	.command	= ir_command,
-};
-
-static void pcf_probe(struct i2c_client *client, struct IR *ir)
-{
-	int ret1, ret2, ret3, ret4;
-
-	ret1 = i2c_smbus_write_byte(client, 0xff);
-	ret2 = i2c_smbus_read_byte(client);
-	ret3 = i2c_smbus_write_byte(client, 0x00);
-	ret4 = i2c_smbus_read_byte(client);
-
-	/* in the Asus TV-Box: bit 1-0 */
-	if (((ret2 & 0x03) == 0x03) && ((ret4 & 0x03) == 0x00)) {
-		ir->bits = (unsigned char) ~0x07;
-		ir->flag = 0x04;
-	/* in the Creative/VisionTek BreakOut-Box: bit 7-6 */
-	} else if (((ret2 & 0xc0) == 0xc0) && ((ret4 & 0xc0) == 0x00)) {
-		ir->bits = (unsigned char) ~0xe0;
-		ir->flag = 0x20;
-	}
-
-	return;
-}
-
-static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
-	struct IR *ir;
-	struct i2c_adapter *adap = client->adapter;
-	unsigned short addr = client->addr;
-	int retval;
-
-	ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
-	if (!ir)
-		return -ENOMEM;
-	memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
-	memcpy(&ir->c, client, sizeof(struct i2c_client));
-
-	i2c_set_clientdata(client, ir);
-	ir->l.data    = ir;
-	ir->l.minor   = minor;
-	ir->l.sample_rate = 10;
-	ir->l.dev     = &ir->c.dev;
-	ir->nextkey   = -1;
-
-	switch (addr) {
-	case 0x64:
-		strlcpy(ir->c.name, "Pixelview IR", I2C_NAME_SIZE);
-		ir->l.code_length = 8;
-		ir->l.add_to_buf = add_to_buf_pixelview;
-		break;
-	case 0x4b:
-		strlcpy(ir->c.name, "PV951 IR", I2C_NAME_SIZE);
-		ir->l.code_length = 32;
-		ir->l.add_to_buf = add_to_buf_pv951;
-		break;
-	case 0x71:
-		if (adap->id == I2C_HW_B_CX2388x)
-			strlcpy(ir->c.name, "Hauppauge HVR1300", I2C_NAME_SIZE);
-		else /* bt8xx or cx2341x */
-			/*
-			 * The PVR150 IR receiver uses the same protocol as
-			 * other Hauppauge cards, but the data flow is
-			 * different, so we need to deal with it by its own.
-			 */
-			strlcpy(ir->c.name, "Hauppauge PVR150", I2C_NAME_SIZE);
-		ir->l.code_length = 13;
-		ir->l.add_to_buf = add_to_buf_haup_pvr150;
-		break;
-	case 0x6b:
-		strlcpy(ir->c.name, "Adaptec IR", I2C_NAME_SIZE);
-		ir->l.code_length = 32;
-		ir->l.add_to_buf = add_to_buf_adap;
-		break;
-	case 0x18:
-	case 0x1a:
-		if (adap->id == I2C_HW_B_CX2388x) {
-			strlcpy(ir->c.name, "Leadtek IR", I2C_NAME_SIZE);
-			ir->l.code_length = 8;
-			ir->l.add_to_buf = add_to_buf_pvr2000;
-		} else { /* bt8xx or cx2341x */
-			strlcpy(ir->c.name, "Hauppauge IR", I2C_NAME_SIZE);
-			ir->l.code_length = 13;
-			ir->l.add_to_buf = add_to_buf_haup;
-		}
-		break;
-	case 0x30:
-		strlcpy(ir->c.name, "KNC ONE IR", I2C_NAME_SIZE);
-		ir->l.code_length = 8;
-		ir->l.add_to_buf = add_to_buf_knc1;
-		break;
-	case 0x21:
-	case 0x23:
-		pcf_probe(client, ir);
-		strlcpy(ir->c.name, "TV-Box IR", I2C_NAME_SIZE);
-		ir->l.code_length = 8;
-		ir->l.add_to_buf = add_to_buf_pcf8574;
-		break;
-	default:
-		/* shouldn't happen */
-		printk("lirc_i2c: Huh? unknown i2c address (0x%02x)?\n", addr);
-		kfree(ir);
-		return -EINVAL;
-	}
-	printk(KERN_INFO "lirc_i2c: chip 0x%x found @ 0x%02x (%s)\n",
-	       adap->id, addr, ir->c.name);
-
-	retval = lirc_register_driver(&ir->l);
-
-	if (retval < 0) {
-		printk(KERN_ERR "lirc_i2c: failed to register driver!\n");
-		kfree(ir);
-		return retval;
-	}
-
-	ir->l.minor = retval;
-
-	return 0;
-}
-
-static int ir_remove(struct i2c_client *client)
-{
-	struct IR *ir = i2c_get_clientdata(client);
-
-	/* unregister device */
-	lirc_unregister_driver(ir->l.minor);
-
-	/* free memory */
-	kfree(ir);
-	return 0;
-}
-
-static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-	/* nothing */
-	return 0;
-}
-
-static int __init lirc_i2c_init(void)
-{
-	i2c_add_driver(&driver);
-	return 0;
-}
-
-static void __exit lirc_i2c_exit(void)
-{
-	i2c_del_driver(&driver);
-}
-
-MODULE_DESCRIPTION("Infrared receiver driver for Hauppauge and "
-		   "Pixelview cards (i2c stack)");
-MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, "
-	      "Ulrich Mueller, Stefan Jahn, Jerome Brock");
-MODULE_LICENSE("GPL");
-
-module_param(minor, int, S_IRUGO);
-MODULE_PARM_DESC(minor, "Preferred minor device number");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
-
-module_init(lirc_i2c_init);
-module_exit(lirc_i2c_exit);
diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c
index 971844b..9bcf149 100644
--- a/drivers/staging/lirc/lirc_serial.c
+++ b/drivers/staging/lirc/lirc_serial.c
@@ -377,7 +377,7 @@
 	duty_cycle = new_duty_cycle;
 	freq = new_freq;
 
-	loops_per_sec = current_cpu_data.loops_per_jiffy;
+	loops_per_sec = __this_cpu_read(cpu.info.loops_per_jiffy);
 	loops_per_sec *= HZ;
 
 	/* How many clocks in a microsecond?, avoiding long long divide */
@@ -398,7 +398,7 @@
 	dprintk("in init_timing_params, freq=%d, duty_cycle=%d, "
 		"clk/jiffy=%ld, pulse=%ld, space=%ld, "
 		"conv_us_to_clocks=%ld\n",
-		freq, duty_cycle, current_cpu_data.loops_per_jiffy,
+		freq, duty_cycle, __this_cpu_read(cpu_info.loops_per_jiffy),
 		pulse_width, space_width, conv_us_to_clocks);
 	return 0;
 }
diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
index f0076eb..ad29bb1 100644
--- a/drivers/staging/lirc/lirc_zilog.c
+++ b/drivers/staging/lirc/lirc_zilog.c
@@ -66,6 +66,7 @@
 	/* Device info */
 	struct mutex ir_lock;
 	int open;
+	bool is_hdpvr;
 
 	/* RX device */
 	struct i2c_client c_rx;
@@ -206,16 +207,12 @@
 		}
 
 		/* key pressed ? */
-#ifdef I2C_HW_B_HDPVR
-		if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR) {
+		if (ir->is_hdpvr) {
 			if (got_data && (keybuf[0] == 0x80))
 				return 0;
 			else if (got_data && (keybuf[0] == 0x00))
 				return -ENODATA;
 		} else if ((ir->b[0] & 0x80) == 0)
-#else
-		if ((ir->b[0] & 0x80) == 0)
-#endif
 			return got_data ? 0 : -ENODATA;
 
 		/* look what we have */
@@ -841,15 +838,15 @@
 		return ret < 0 ? ret : -EFAULT;
 	}
 
-#ifdef I2C_HW_B_HDPVR
 	/*
 	 * The sleep bits aren't necessary on the HD PVR, and in fact, the
 	 * last i2c_master_recv always fails with a -5, so for now, we're
 	 * going to skip this whole mess and say we're done on the HD PVR
 	 */
-	if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR)
-		goto done;
-#endif
+	if (ir->is_hdpvr) {
+		dprintk("sent code %u, key %u\n", code, key);
+		return 0;
+	}
 
 	/*
 	 * This bit NAKs until the device is ready, so we retry it
@@ -883,7 +880,6 @@
 		return -EFAULT;
 	}
 
-done:
 	/* Oh good, it worked */
 	dprintk("sent code %u, key %u\n", code, key);
 	return 0;
@@ -1112,12 +1108,14 @@
 static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
 static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg);
 
+#define ID_FLAG_TX	0x01
+#define ID_FLAG_HDPVR	0x02
+
 static const struct i2c_device_id ir_transceiver_id[] = {
-	/* Generic entry for any IR transceiver */
-	{ "ir_video", 0 },
-	/* IR device specific entries should be added here */
-	{ "ir_tx_z8f0811_haup", 0 },
-	{ "ir_rx_z8f0811_haup", 0 },
+	{ "ir_tx_z8f0811_haup",  ID_FLAG_TX                 },
+	{ "ir_rx_z8f0811_haup",  0                          },
+	{ "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX },
+	{ "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR              },
 	{ }
 };
 
@@ -1197,10 +1195,25 @@
 	int ret;
 	int have_rx = 0, have_tx = 0;
 
-	dprintk("%s: adapter id=0x%x, client addr=0x%02x\n",
-		__func__, adap->id, client->addr);
+	dprintk("%s: adapter name (%s) nr %d, i2c_device_id name (%s), "
+		"client addr=0x%02x\n",
+		__func__, adap->name, adap->nr, id->name, client->addr);
 
 	/*
+	 * FIXME - This probe function probes both the Tx and Rx
+	 * addresses of the IR microcontroller.
+	 *
+	 * However, the I2C subsystem is passing along one I2C client at a
+	 * time, based on matches to the ir_transceiver_id[] table above.
+	 * The expectation is that each i2c_client address will be probed
+	 * individually by drivers so the I2C subsystem can mark all client
+	 * addresses as claimed or not.
+	 *
+	 * This probe routine causes only one of the client addresses, TX or RX,
+	 * to be claimed.  This will cause a problem if the I2C subsystem is
+	 * subsequently triggered to probe unclaimed clients again.
+	 */
+	/*
 	 * The external IR receiver is at i2c address 0x71.
 	 * The IR transmitter is at 0x70.
 	 */
@@ -1242,6 +1255,7 @@
 	mutex_init(&ir->ir_lock);
 	mutex_init(&ir->buf_lock);
 	ir->need_boot = 1;
+	ir->is_hdpvr = (id->driver_data & ID_FLAG_HDPVR) ? true : false;
 
 	memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
 	ir->l.minor = -1;
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index 61685cc..56d3a4e 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -826,6 +826,13 @@
 	.set_page_dirty 	= __set_page_dirty_nobuffers,
 };
 
+static void pohmelfs_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(pohmelfs_inode_cache, POHMELFS_I(inode));
+}
+
 /*
  * ->detroy_inode() callback. Deletes inode from the caches
  *  and frees private data.
@@ -842,8 +849,8 @@
 
 	dprintk("%s: pi: %p, inode: %p, ino: %llu.\n",
 		__func__, pi, &pi->vfs_inode, pi->ino);
-	kmem_cache_free(pohmelfs_inode_cache, pi);
 	atomic_long_dec(&psb->total_inodes);
+	call_rcu(&inode->i_rcu, pohmelfs_i_callback);
 }
 
 /*
@@ -1318,8 +1325,8 @@
 	}
 
 	psb->trans_scan_timeout = psb->drop_scan_timeout = 0;
-	cancel_rearming_delayed_work(&psb->dwork);
-	cancel_rearming_delayed_work(&psb->drop_dwork);
+	cancel_delayed_work_sync(&psb->dwork);
+	cancel_delayed_work_sync(&psb->drop_dwork);
 	flush_scheduled_work();
 
 	dprintk("%s: stopped workqueues.\n", __func__);
diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c
index 8ec83d2..400a9fc 100644
--- a/drivers/staging/pohmelfs/path_entry.c
+++ b/drivers/staging/pohmelfs/path_entry.c
@@ -83,10 +83,11 @@
 int pohmelfs_path_length(struct pohmelfs_inode *pi)
 {
 	struct dentry *d, *root, *first;
-	int len = 1; /* Root slash */
+	int len;
+	unsigned seq;
 
-	first = d = d_find_alias(&pi->vfs_inode);
-	if (!d) {
+	first = d_find_alias(&pi->vfs_inode);
+	if (!first) {
 		dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode);
 		return -ENOENT;
 	}
@@ -95,7 +96,11 @@
 	root = dget(current->fs->root.dentry);
 	spin_unlock(&current->fs->lock);
 
-	spin_lock(&dcache_lock);
+rename_retry:
+	len = 1; /* Root slash */
+	d = first;
+	seq = read_seqbegin(&rename_lock);
+	rcu_read_lock();
 
 	if (!IS_ROOT(d) && d_unhashed(d))
 		len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */
@@ -104,7 +109,9 @@
 		len += d->d_name.len + 1; /* Plus slash */
 		d = d->d_parent;
 	}
-	spin_unlock(&dcache_lock);
+	rcu_read_unlock();
+	if (read_seqretry(&rename_lock, seq))
+		goto rename_retry;
 
 	dput(root);
 	dput(first);
diff --git a/drivers/staging/se401/Kconfig b/drivers/staging/se401/Kconfig
new file mode 100644
index 0000000..b7f8222
--- /dev/null
+++ b/drivers/staging/se401/Kconfig
@@ -0,0 +1,13 @@
+config USB_SE401
+	tristate "USB SE401 Camera support (DEPRECATED)"
+	depends on VIDEO_DEV && VIDEO_V4L2_COMMON && USB
+	---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.
+
+	  This driver uses the deprecated V4L1 API and will be removed in
+	  2.6.39, unless someone converts it to the V4L2 API.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called se401.
diff --git a/drivers/staging/se401/Makefile b/drivers/staging/se401/Makefile
new file mode 100644
index 0000000..b465d49
--- /dev/null
+++ b/drivers/staging/se401/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_SE401)         += se401.o
diff --git a/drivers/staging/se401/TODO b/drivers/staging/se401/TODO
new file mode 100644
index 0000000..3b2c038
--- /dev/null
+++ b/drivers/staging/se401/TODO
@@ -0,0 +1,5 @@
+This is an obsolete driver for some old webcams that still use V4L1 API. 
+As V4L1 support is being removed from kernel, if nobody take care on it, 
+the driver will be removed for 2.6.39.
+
+Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/media/video/se401.c b/drivers/staging/se401/se401.c
similarity index 100%
rename from drivers/media/video/se401.c
rename to drivers/staging/se401/se401.c
diff --git a/drivers/staging/se401/se401.h b/drivers/staging/se401/se401.h
new file mode 100644
index 0000000..2758f47
--- /dev/null
+++ b/drivers/staging/se401/se401.h
@@ -0,0 +1,236 @@
+
+#ifndef __LINUX_se401_H
+#define __LINUX_se401_H
+
+#include <linux/uaccess.h>
+#include "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 --git a/drivers/staging/se401/videodev.h b/drivers/staging/se401/videodev.h
new file mode 100644
index 0000000..f11efbe
--- /dev/null
+++ b/drivers/staging/se401/videodev.h
@@ -0,0 +1,318 @@
+/*
+ *	Video for Linux version 1 - OBSOLETE
+ *
+ *	Header file for v4l1 drivers and applications, for
+ *	Linux kernels 2.2.x or 2.4.x.
+ *
+ *	Provides header for legacy drivers and applications
+ *
+ *	See http://linuxtv.org for more info
+ *
+ */
+#ifndef __LINUX_VIDEODEV_H
+#define __LINUX_VIDEODEV_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/videodev2.h>
+
+#define VID_TYPE_CAPTURE	1	/* Can capture */
+#define VID_TYPE_TUNER		2	/* Can tune */
+#define VID_TYPE_TELETEXT	4	/* Does teletext */
+#define VID_TYPE_OVERLAY	8	/* Overlay onto frame buffer */
+#define VID_TYPE_CHROMAKEY	16	/* Overlay by chromakey */
+#define VID_TYPE_CLIPPING	32	/* Can clip */
+#define VID_TYPE_FRAMERAM	64	/* Uses the frame buffer memory */
+#define VID_TYPE_SCALES		128	/* Scalable */
+#define VID_TYPE_MONOCHROME	256	/* Monochrome only */
+#define VID_TYPE_SUBCAPTURE	512	/* Can capture subareas of the image */
+#define VID_TYPE_MPEG_DECODER	1024	/* Can decode MPEG streams */
+#define VID_TYPE_MPEG_ENCODER	2048	/* Can encode MPEG streams */
+#define VID_TYPE_MJPEG_DECODER	4096	/* Can decode MJPEG streams */
+#define VID_TYPE_MJPEG_ENCODER	8192	/* Can encode MJPEG streams */
+
+struct video_capability
+{
+	char name[32];
+	int type;
+	int channels;	/* Num channels */
+	int audios;	/* Num audio devices */
+	int maxwidth;	/* Supported width */
+	int maxheight;	/* And height */
+	int minwidth;	/* Supported width */
+	int minheight;	/* And height */
+};
+
+
+struct video_channel
+{
+	int channel;
+	char name[32];
+	int tuners;
+	__u32  flags;
+#define VIDEO_VC_TUNER		1	/* Channel has a tuner */
+#define VIDEO_VC_AUDIO		2	/* Channel has audio */
+	__u16  type;
+#define VIDEO_TYPE_TV		1
+#define VIDEO_TYPE_CAMERA	2
+	__u16 norm;			/* Norm set by channel */
+};
+
+struct video_tuner
+{
+	int tuner;
+	char name[32];
+	unsigned long rangelow, rangehigh;	/* Tuner range */
+	__u32 flags;
+#define VIDEO_TUNER_PAL		1
+#define VIDEO_TUNER_NTSC	2
+#define VIDEO_TUNER_SECAM	4
+#define VIDEO_TUNER_LOW		8	/* Uses KHz not MHz */
+#define VIDEO_TUNER_NORM	16	/* Tuner can set norm */
+#define VIDEO_TUNER_STEREO_ON	128	/* Tuner is seeing stereo */
+#define VIDEO_TUNER_RDS_ON      256     /* Tuner is seeing an RDS datastream */
+#define VIDEO_TUNER_MBS_ON      512     /* Tuner is seeing an MBS datastream */
+	__u16 mode;			/* PAL/NTSC/SECAM/OTHER */
+#define VIDEO_MODE_PAL		0
+#define VIDEO_MODE_NTSC		1
+#define VIDEO_MODE_SECAM	2
+#define VIDEO_MODE_AUTO		3
+	__u16 signal;			/* Signal strength 16bit scale */
+};
+
+struct video_picture
+{
+	__u16	brightness;
+	__u16	hue;
+	__u16	colour;
+	__u16	contrast;
+	__u16	whiteness;	/* Black and white only */
+	__u16	depth;		/* Capture depth */
+	__u16   palette;	/* Palette in use */
+#define VIDEO_PALETTE_GREY	1	/* Linear greyscale */
+#define VIDEO_PALETTE_HI240	2	/* High 240 cube (BT848) */
+#define VIDEO_PALETTE_RGB565	3	/* 565 16 bit RGB */
+#define VIDEO_PALETTE_RGB24	4	/* 24bit RGB */
+#define VIDEO_PALETTE_RGB32	5	/* 32bit RGB */
+#define VIDEO_PALETTE_RGB555	6	/* 555 15bit RGB */
+#define VIDEO_PALETTE_YUV422	7	/* YUV422 capture */
+#define VIDEO_PALETTE_YUYV	8
+#define VIDEO_PALETTE_UYVY	9	/* The great thing about standards is ... */
+#define VIDEO_PALETTE_YUV420	10
+#define VIDEO_PALETTE_YUV411	11	/* YUV411 capture */
+#define VIDEO_PALETTE_RAW	12	/* RAW capture (BT848) */
+#define VIDEO_PALETTE_YUV422P	13	/* YUV 4:2:2 Planar */
+#define VIDEO_PALETTE_YUV411P	14	/* YUV 4:1:1 Planar */
+#define VIDEO_PALETTE_YUV420P	15	/* YUV 4:2:0 Planar */
+#define VIDEO_PALETTE_YUV410P	16	/* YUV 4:1:0 Planar */
+#define VIDEO_PALETTE_PLANAR	13	/* start of planar entries */
+#define VIDEO_PALETTE_COMPONENT 7	/* start of component entries */
+};
+
+struct video_audio
+{
+	int	audio;		/* Audio channel */
+	__u16	volume;		/* If settable */
+	__u16	bass, treble;
+	__u32	flags;
+#define VIDEO_AUDIO_MUTE	1
+#define VIDEO_AUDIO_MUTABLE	2
+#define VIDEO_AUDIO_VOLUME	4
+#define VIDEO_AUDIO_BASS	8
+#define VIDEO_AUDIO_TREBLE	16
+#define VIDEO_AUDIO_BALANCE	32
+	char    name[16];
+#define VIDEO_SOUND_MONO	1
+#define VIDEO_SOUND_STEREO	2
+#define VIDEO_SOUND_LANG1	4
+#define VIDEO_SOUND_LANG2	8
+	__u16   mode;
+	__u16	balance;	/* Stereo balance */
+	__u16	step;		/* Step actual volume uses */
+};
+
+struct video_clip
+{
+	__s32	x,y;
+	__s32	width, height;
+	struct	video_clip *next;	/* For user use/driver use only */
+};
+
+struct video_window
+{
+	__u32	x,y;			/* Position of window */
+	__u32	width,height;		/* Its size */
+	__u32	chromakey;
+	__u32	flags;
+	struct	video_clip __user *clips;	/* Set only */
+	int	clipcount;
+#define VIDEO_WINDOW_INTERLACE	1
+#define VIDEO_WINDOW_CHROMAKEY	16	/* Overlay by chromakey */
+#define VIDEO_CLIP_BITMAP	-1
+/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
+#define VIDEO_CLIPMAP_SIZE	(128 * 625)
+};
+
+struct video_capture
+{
+	__u32 	x,y;			/* Offsets into image */
+	__u32	width, height;		/* Area to capture */
+	__u16	decimation;		/* Decimation divider */
+	__u16	flags;			/* Flags for capture */
+#define VIDEO_CAPTURE_ODD		0	/* Temporal */
+#define VIDEO_CAPTURE_EVEN		1
+};
+
+struct video_buffer
+{
+	void	*base;
+	int	height,width;
+	int	depth;
+	int	bytesperline;
+};
+
+struct video_mmap
+{
+	unsigned	int frame;		/* Frame (0 - n) for double buffer */
+	int		height,width;
+	unsigned	int format;		/* should be VIDEO_PALETTE_* */
+};
+
+struct video_key
+{
+	__u8	key[8];
+	__u32	flags;
+};
+
+struct video_mbuf
+{
+	int	size;		/* Total memory to map */
+	int	frames;		/* Frames */
+	int	offsets[VIDEO_MAX_FRAME];
+};
+
+#define 	VIDEO_NO_UNIT	(-1)
+
+struct video_unit
+{
+	int 	video;		/* Video minor */
+	int	vbi;		/* VBI minor */
+	int	radio;		/* Radio minor */
+	int	audio;		/* Audio minor */
+	int	teletext;	/* Teletext minor */
+};
+
+struct vbi_format {
+	__u32	sampling_rate;	/* in Hz */
+	__u32	samples_per_line;
+	__u32	sample_format;	/* VIDEO_PALETTE_RAW only (1 byte) */
+	__s32	start[2];	/* starting line for each frame */
+	__u32	count[2];	/* count of lines for each frame */
+	__u32	flags;
+#define	VBI_UNSYNC	1	/* can distingues between top/bottom field */
+#define	VBI_INTERLACED	2	/* lines are interlaced */
+};
+
+/* video_info is biased towards hardware mpeg encode/decode */
+/* but it could apply generically to any hardware compressor/decompressor */
+struct video_info
+{
+	__u32	frame_count;	/* frames output since decode/encode began */
+	__u32	h_size;		/* current unscaled horizontal size */
+	__u32	v_size;		/* current unscaled veritcal size */
+	__u32	smpte_timecode;	/* current SMPTE timecode (for current GOP) */
+	__u32	picture_type;	/* current picture type */
+	__u32	temporal_reference;	/* current temporal reference */
+	__u8	user_data[256];	/* user data last found in compressed stream */
+	/* user_data[0] contains user data flags, user_data[1] has count */
+};
+
+/* generic structure for setting playback modes */
+struct video_play_mode
+{
+	int	mode;
+	int	p1;
+	int	p2;
+};
+
+/* for loading microcode / fpga programming */
+struct video_code
+{
+	char	loadwhat[16];	/* name or tag of file being passed */
+	int	datasize;
+	__u8	*data;
+};
+
+#define VIDIOCGCAP		_IOR('v',1,struct video_capability)	/* Get capabilities */
+#define VIDIOCGCHAN		_IOWR('v',2,struct video_channel)	/* Get channel info (sources) */
+#define VIDIOCSCHAN		_IOW('v',3,struct video_channel)	/* Set channel 	*/
+#define VIDIOCGTUNER		_IOWR('v',4,struct video_tuner)		/* Get tuner abilities */
+#define VIDIOCSTUNER		_IOW('v',5,struct video_tuner)		/* Tune the tuner for the current channel */
+#define VIDIOCGPICT		_IOR('v',6,struct video_picture)	/* Get picture properties */
+#define VIDIOCSPICT		_IOW('v',7,struct video_picture)	/* Set picture properties */
+#define VIDIOCCAPTURE		_IOW('v',8,int)				/* Start, end capture */
+#define VIDIOCGWIN		_IOR('v',9, struct video_window)	/* Get the video overlay window */
+#define VIDIOCSWIN		_IOW('v',10, struct video_window)	/* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
+#define VIDIOCGFBUF		_IOR('v',11, struct video_buffer)	/* Get frame buffer */
+#define VIDIOCSFBUF		_IOW('v',12, struct video_buffer)	/* Set frame buffer - root only */
+#define VIDIOCKEY		_IOR('v',13, struct video_key)		/* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
+#define VIDIOCGFREQ		_IOR('v',14, unsigned long)		/* Set tuner */
+#define VIDIOCSFREQ		_IOW('v',15, unsigned long)		/* Set tuner */
+#define VIDIOCGAUDIO		_IOR('v',16, struct video_audio)	/* Get audio info */
+#define VIDIOCSAUDIO		_IOW('v',17, struct video_audio)	/* Audio source, mute etc */
+#define VIDIOCSYNC		_IOW('v',18, int)			/* Sync with mmap grabbing */
+#define VIDIOCMCAPTURE		_IOW('v',19, struct video_mmap)		/* Grab frames */
+#define VIDIOCGMBUF		_IOR('v',20, struct video_mbuf)		/* Memory map buffer info */
+#define VIDIOCGUNIT		_IOR('v',21, struct video_unit)		/* Get attached units */
+#define VIDIOCGCAPTURE		_IOR('v',22, struct video_capture)	/* Get subcapture */
+#define VIDIOCSCAPTURE		_IOW('v',23, struct video_capture)	/* Set subcapture */
+#define VIDIOCSPLAYMODE		_IOW('v',24, struct video_play_mode)	/* Set output video mode/feature */
+#define VIDIOCSWRITEMODE	_IOW('v',25, int)			/* Set write mode */
+#define VIDIOCGPLAYINFO		_IOR('v',26, struct video_info)		/* Get current playback info from hardware */
+#define VIDIOCSMICROCODE	_IOW('v',27, struct video_code)		/* Load microcode into hardware */
+#define	VIDIOCGVBIFMT		_IOR('v',28, struct vbi_format)		/* Get VBI information */
+#define	VIDIOCSVBIFMT		_IOW('v',29, struct vbi_format)		/* Set VBI information */
+
+
+#define BASE_VIDIOCPRIVATE	192		/* 192-255 are private */
+
+/* VIDIOCSWRITEMODE */
+#define VID_WRITE_MPEG_AUD		0
+#define VID_WRITE_MPEG_VID		1
+#define VID_WRITE_OSD			2
+#define VID_WRITE_TTX			3
+#define VID_WRITE_CC			4
+#define VID_WRITE_MJPEG			5
+
+/* VIDIOCSPLAYMODE */
+#define VID_PLAY_VID_OUT_MODE		0
+	/* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
+#define VID_PLAY_GENLOCK		1
+	/* p1: 0 = OFF, 1 = ON */
+	/* p2: GENLOCK FINE DELAY value */
+#define VID_PLAY_NORMAL			2
+#define VID_PLAY_PAUSE			3
+#define VID_PLAY_SINGLE_FRAME		4
+#define VID_PLAY_FAST_FORWARD		5
+#define VID_PLAY_SLOW_MOTION		6
+#define VID_PLAY_IMMEDIATE_NORMAL	7
+#define VID_PLAY_SWITCH_CHANNELS	8
+#define VID_PLAY_FREEZE_FRAME		9
+#define VID_PLAY_STILL_MODE		10
+#define VID_PLAY_MASTER_MODE		11
+	/* p1: see below */
+#define		VID_PLAY_MASTER_NONE	1
+#define		VID_PLAY_MASTER_VIDEO	2
+#define		VID_PLAY_MASTER_AUDIO	3
+#define VID_PLAY_ACTIVE_SCANLINES	12
+	/* p1 = first active; p2 = last active */
+#define VID_PLAY_RESET			13
+#define VID_PLAY_END_MARK		14
+
+#endif /* __LINUX_VIDEODEV_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/staging/smbfs/cache.c b/drivers/staging/smbfs/cache.c
index dbb9865..f2a1323 100644
--- a/drivers/staging/smbfs/cache.c
+++ b/drivers/staging/smbfs/cache.c
@@ -62,7 +62,7 @@
 	struct list_head *next;
 	struct dentry *dentry;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 	next = parent->d_subdirs.next;
 	while (next != &parent->d_subdirs) {
 		dentry = list_entry(next, struct dentry, d_u.d_child);
@@ -70,7 +70,7 @@
 		smb_age_dentry(server, dentry);
 		next = next->next;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&parent->d_lock);
 }
 
 /*
@@ -96,13 +96,13 @@
 	}
 
 	/* If a pointer is invalid, we search the dentry. */
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 	next = parent->d_subdirs.next;
 	while (next != &parent->d_subdirs) {
 		dent = list_entry(next, struct dentry, d_u.d_child);
 		if ((unsigned long)dent->d_fsdata == fpos) {
 			if (dent->d_inode)
-				dget_locked(dent);
+				dget(dent);
 			else
 				dent = NULL;
 			goto out_unlock;
@@ -111,7 +111,7 @@
 	}
 	dent = NULL;
 out_unlock:
-	spin_unlock(&dcache_lock);
+	spin_unlock(&parent->d_lock);
 	return dent;
 }
 
@@ -134,7 +134,7 @@
 	qname->hash = full_name_hash(qname->name, qname->len);
 
 	if (dentry->d_op && dentry->d_op->d_hash)
-		if (dentry->d_op->d_hash(dentry, qname) != 0)
+		if (dentry->d_op->d_hash(dentry, inode, qname) != 0)
 			goto end_advance;
 
 	newdent = d_lookup(dentry, qname);
@@ -145,8 +145,8 @@
 			goto end_advance;
 	} else {
 		hashed = 1;
-		memcpy((char *) newdent->d_name.name, qname->name,
-		       newdent->d_name.len);
+		/* dir i_mutex is locked because we're in readdir */
+		dentry_update_name_case(newdent, qname);
 	}
 
 	if (!newdent->d_inode) {
diff --git a/drivers/staging/smbfs/dir.c b/drivers/staging/smbfs/dir.c
index f088ea2..dd612f5 100644
--- a/drivers/staging/smbfs/dir.c
+++ b/drivers/staging/smbfs/dir.c
@@ -14,6 +14,7 @@
 #include <linux/ctype.h>
 #include <linux/net.h>
 #include <linux/sched.h>
+#include <linux/namei.h>
 
 #include "smb_fs.h"
 #include "smb_mount.h"
@@ -274,9 +275,13 @@
  * Dentry operations routines
  */
 static int smb_lookup_validate(struct dentry *, struct nameidata *);
-static int smb_hash_dentry(struct dentry *, struct qstr *);
-static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
-static int smb_delete_dentry(struct dentry *);
+static int smb_hash_dentry(const struct dentry *, const struct inode *,
+		struct qstr *);
+static int smb_compare_dentry(const struct dentry *,
+		const struct inode *,
+		const struct dentry *, const struct inode *,
+		unsigned int, const char *, const struct qstr *);
+static int smb_delete_dentry(const struct dentry *);
 
 static const struct dentry_operations smbfs_dentry_operations =
 {
@@ -297,13 +302,20 @@
  * This is the callback when the dcache has a lookup hit.
  */
 static int
-smb_lookup_validate(struct dentry * dentry, struct nameidata *nd)
+smb_lookup_validate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	struct inode * inode = dentry->d_inode;
-	unsigned long age = jiffies - dentry->d_time;
+	struct smb_sb_info *server;
+	struct inode *inode;
+	unsigned long age;
 	int valid;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	server = server_from_dentry(dentry);
+	inode = dentry->d_inode;
+	age = jiffies - dentry->d_time;
+
 	/*
 	 * The default validation is based on dentry age:
 	 * we believe in dentries for a few seconds.  (But each
@@ -333,7 +345,8 @@
 }
 
 static int 
-smb_hash_dentry(struct dentry *dir, struct qstr *this)
+smb_hash_dentry(const struct dentry *dir, const struct inode *inode,
+		struct qstr *this)
 {
 	unsigned long hash;
 	int i;
@@ -347,14 +360,17 @@
 }
 
 static int
-smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b)
+smb_compare_dentry(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
 	int i, result = 1;
 
-	if (a->len != b->len)
+	if (len != name->len)
 		goto out;
-	for (i=0; i < a->len; i++) {
-		if (tolower(a->name[i]) != tolower(b->name[i]))
+	for (i=0; i < len; i++) {
+		if (tolower(str[i]) != tolower(name->name[i]))
 			goto out;
 	}
 	result = 0;
@@ -367,7 +383,7 @@
  * We use this to unhash dentries with bad inodes.
  */
 static int
-smb_delete_dentry(struct dentry * dentry)
+smb_delete_dentry(const struct dentry *dentry)
 {
 	if (dentry->d_inode) {
 		if (is_bad_inode(dentry->d_inode)) {
@@ -390,9 +406,9 @@
 	struct smb_sb_info *server = server_from_dentry(dentry);
 
 	if (server->mnt->flags & SMB_MOUNT_CASE)
-		dentry->d_op = &smbfs_dentry_operations_case;
+		d_set_d_op(dentry, &smbfs_dentry_operations_case);
 	else
-		dentry->d_op = &smbfs_dentry_operations;
+		d_set_d_op(dentry, &smbfs_dentry_operations);
 	dentry->d_time = jiffies;
 }
 
@@ -454,9 +470,9 @@
 	add_entry:
 			server = server_from_dentry(dentry);
 			if (server->mnt->flags & SMB_MOUNT_CASE)
-				dentry->d_op = &smbfs_dentry_operations_case;
+				d_set_d_op(dentry, &smbfs_dentry_operations_case);
 			else
-				dentry->d_op = &smbfs_dentry_operations;
+				d_set_d_op(dentry, &smbfs_dentry_operations);
 
 			d_add(dentry, inode);
 			smb_renew_times(dentry);
diff --git a/drivers/staging/smbfs/file.c b/drivers/staging/smbfs/file.c
index 5dcd19c..31372e7 100644
--- a/drivers/staging/smbfs/file.c
+++ b/drivers/staging/smbfs/file.c
@@ -407,11 +407,14 @@
  * privileges, so we need our own check for this.
  */
 static int
-smb_file_permission(struct inode *inode, int mask)
+smb_file_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	int mode = inode->i_mode;
 	int error = 0;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	VERBOSE("mode=%x, mask=%x\n", mode, mask);
 
 	/* Look at user permissions */
diff --git a/drivers/staging/smbfs/inode.c b/drivers/staging/smbfs/inode.c
index 540a984..244319d 100644
--- a/drivers/staging/smbfs/inode.c
+++ b/drivers/staging/smbfs/inode.c
@@ -62,9 +62,16 @@
 	return &ei->vfs_inode;
 }
 
+static void smb_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(smb_inode_cachep, SMB_I(inode));
+}
+
 static void smb_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(smb_inode_cachep, SMB_I(inode));
+	call_rcu(&inode->i_rcu, smb_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/drivers/staging/speakup/fakekey.c b/drivers/staging/speakup/fakekey.c
index 65b2311..1b34a87 100644
--- a/drivers/staging/speakup/fakekey.c
+++ b/drivers/staging/speakup/fakekey.c
@@ -78,10 +78,10 @@
 	/* don't change CPU */
 	preempt_disable();
 
-	__get_cpu_var(reporting_keystroke) = true;
+	__this_cpu_write(reporting_keystroke, true);
 	input_report_key(virt_keyboard, KEY_DOWN, PRESSED);
 	input_report_key(virt_keyboard, KEY_DOWN, RELEASED);
-	__get_cpu_var(reporting_keystroke) = false;
+	__this_cpu_write(reporting_keystroke, false);
 
 	/* reenable preemption */
 	preempt_enable();
@@ -95,10 +95,5 @@
 	 */
 bool speakup_fake_key_pressed(void)
 {
-	bool is_pressed;
-
-	is_pressed = get_cpu_var(reporting_keystroke);
-	put_cpu_var(reporting_keystroke);
-
-	return is_pressed;
+	return this_cpu_read(reporting_keystroke);
 }
diff --git a/drivers/staging/stradis/Kconfig b/drivers/staging/stradis/Kconfig
deleted file mode 100644
index 02f0fc5..0000000
--- a/drivers/staging/stradis/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config VIDEO_STRADIS
-        tristate "Stradis 4:2:2 MPEG-2 video driver (DEPRECATED)"
-        depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS && BKL
-        help
-          Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
-          driver for PCI.  There is a product page at
-          <http://www.stradis.com/>.
diff --git a/drivers/staging/stradis/Makefile b/drivers/staging/stradis/Makefile
deleted file mode 100644
index 0f1feab..0000000
--- a/drivers/staging/stradis/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
-
-EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/staging/stradis/TODO b/drivers/staging/stradis/TODO
deleted file mode 100644
index f48150f..0000000
--- a/drivers/staging/stradis/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-This is an obsolete driver for ancient stradis hardware.
-We couldn't find anyone with this hardware in order to port it to use V4L2.
-
-If nobody take care on it, the driver will be removed for 2.6.38.
-
-Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/staging/stradis/stradis.c b/drivers/staging/stradis/stradis.c
deleted file mode 100644
index 807dd7e..0000000
--- a/drivers/staging/stradis/stradis.c
+++ /dev/null
@@ -1,2222 +0,0 @@
-/*
- * stradis.c - stradis 4:2:2 mpeg decoder driver
- *
- * Stradis 4:2:2 MPEG-2 Decoder Driver
- * Copyright (C) 1999 Nathan Laredo <laredo@gnu.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 <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/pci.h>
-#include <linux/signal.h>
-#include <asm/io.h>
-#include <linux/ioport.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/sched.h>
-#include <asm/types.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <asm/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-#include "saa7146.h"
-#include "saa7146reg.h"
-#include "ibmmpeg2.h"
-#include "saa7121.h"
-#include "cs8420.h"
-
-#define DEBUG(x)		/* debug driver */
-#undef  IDEBUG			/* debug irq handler */
-#undef  MDEBUG			/* debug memory management */
-
-#define SAA7146_MAX 6
-
-static struct saa7146 saa7146s[SAA7146_MAX];
-
-static int saa_num;		/* number of SAA7146s in use */
-
-static int video_nr = -1;
-module_param(video_nr, int, 0);
-MODULE_LICENSE("GPL");
-
-#define nDebNormal	0x00480000
-#define nDebNoInc	0x00480000
-#define nDebVideo	0xd0480000
-#define nDebAudio	0xd0400000
-#define nDebDMA		0x02c80000
-
-#define oDebNormal	0x13c80000
-#define oDebNoInc	0x13c80000
-#define oDebVideo	0xd1080000
-#define oDebAudio	0xd1080000
-#define oDebDMA		0x03080000
-
-#define NewCard		(saa->boardcfg[3])
-#define ChipControl	(saa->boardcfg[1])
-#define NTSCFirstActive	(saa->boardcfg[4])
-#define PALFirstActive	(saa->boardcfg[5])
-#define NTSCLastActive	(saa->boardcfg[54])
-#define PALLastActive	(saa->boardcfg[55])
-#define Have2MB		(saa->boardcfg[18] & 0x40)
-#define HaveCS8420	(saa->boardcfg[18] & 0x04)
-#define IBMMPEGCD20	(saa->boardcfg[18] & 0x20)
-#define HaveCS3310	(saa->boardcfg[18] & 0x01)
-#define CS3310MaxLvl	((saa->boardcfg[30] << 8) | saa->boardcfg[31])
-#define HaveCS4341	(saa->boardcfg[40] == 2)
-#define SDIType		(saa->boardcfg[27])
-#define CurrentMode	(saa->boardcfg[2])
-
-#define debNormal	(NewCard ? nDebNormal : oDebNormal)
-#define debNoInc	(NewCard ? nDebNoInc : oDebNoInc)
-#define debVideo	(NewCard ? nDebVideo : oDebVideo)
-#define debAudio	(NewCard ? nDebAudio : oDebAudio)
-#define debDMA		(NewCard ? nDebDMA : oDebDMA)
-
-#ifdef USE_RESCUE_EEPROM_SDM275
-static unsigned char rescue_eeprom[64] = {
-	0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63,
-	0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f,  'd',  'e',  'c',  'x',  'l',
-	 'd',  'v',  'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2,
-	0x10, 0x00, 0x0a, 0x00, 0x02, 0x02,  'd',  'e',  'c',  'x',  'l',  'a',
-	0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-};
-#endif
-
-/* ----------------------------------------------------------------------- */
-/* Hardware I2C functions */
-static void I2CWipe(struct saa7146 *saa)
-{
-	int i;
-	/* set i2c to ~=100kHz, abort transfer, clear busy */
-	saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS);
-	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
-		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
-	/* wait for i2c registers to be programmed */
-	for (i = 0; i < 1000 &&
-	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
-		schedule();
-	saawrite(0x600, SAA7146_I2C_STATUS);
-	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
-		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
-	/* wait for i2c registers to be programmed */
-	for (i = 0; i < 1000 &&
-	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
-		schedule();
-	saawrite(0x600, SAA7146_I2C_STATUS);
-	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
-		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
-	/* wait for i2c registers to be programmed */
-	for (i = 0; i < 1000 &&
-	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
-		schedule();
-}
-
-/* read I2C */
-static int I2CRead(struct saa7146 *saa, unsigned char addr,
-		   unsigned char subaddr, int dosub)
-{
-	int i;
-
-	if (saaread(SAA7146_I2C_STATUS) & 0x3c)
-		I2CWipe(saa);
-	for (i = 0;
-		i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY);
-		i++)
-		schedule();
-	if (i == 1000)
-		I2CWipe(saa);
-	if (dosub)
-		saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
-			((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
-	else
-		saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
-			0xf1, SAA7146_I2C_TRANSFER);
-	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
-		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
-	/* wait for i2c registers to be programmed */
-	for (i = 0; i < 1000 &&
-	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
-		schedule();
-	/* wait for valid data */
-	for (i = 0; i < 1000 &&
-	     (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
-		schedule();
-	if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
-		return -1;
-	if (i == 1000)
-		printk("i2c setup read timeout\n");
-	saawrite(0x41, SAA7146_I2C_TRANSFER);
-	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
-		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
-	/* wait for i2c registers to be programmed */
-	for (i = 0; i < 1000 &&
-	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
-		schedule();
-	/* wait for valid data */
-	for (i = 0; i < 1000 &&
-	     (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++)
-		schedule();
-	if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
-		return -1;
-	if (i == 1000)
-		printk("i2c read timeout\n");
-	return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
-}
-
-/* set both to write both bytes, reset it to write only b1 */
-
-static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1,
-		    unsigned char b2, int both)
-{
-	int i;
-	u32 data;
-
-	if (saaread(SAA7146_I2C_STATUS) & 0x3c)
-		I2CWipe(saa);
-	for (i = 0; i < 1000 &&
-	     (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
-		schedule();
-	if (i == 1000)
-		I2CWipe(saa);
-	data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16);
-	if (both)
-		data |= ((b2 & 0xff) << 8) | 0xe5;
-	else
-		data |= 0xd1;
-	saawrite(data, SAA7146_I2C_TRANSFER);
-	saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C,
-		 SAA7146_MC2);
-	return 0;
-}
-
-static void attach_inform(struct saa7146 *saa, int id)
-{
-	int i;
-
-	DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr,
-		id));
-	if (id == 0xa0) {	/* we have rev2 or later board, fill in info */
-		for (i = 0; i < 64; i++)
-			saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
-#ifdef USE_RESCUE_EEPROM_SDM275
-		if (saa->boardcfg[0] != 0) {
-			printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE "
-				"BEEN IGNORED\n", saa->nr);
-			for (i = 0; i < 64; i++)
-				saa->boardcfg[i] = rescue_eeprom[i];
-		}
-#endif
-		printk("stradis%d: config =", saa->nr);
-		for (i = 0; i < 51; i++) {
-			printk(" %02x", saa->boardcfg[i]);
-		}
-		printk("\n");
-	}
-}
-
-static void I2CBusScan(struct saa7146 *saa)
-{
-	int i;
-	for (i = 0; i < 0xff; i += 2)
-		if ((I2CRead(saa, i, 0, 0)) >= 0)
-			attach_inform(saa, i);
-}
-
-static int debiwait_maxwait;
-
-static int wait_for_debi_done(struct saa7146 *saa)
-{
-	int i;
-
-	/* wait for registers to be programmed */
-	for (i = 0; i < 100000 &&
-	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++)
-		saaread(SAA7146_MC2);
-	/* wait for transfer to complete */
-	for (i = 0; i < 500000 &&
-	     (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
-		saaread(SAA7146_MC2);
-
-	if (i > debiwait_maxwait)
-		printk("wait-for-debi-done maxwait: %d\n",
-			debiwait_maxwait = i);
-
-	if (i == 500000)
-		return -1;
-
-	return 0;
-}
-
-static int debiwrite(struct saa7146 *saa, u32 config, int addr,
-	u32 val, int count)
-{
-	u32 cmd;
-	if (count <= 0 || count > 32764)
-		return -1;
-	if (wait_for_debi_done(saa) < 0)
-		return -1;
-	saawrite(config, SAA7146_DEBI_CONFIG);
-	if (count <= 4)		/* immediate transfer */
-		saawrite(val, SAA7146_DEBI_AD);
-	else			/* block transfer */
-		saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
-	saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND);
-	saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
-		 SAA7146_MC2);
-	return 0;
-}
-
-static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
-{
-	u32 result = 0;
-
-	if (count > 32764 || count <= 0)
-		return 0;
-	if (wait_for_debi_done(saa) < 0)
-		return 0;
-	saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
-	saawrite((count << 17) | 0x10000 | (addr & 0xffff),
-		 SAA7146_DEBI_COMMAND);
-	saawrite(config, SAA7146_DEBI_CONFIG);
-	saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
-		 SAA7146_MC2);
-	if (count > 4)		/* not an immediate transfer */
-		return count;
-	wait_for_debi_done(saa);
-	result = saaread(SAA7146_DEBI_AD);
-	if (count == 1)
-		result &= 0xff;
-	if (count == 2)
-		result &= 0xffff;
-	if (count == 3)
-		result &= 0xffffff;
-	return result;
-}
-
-static void do_irq_send_data(struct saa7146 *saa)
-{
-	int split, audbytes, vidbytes;
-
-	saawrite(SAA7146_PSR_PIN1, SAA7146_IER);
-	/* if special feature mode in effect, disable audio sending */
-	if (saa->playmode != VID_PLAY_NORMAL)
-		saa->audtail = saa->audhead = 0;
-	if (saa->audhead <= saa->audtail)
-		audbytes = saa->audtail - saa->audhead;
-	else
-		audbytes = 65536 - (saa->audhead - saa->audtail);
-	if (saa->vidhead <= saa->vidtail)
-		vidbytes = saa->vidtail - saa->vidhead;
-	else
-		vidbytes = 524288 - (saa->vidhead - saa->vidtail);
-	if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) {
-		saawrite(0, SAA7146_IER);
-		return;
-	}
-	/* if at least 1 block audio waiting and audio fifo isn't full */
-	if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2)
-			& 0xff) < 60) {
-		if (saa->audhead > saa->audtail)
-			split = 65536 - saa->audhead;
-		else
-			split = 0;
-		audbytes = 2048;
-		if (split > 0 && split < 2048) {
-			memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split);
-			saa->audhead = 0;
-			audbytes -= split;
-		} else
-			split = 0;
-		memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead,
-			audbytes);
-		saa->audhead += audbytes;
-		saa->audhead &= 0xffff;
-		debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO :
-			IBM_MP2_AUD_FIFOW), 0, 2048);
-		wake_up_interruptible(&saa->audq);
-		/* if at least 1 block video waiting and video fifo isn't full */
-	} else if (vidbytes >= 30720 && (debiread(saa, debNormal,
-						  IBM_MP2_FIFO, 2)) < 16384) {
-		if (saa->vidhead > saa->vidtail)
-			split = 524288 - saa->vidhead;
-		else
-			split = 0;
-		vidbytes = 30720;
-		if (split > 0 && split < 30720) {
-			memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split);
-			saa->vidhead = 0;
-			vidbytes -= split;
-		} else
-			split = 0;
-		memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead,
-			vidbytes);
-		saa->vidhead += vidbytes;
-		saa->vidhead &= 0x7ffff;
-		debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
-					  IBM_MP2_FIFOW), 0, 30720);
-		wake_up_interruptible(&saa->vidq);
-	}
-	saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
-}
-
-static void send_osd_data(struct saa7146 *saa)
-{
-	int size = saa->osdtail - saa->osdhead;
-	if (size > 30720)
-		size = 30720;
-	/* ensure some multiple of 8 bytes is transferred */
-	size = 8 * ((size + 8) >> 3);
-	if (size) {
-		debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
-			  (saa->osdhead >> 3), 2);
-		memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
-		saa->osdhead += size;
-		/* block transfer of next 8 bytes to ~32k bytes */
-		debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size);
-	}
-	if (saa->osdhead >= saa->osdtail) {
-		saa->osdhead = saa->osdtail = 0;
-		debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
-	}
-}
-
-static irqreturn_t saa7146_irq(int irq, void *dev_id)
-{
-	struct saa7146 *saa = dev_id;
-	u32 stat, astat;
-	int count;
-	int handled = 0;
-
-	count = 0;
-	while (1) {
-		/* get/clear interrupt status bits */
-		stat = saaread(SAA7146_ISR);
-		astat = stat & saaread(SAA7146_IER);
-		if (!astat)
-			break;
-		handled = 1;
-		saawrite(astat, SAA7146_ISR);
-		if (astat & SAA7146_PSR_DEBI_S) {
-			do_irq_send_data(saa);
-		}
-		if (astat & SAA7146_PSR_PIN1) {
-			int istat;
-			/* the following read will trigger DEBI_S */
-			istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
-			if (istat & 1) {
-				saawrite(0, SAA7146_IER);
-				send_osd_data(saa);
-				saawrite(SAA7146_PSR_DEBI_S |
-					 SAA7146_PSR_PIN1, SAA7146_IER);
-			}
-			if (istat & 0x20) {	/* Video Start */
-				saa->vidinfo.frame_count++;
-			}
-			if (istat & 0x400) {	/* Picture Start */
-				/* update temporal reference */
-			}
-			if (istat & 0x200) {	/* Picture Resolution Change */
-				/* read new resolution */
-			}
-			if (istat & 0x100) {	/* New User Data found */
-				/* read new user data */
-			}
-			if (istat & 0x1000) {	/* new GOP/SMPTE */
-				/* read new SMPTE */
-			}
-			if (istat & 0x8000) {	/* Sequence Start Code */
-				/* reset frame counter, load sizes */
-				saa->vidinfo.frame_count = 0;
-				saa->vidinfo.h_size = 704;
-				saa->vidinfo.v_size = 480;
-#if 0
-				if (saa->endmarkhead != saa->endmarktail) {
-					saa->audhead =
-						saa->endmark[saa->endmarkhead];
-					saa->endmarkhead++;
-					if (saa->endmarkhead >= MAX_MARKS)
-						saa->endmarkhead = 0;
-				}
-#endif
-			}
-			if (istat & 0x4000) {	/* Sequence Error Code */
-				if (saa->endmarkhead != saa->endmarktail) {
-					saa->audhead =
-						saa->endmark[saa->endmarkhead];
-					saa->endmarkhead++;
-					if (saa->endmarkhead >= MAX_MARKS)
-						saa->endmarkhead = 0;
-				}
-			}
-		}
-#ifdef IDEBUG
-		if (astat & SAA7146_PSR_PPEF) {
-			IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_PABO) {
-			IDEBUG(printk("stradis%d irq: PABO\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_PPED) {
-			IDEBUG(printk("stradis%d irq: PPED\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_I1) {
-			IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_I0) {
-			IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_LATE1) {
-			IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_LATE0) {
-			IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_E1) {
-			IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_E0) {
-			IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_TO1) {
-			IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_RPS_TO0) {
-			IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_UPLD) {
-			IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_DEBI_E) {
-			IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_I2C_S) {
-			IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_I2C_E) {
-			IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_A2_IN) {
-			IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_A2_OUT) {
-			IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_A1_IN) {
-			IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_A1_OUT) {
-			IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_AFOU) {
-			IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_V_PE) {
-			IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_VFOU) {
-			IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_FIDA) {
-			IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_FIDB) {
-			IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_PIN3) {
-			IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_PIN2) {
-			IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_PIN0) {
-			IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_ECS) {
-			IDEBUG(printk("stradis%d irq: ECS\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_EC3S) {
-			IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr));
-		}
-		if (astat & SAA7146_PSR_EC0S) {
-			IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr));
-		}
-#endif
-		count++;
-		if (count > 15)
-			printk(KERN_WARNING "stradis%d: irq loop %d\n",
-			       saa->nr, count);
-		if (count > 20) {
-			saawrite(0, SAA7146_IER);
-			printk(KERN_ERR
-			       "stradis%d: IRQ loop cleared\n", saa->nr);
-		}
-	}
-	return IRQ_RETVAL(handled);
-}
-
-static int ibm_send_command(struct saa7146 *saa,
-			    int command, int data, int chain)
-{
-	int i;
-
-	if (chain)
-		debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2);
-	else
-		debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
-	debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
-	debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2);
-	for (i = 0; i < 100 &&
-	     (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++)
-		schedule();
-	if (i == 100)
-		return -1;
-	return 0;
-}
-
-static void cs4341_setlevel(struct saa7146 *saa, int left, int right)
-{
-	I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2);
-	I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2);
-}
-
-static void initialize_cs4341(struct saa7146 *saa)
-{
-	int i;
-	for (i = 0; i < 200; i++) {
-		/* auto mute off, power on, no de-emphasis */
-		/* I2S data up to 24-bit 64xFs internal SCLK */
-		I2CWrite(saa, 0x22, 0x01, 0x11, 2);
-		/* ATAPI mixer settings */
-		I2CWrite(saa, 0x22, 0x02, 0x49, 2);
-		/* attenuation left 3db */
-		I2CWrite(saa, 0x22, 0x03, 0x00, 2);
-		/* attenuation right 3db */
-		I2CWrite(saa, 0x22, 0x04, 0x00, 2);
-		I2CWrite(saa, 0x22, 0x01, 0x10, 2);
-		if (I2CRead(saa, 0x22, 0x02, 1) == 0x49)
-			break;
-		schedule();
-	}
-	printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i);
-	return;
-}
-
-static void initialize_cs8420(struct saa7146 *saa, int pro)
-{
-	int i;
-	u8 *sequence;
-	if (pro)
-		sequence = mode8420pro;
-	else
-		sequence = mode8420con;
-	for (i = 0; i < INIT8420LEN; i++)
-		I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2);
-	for (i = 0; i < MODE8420LEN; i++)
-		I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2);
-	printk("stradis%d: CS8420 initialized\n", saa->nr);
-}
-
-static void initialize_saa7121(struct saa7146 *saa, int dopal)
-{
-	int i, mod;
-	u8 *sequence;
-	if (dopal)
-		sequence = init7121pal;
-	else
-		sequence = init7121ntsc;
-	mod = saaread(SAA7146_PSR) & 0x08;
-	/* initialize PAL/NTSC video encoder */
-	for (i = 0; i < INIT7121LEN; i++) {
-		if (NewCard) {	/* handle new card encoder differences */
-			if (sequence[i * 2] == 0x3a)
-				I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
-			else if (sequence[i * 2] == 0x6b)
-				I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
-			else if (sequence[i * 2] == 0x6c)
-				I2CWrite(saa, 0x88, 0x6c,
-					 dopal ? 0x09 : 0xf5, 2);
-			else if (sequence[i * 2] == 0x6d)
-				I2CWrite(saa, 0x88, 0x6d,
-					 dopal ? 0x20 : 0x00, 2);
-			else if (sequence[i * 2] == 0x7a)
-				I2CWrite(saa, 0x88, 0x7a,
-					 dopal ? (PALFirstActive - 1) :
-					 (NTSCFirstActive - 4), 2);
-			else if (sequence[i * 2] == 0x7b)
-				I2CWrite(saa, 0x88, 0x7b,
-					 dopal ? PALLastActive :
-					 NTSCLastActive, 2);
-			else
-				I2CWrite(saa, 0x88, sequence[i * 2],
-					 sequence[i * 2 + 1], 2);
-		} else {
-			if (sequence[i * 2] == 0x6b && mod)
-				I2CWrite(saa, 0x88, 0x6b,
-					 (sequence[i * 2 + 1] ^ 0x09), 2);
-			else if (sequence[i * 2] == 0x7a)
-				I2CWrite(saa, 0x88, 0x7a,
-					 dopal ? (PALFirstActive - 1) :
-					 (NTSCFirstActive - 4), 2);
-			else if (sequence[i * 2] == 0x7b)
-				I2CWrite(saa, 0x88, 0x7b,
-					 dopal ? PALLastActive :
-					 NTSCLastActive, 2);
-			else
-				I2CWrite(saa, 0x88, sequence[i * 2],
-					 sequence[i * 2 + 1], 2);
-		}
-	}
-}
-
-static void set_genlock_offset(struct saa7146 *saa, int noffset)
-{
-	int nCode;
-	int PixelsPerLine = 858;
-	if (CurrentMode == VIDEO_MODE_PAL)
-		PixelsPerLine = 864;
-	if (noffset > 500)
-		noffset = 500;
-	else if (noffset < -500)
-		noffset = -500;
-	nCode = noffset + 0x100;
-	if (nCode == 1)
-		nCode = 0x401;
-	else if (nCode < 1)
-		nCode = 0x400 + PixelsPerLine + nCode;
-	debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
-}
-
-static void set_out_format(struct saa7146 *saa, int mode)
-{
-	initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1));
-	saa->boardcfg[2] = mode;
-	/* do not adjust analog video parameters here, use saa7121 init */
-	/* you will affect the SDI output on the new card */
-	if (mode == VIDEO_MODE_PAL) {	/* PAL */
-		debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
-		mdelay(50);
-		saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
-		if (NewCard) {
-			debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2);
-			mdelay(50);
-		}
-		debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
-			  NewCard ? 0xe500 : 0x6500, 2);
-		debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
-			  (1 << 8) |
-			  (NewCard ? PALFirstActive : PALFirstActive - 6), 2);
-	} else {		/* NTSC */
-		debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
-		mdelay(50);
-		saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
-		debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
-			  NewCard ? 0xe100 : 0x6100, 2);
-		debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
-			  (1 << 8) |
-			  (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2);
-	}
-}
-
-/* Intialize bitmangler to map from a byte value to the mangled word that
- * must be output to program the Xilinx part through the DEBI port.
- * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
- * transfer FPGA code, init IBM chip, transfer IBM microcode
- * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0
- */
-static u16 bitmangler[256];
-
-static int initialize_fpga(struct video_code *bitdata)
-{
-	int i, num, startindex, failure = 0, loadtwo, loadfile = 0;
-	u16 *dmabuf;
-	u8 *newdma;
-	struct saa7146 *saa;
-
-	/* verify fpga code */
-	for (startindex = 0; startindex < bitdata->datasize; startindex++)
-		if (bitdata->data[startindex] == 255)
-			break;
-	if (startindex == bitdata->datasize) {
-		printk(KERN_INFO "stradis: bad fpga code\n");
-		return -1;
-	}
-	/* initialize all detected cards */
-	for (num = 0; num < saa_num; num++) {
-		saa = &saa7146s[num];
-		if (saa->boardcfg[0] > 20)
-			continue;	/* card was programmed */
-		loadtwo = (saa->boardcfg[18] & 0x10);
-		if (!NewCard)	/* we have an old board */
-			for (i = 0; i < 256; i++)
-				bitmangler[i] = ((i & 0x01) << 15) |
-					((i & 0x02) << 6) | ((i & 0x04) << 4) |
-					((i & 0x08) << 9) | ((i & 0x10) << 7) |
-					((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
-					((i & 0x80) >> 7);
-		else		/* else we have a new board */
-			for (i = 0; i < 256; i++)
-				bitmangler[i] = ((i & 0x01) << 7) |
-					((i & 0x02) << 5) | ((i & 0x04) << 3) |
-					((i & 0x08) << 1) | ((i & 0x10) >> 1) |
-					((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
-					((i & 0x80) >> 7);
-
-		dmabuf = (u16 *) saa->dmadebi;
-		newdma = (u8 *) saa->dmadebi;
-		if (NewCard) {	/* SDM2xxx */
-			if (!strncmp(bitdata->loadwhat, "decoder2", 8))
-				continue;	/* fpga not for this card */
-			if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8))
-				loadfile = 1;
-			else if (loadtwo && !strncmp(&saa->boardcfg[19],
-				       bitdata->loadwhat, 8))
-				loadfile = 2;
-			else if (!saa->boardcfg[42] && !strncmp("decxl",
-					bitdata->loadwhat, 8))
-				loadfile = 1;	/* special */
-			else
-				continue;	/* fpga not for this card */
-			if (loadfile != 1 && loadfile != 2)
-				continue;	/* skip to next card */
-			if (saa->boardcfg[0] && loadfile == 1)
-				continue;	/* skip to next card */
-			if (saa->boardcfg[0] != 1 && loadfile == 2)
-				continue;	/* skip to next card */
-			saa->boardcfg[0]++;	/* mark fpga handled */
-			printk("stradis%d: loading %s\n", saa->nr,
-				bitdata->loadwhat);
-			if (loadtwo && loadfile == 2)
-				goto send_fpga_stuff;
-			/* turn on the Audio interface to set PROG low */
-			saawrite(0x00400040, SAA7146_GPIO_CTRL);
-			saaread(SAA7146_PSR);	/* ensure posted write */
-			/* wait for everyone to reset */
-			mdelay(10);
-			saawrite(0x00400000, SAA7146_GPIO_CTRL);
-		} else {	/* original card */
-			if (strncmp(bitdata->loadwhat, "decoder2", 8))
-				continue;	/* fpga not for this card */
-			/* Pull the Xilinx PROG signal WS3 low */
-			saawrite(0x02000200, SAA7146_MC1);
-			/* Turn on the Audio interface so can set PROG low */
-			saawrite(0x000000c0, SAA7146_ACON1);
-			/* Pull the Xilinx INIT signal (GPIO2) low */
-			saawrite(0x00400000, SAA7146_GPIO_CTRL);
-			/* Make sure everybody resets */
-			saaread(SAA7146_PSR);	/* ensure posted write */
-			mdelay(10);
-			/* Release the Xilinx PROG signal */
-			saawrite(0x00000000, SAA7146_ACON1);
-			/* Turn off the Audio interface */
-			saawrite(0x02000000, SAA7146_MC1);
-		}
-		/* Release Xilinx INIT signal (WS2) */
-		saawrite(0x00000000, SAA7146_GPIO_CTRL);
-		/* Wait for the INIT to go High */
-		for (i = 0;
-			i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
-			i++)
-			schedule();
-		if (i == 1000) {
-			printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
-			return -1;
-		}
-send_fpga_stuff:
-		if (NewCard) {
-			for (i = startindex; i < bitdata->datasize; i++)
-				newdma[i - startindex] =
-				    bitmangler[bitdata->data[i]];
-			debiwrite(saa, 0x01420000, 0, 0,
-				((bitdata->datasize - startindex) + 5));
-			if (loadtwo && loadfile == 1) {
-				printk("stradis%d: awaiting 2nd FPGA bitfile\n",
-				       saa->nr);
-				continue;	/* skip to next card */
-			}
-		} else {
-			for (i = startindex; i < bitdata->datasize; i++)
-				dmabuf[i - startindex] =
-					bitmangler[bitdata->data[i]];
-			debiwrite(saa, 0x014a0000, 0, 0,
-				((bitdata->datasize - startindex) + 5) * 2);
-		}
-		for (i = 0;
-			i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
-			i++)
-			schedule();
-		if (i == 1000) {
-			printk(KERN_INFO "stradis%d: FPGA load failed\n",
-			       saa->nr);
-			failure++;
-			continue;
-		}
-		if (!NewCard) {
-			/* Pull the Xilinx INIT signal (GPIO2) low */
-			saawrite(0x00400000, SAA7146_GPIO_CTRL);
-			saaread(SAA7146_PSR);	/* ensure posted write */
-			mdelay(2);
-			saawrite(0x00000000, SAA7146_GPIO_CTRL);
-			mdelay(2);
-		}
-		printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr);
-		saa->boardcfg[0] = 26;	/* mark fpga programmed */
-		/* set VXCO to its lowest frequency */
-		debiwrite(saa, debNormal, XILINX_PWM, 0, 2);
-		if (NewCard) {
-			/* mute CS3310 */
-			if (HaveCS3310)
-				debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
-					0, 2);
-			/* set VXCO to PWM mode, release reset, blank on */
-			debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
-			mdelay(10);
-			/* unmute CS3310 */
-			if (HaveCS3310)
-				debiwrite(saa, debNormal, XILINX_CTL0,
-					0x2020, 2);
-		}
-		/* set source Black */
-		debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
-		saa->boardcfg[4] = 22;	/* set NTSC First Active Line */
-		saa->boardcfg[5] = 23;	/* set PAL First Active Line */
-		saa->boardcfg[54] = 2;	/* set NTSC Last Active Line - 256 */
-		saa->boardcfg[55] = 54;	/* set PAL Last Active Line - 256 */
-		set_out_format(saa, VIDEO_MODE_NTSC);
-		mdelay(50);
-		/* begin IBM chip init */
-		debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
-		saaread(SAA7146_PSR);	/* wait for reset */
-		mdelay(5);
-		debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
-		debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
-		debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2);
-		debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2);
-		debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
-		if (NewCard) {
-			mdelay(5);
-			/* set i2s rate converter to 48KHz */
-			debiwrite(saa, debNormal, 0x80c0, 6, 2);
-			/* we must init CS8420 first since rev b pulls i2s */
-			/* master clock low and CS4341 needs i2s master to */
-			/* run the i2c port. */
-			if (HaveCS8420)
-				/* 0=consumer, 1=pro */
-				initialize_cs8420(saa, 0);
-
-			mdelay(5);
-			if (HaveCS4341)
-				initialize_cs4341(saa);
-		}
-		debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
-		debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
-		debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
-		debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
-		if (NewCard)
-			set_genlock_offset(saa, 0);
-		debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
-#if 0
-		/* enable genlock */
-		debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2);
-#else
-		/* disable genlock */
-		debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
-#endif
-	}
-
-	return failure;
-}
-
-static int do_ibm_reset(struct saa7146 *saa)
-{
-	/* failure if decoder not previously programmed */
-	if (saa->boardcfg[0] < 37)
-		return -EIO;
-	/* mute CS3310 */
-	if (HaveCS3310)
-		debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2);
-	/* disable interrupts */
-	saawrite(0, SAA7146_IER);
-	saa->audhead = saa->audtail = 0;
-	saa->vidhead = saa->vidtail = 0;
-	/* tristate debi bus, disable debi transfers */
-	saawrite(0x00880000, SAA7146_MC1);
-	/* ensure posted write */
-	saaread(SAA7146_MC1);
-	mdelay(50);
-	/* re-enable debi transfers */
-	saawrite(0x00880088, SAA7146_MC1);
-	/* set source Black */
-	debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
-	/* begin IBM chip init */
-	set_out_format(saa, CurrentMode);
-	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
-	saaread(SAA7146_PSR);	/* wait for reset */
-	mdelay(5);
-	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
-	debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
-	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
-	debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
-	if (NewCard) {
-		mdelay(5);
-		/* set i2s rate converter to 48KHz */
-		debiwrite(saa, debNormal, 0x80c0, 6, 2);
-		/* we must init CS8420 first since rev b pulls i2s */
-		/* master clock low and CS4341 needs i2s master to */
-		/* run the i2c port. */
-		if (HaveCS8420)
-			/* 0=consumer, 1=pro */
-			initialize_cs8420(saa, 1);
-
-		mdelay(5);
-		if (HaveCS4341)
-			initialize_cs4341(saa);
-	}
-	debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
-	debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
-	debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
-	debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
-	if (NewCard)
-		set_genlock_offset(saa, 0);
-	debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
-	debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
-	debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
-	if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
-			(ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
-		printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
-	}
-	if (HaveCS3310) {
-		int i = CS3310MaxLvl;
-		debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2);
-	}
-	/* start video decoder */
-	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
-	/* 256k vid, 3520 bytes aud */
-	debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2);
-	debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
-	ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
-	/* enable buffer threshold irq */
-	debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
-	/* clear pending interrupts */
-	debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
-	debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
-
-	return 0;
-}
-
-/* load the decoder microcode */
-static int initialize_ibmmpeg2(struct video_code *microcode)
-{
-	int i, num;
-	struct saa7146 *saa;
-
-	for (num = 0; num < saa_num; num++) {
-		saa = &saa7146s[num];
-		/* check that FPGA is loaded */
-		debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
-		i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2);
-		if (i != 0xa55a) {
-			printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
-				saa->nr, i);
-#if 0
-			return -1;
-#endif
-		}
-		if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) {
-			if (saa->boardcfg[0] > 27)
-				continue;	/* skip to next card */
-			/* load video control store */
-			saa->boardcfg[1] = 0x13;	/* no-sync default */
-			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
-			debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
-			for (i = 0; i < microcode->datasize / 2; i++)
-				debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
-					(microcode->data[i * 2] << 8) |
-					microcode->data[i * 2 + 1], 2);
-			debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
-			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
-			debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
-				ChipControl, 2);
-			saa->boardcfg[0] = 28;
-		}
-		if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
-			if (saa->boardcfg[0] > 35)
-				continue;	/* skip to next card */
-			/* load audio control store */
-			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
-			debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
-			for (i = 0; i < microcode->datasize; i++)
-				debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA,
-					microcode->data[i], 1);
-			debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
-			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
-			debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
-			debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
-			if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
-					0xe000, 1)) {
-				printk(KERN_ERR "stradis%d: IBM config "
-					"failed\n", saa->nr);
-				return -1;
-			}
-			/* set PWM to center value */
-			if (NewCard) {
-				debiwrite(saa, debNormal, XILINX_PWM,
-					saa->boardcfg[14] +
-					(saa->boardcfg[13] << 8), 2);
-			} else
-				debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2);
-
-			if (HaveCS3310) {
-				i = CS3310MaxLvl;
-				debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
-					(i << 8) | i, 2);
-			}
-			printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n",
-				saa->nr, 18 + (debiread(saa, debNormal,
-				IBM_MP2_CHIP_CONTROL, 2) >> 12));
-			/* start video decoder */
-			debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
-				ChipControl, 2);
-			debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037,
-				2);	/* 256k vid, 3520 bytes aud */
-			debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
-			ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
-			/* enable buffer threshold irq */
-			debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
-			debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
-			/* enable gpio irq */
-			saawrite(0x00002000, SAA7146_GPIO_CTRL);
-			/* enable decoder output to HPS */
-			debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
-			saa->boardcfg[0] = 37;
-		}
-	}
-
-	return 0;
-}
-
-static u32 palette2fmt[] = {	/* some of these YUV translations are wrong */
-	0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
-	0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
-	0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
-};
-static int bpp2fmt[4] = {
-	VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
-	VIDEO_PALETTE_RGB32
-};
-
-/* I wish I could find a formula to calculate these... */
-static u32 h_prescale[64] = {
-	0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
-	0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
-	0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
-	0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
-	0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
-	0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
-	0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
-	0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
-	0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
-	0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
-	0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
-};
-static u32 v_gain[64] = {
-	0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
-	0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
-	0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-	0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
-};
-
-static void saa7146_set_winsize(struct saa7146 *saa)
-{
-	u32 format;
-	int offset, yacl, ysci;
-	saa->win.color_fmt = format =
-	    (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] :
-	    palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]];
-	offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl;
-	saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1);
-	saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1);
-	saawrite(saa->win.bpl * 2, SAA7146_PITCH1);
-	saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
-		 SAA7146_PROT_ADDR1);
-	saawrite(0, SAA7146_PAGE1);
-	saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL);
-	offset = (704 / (saa->win.width - 1)) & 0x3f;
-	saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
-	offset = (720896 / saa->win.width) / (offset + 1);
-	saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE);
-	if (CurrentMode == VIDEO_MODE_NTSC) {
-		yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0;
-		ysci = 1024 - (saa->win.height * 1024 / 480);
-	} else {
-		yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0;
-		ysci = 1024 - (saa->win.height * 1024 / 576);
-	}
-	saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE);
-	saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
-	saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
-		SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
-		SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2);
-}
-
-/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
- * bitmap is fixed width, 128 bytes (1024 pixels represented)
- * arranged most-sigificant-bit-left in 32-bit words
- * based on saa7146 clipping hardware, it swaps bytes if LE
- * much of this makes up for egcs brain damage -- so if you
- * are wondering "why did he do this?" it is because the C
- * was adjusted to generate the optimal asm output without
- * writing non-portable __asm__ directives.
- */
-
-static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
-{
-	register int startword, endword;
-	register u32 bitsleft, bitsright;
-	u32 *temp;
-	if (x < 0) {
-		w += x;
-		x = 0;
-	}
-	if (y < 0) {
-		h += y;
-		y = 0;
-	}
-	if (w <= 0 || h <= 0 || x > 1023 || y > 639)
-		return;		/* throw away bad clips */
-	if (x + w > 1024)
-		w = 1024 - x;
-	if (y + h > 640)
-		h = 640 - y;
-	startword = (x >> 5);
-	endword = ((x + w) >> 5);
-	bitsleft = (0xffffffff >> (x & 31));
-	bitsright = (0xffffffff << (~((x + w) - (endword << 5))));
-	temp = &clipmap[(y << 5) + startword];
-	w = endword - startword;
-	if (!w) {
-		bitsleft |= bitsright;
-		for (y = 0; y < h; y++) {
-			*temp |= bitsleft;
-			temp += 32;
-		}
-	} else {
-		for (y = 0; y < h; y++) {
-			*temp++ |= bitsleft;
-			for (x = 1; x < w; x++)
-				*temp++ = 0xffffffff;
-			*temp |= bitsright;
-			temp += (32 - w);
-		}
-	}
-}
-
-static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
-{
-	int i, width, height;
-	u32 *clipmap;
-
-	clipmap = saa->dmavid2;
-	if ((width = saa->win.width) > 1023)
-		width = 1023;	/* sanity check */
-	if ((height = saa->win.height) > 640)
-		height = 639;	/* sanity check */
-	if (ncr > 0) {		/* rectangles pased */
-		/* convert rectangular clips to a bitmap */
-		memset(clipmap, 0, VIDEO_CLIPMAP_SIZE);	/* clear map */
-		for (i = 0; i < ncr; i++)
-			clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
-				cr[i].width, cr[i].height);
-	}
-	/* clip against viewing window AND screen
-	   so we do not have to rely on the user program
-	 */
-	clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
-		(saa->win.swidth - saa->win.x) : width, 0, 1024, 768);
-	clip_draw_rectangle(clipmap, 0,
-		(saa->win.y + height > saa->win.sheight) ?
-		(saa->win.sheight - saa->win.y) : height, 1024, 768);
-	if (saa->win.x < 0)
-		clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768);
-	if (saa->win.y < 0)
-		clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
-}
-
-static long saa_ioctl(struct file *file,
-		     unsigned int cmd, unsigned long argl)
-{
-	struct saa7146 *saa = file->private_data;
-	void __user *arg = (void __user *)argl;
-
-	switch (cmd) {
-	case VIDIOCGCAP:
-		{
-			struct video_capability b;
-			memset(&b, 0, sizeof(b));
-			strcpy(b.name, saa->video_dev.name);
-			b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
-				VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
-				VID_TYPE_SCALES;
-			b.channels = 1;
-			b.audios = 1;
-			b.maxwidth = 768;
-			b.maxheight = 576;
-			b.minwidth = 32;
-			b.minheight = 32;
-			if (copy_to_user(arg, &b, sizeof(b)))
-				return -EFAULT;
-			return 0;
-		}
-	case VIDIOCGPICT:
-		{
-			struct video_picture p = saa->picture;
-			if (saa->win.depth == 8)
-				p.palette = VIDEO_PALETTE_HI240;
-			if (saa->win.depth == 15)
-				p.palette = VIDEO_PALETTE_RGB555;
-			if (saa->win.depth == 16)
-				p.palette = VIDEO_PALETTE_RGB565;
-			if (saa->win.depth == 24)
-				p.palette = VIDEO_PALETTE_RGB24;
-			if (saa->win.depth == 32)
-				p.palette = VIDEO_PALETTE_RGB32;
-			if (copy_to_user(arg, &p, sizeof(p)))
-				return -EFAULT;
-			return 0;
-		}
-	case VIDIOCSPICT:
-		{
-			struct video_picture p;
-			u32 format;
-			if (copy_from_user(&p, arg, sizeof(p)))
-				return -EFAULT;
-			if (p.palette < ARRAY_SIZE(palette2fmt)) {
-				format = palette2fmt[p.palette];
-				saa->win.color_fmt = format;
-				saawrite(format | 0x60,
-					SAA7146_CLIP_FORMAT_CTRL);
-			}
-			saawrite(((p.brightness & 0xff00) << 16) |
-				((p.contrast & 0xfe00) << 7) |
-				((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
-			saa->picture = p;
-			/* upload changed registers */
-			saawrite(((SAA7146_MC2_UPLD_HPS_H |
-				SAA7146_MC2_UPLD_HPS_V) << 16) |
-				SAA7146_MC2_UPLD_HPS_H |
-				SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2);
-			return 0;
-		}
-	case VIDIOCSWIN:
-		{
-			struct video_window vw;
-			struct video_clip *vcp = NULL;
-
-			if (copy_from_user(&vw, arg, sizeof(vw)))
-				return -EFAULT;
-
-			/* stop capture */
-			if (vw.flags || vw.width < 16 || vw.height < 16) {
-				saawrite((SAA7146_MC1_TR_E_1 << 16),
-					SAA7146_MC1);
-				return -EINVAL;
-			}
-			/* 32-bit align start and adjust width */
-			if (saa->win.bpp < 4) {
-				int i = vw.x;
-				vw.x = (vw.x + 3) & ~3;
-				i = vw.x - i;
-				vw.width -= i;
-			}
-			saa->win.x = vw.x;
-			saa->win.y = vw.y;
-			saa->win.width = vw.width;
-			if (saa->win.width > 768)
-				saa->win.width = 768;
-			saa->win.height = vw.height;
-			if (CurrentMode == VIDEO_MODE_NTSC) {
-				if (saa->win.height > 480)
-					saa->win.height = 480;
-			} else {
-				if (saa->win.height > 576)
-					saa->win.height = 576;
-			}
-
-			/* stop capture */
-			saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
-			saa7146_set_winsize(saa);
-
-			/*
-			 *    Do any clips.
-			 */
-			if (vw.clipcount < 0) {
-				if (copy_from_user(saa->dmavid2, vw.clips,
-						VIDEO_CLIPMAP_SIZE))
-					return -EFAULT;
-			} else if (vw.clipcount > 16384) {
-				return -EINVAL;
-			} else if (vw.clipcount > 0) {
-				vcp = vmalloc(sizeof(struct video_clip) *
-					vw.clipcount);
-				if (vcp == NULL)
-					return -ENOMEM;
-				if (copy_from_user(vcp, vw.clips,
-						sizeof(struct video_clip) *
-						vw.clipcount)) {
-					vfree(vcp);
-					return -EFAULT;
-				}
-			} else	/* nothing clipped */
-				memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
-
-			make_clip_tab(saa, vcp, vw.clipcount);
-			if (vw.clipcount > 0)
-				vfree(vcp);
-
-			/* start capture & clip dma if we have an address */
-			if ((saa->cap & 3) && saa->win.vidadr != 0)
-				saawrite(((SAA7146_MC1_TR_E_1 |
-					SAA7146_MC1_TR_E_2) << 16) | 0xffff,
-					SAA7146_MC1);
-			return 0;
-		}
-	case VIDIOCGWIN:
-		{
-			struct video_window vw;
-			memset(&vw, 0, sizeof(vw));
-			vw.x = saa->win.x;
-			vw.y = saa->win.y;
-			vw.width = saa->win.width;
-			vw.height = saa->win.height;
-			vw.chromakey = 0;
-			vw.flags = 0;
-			if (copy_to_user(arg, &vw, sizeof(vw)))
-				return -EFAULT;
-			return 0;
-		}
-	case VIDIOCCAPTURE:
-		{
-			int v;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if (v == 0) {
-				saa->cap &= ~1;
-				saawrite((SAA7146_MC1_TR_E_1 << 16),
-					SAA7146_MC1);
-			} else {
-				if (saa->win.vidadr == 0 || saa->win.width == 0
-						|| saa->win.height == 0)
-					return -EINVAL;
-				saa->cap |= 1;
-				saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
-					SAA7146_MC1);
-			}
-			return 0;
-		}
-	case VIDIOCGFBUF:
-		{
-			struct video_buffer v;
-			memset(&v, 0, sizeof(v));
-			v.base = (void *)saa->win.vidadr;
-			v.height = saa->win.sheight;
-			v.width = saa->win.swidth;
-			v.depth = saa->win.depth;
-			v.bytesperline = saa->win.bpl;
-			if (copy_to_user(arg, &v, sizeof(v)))
-				return -EFAULT;
-			return 0;
-
-		}
-	case VIDIOCSFBUF:
-		{
-			struct video_buffer v;
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
-			    v.depth != 24 && v.depth != 32 && v.width > 16 &&
-			    v.height > 16 && v.bytesperline > 16)
-				return -EINVAL;
-			if (v.base)
-				saa->win.vidadr = (unsigned long)v.base;
-			saa->win.sheight = v.height;
-			saa->win.swidth = v.width;
-			saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
-			saa->win.depth = v.depth;
-			saa->win.bpl = v.bytesperline;
-
-			DEBUG(printk("Display at %p is %d by %d, bytedepth %d, "
-					"bpl %d\n", v.base, v.width, v.height,
-					saa->win.bpp, saa->win.bpl));
-			saa7146_set_winsize(saa);
-			return 0;
-		}
-	case VIDIOCKEY:
-		{
-			/* Will be handled higher up .. */
-			return 0;
-		}
-
-	case VIDIOCGAUDIO:
-		{
-			struct video_audio v;
-			memset(&v, 0, sizeof(v));
-			v = saa->audio_dev;
-			v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
-			v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
-			strcpy(v.name, "MPEG");
-			v.mode = VIDEO_SOUND_STEREO;
-			if (copy_to_user(arg, &v, sizeof(v)))
-				return -EFAULT;
-			return 0;
-		}
-	case VIDIOCSAUDIO:
-		{
-			struct video_audio v;
-			int i;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			i = (~(v.volume >> 8)) & 0xff;
-			if (!HaveCS4341) {
-				if (v.flags & VIDEO_AUDIO_MUTE)
-					debiwrite(saa, debNormal,
-						IBM_MP2_FRNT_ATTEN, 0xffff, 2);
-				if (!(v.flags & VIDEO_AUDIO_MUTE))
-					debiwrite(saa, debNormal,
-						IBM_MP2_FRNT_ATTEN, 0x0000, 2);
-				if (v.flags & VIDEO_AUDIO_VOLUME)
-					debiwrite(saa, debNormal,
-						IBM_MP2_FRNT_ATTEN,
-						(i << 8) | i, 2);
-			} else {
-				if (v.flags & VIDEO_AUDIO_MUTE)
-					cs4341_setlevel(saa, 0xff, 0xff);
-				if (!(v.flags & VIDEO_AUDIO_MUTE))
-					cs4341_setlevel(saa, 0, 0);
-				if (v.flags & VIDEO_AUDIO_VOLUME)
-					cs4341_setlevel(saa, i, i);
-			}
-			saa->audio_dev = v;
-			return 0;
-		}
-
-	case VIDIOCGUNIT:
-		{
-			struct video_unit vu;
-			memset(&vu, 0, sizeof(vu));
-			vu.video = saa->video_dev.minor;
-			vu.vbi = VIDEO_NO_UNIT;
-			vu.radio = VIDEO_NO_UNIT;
-			vu.audio = VIDEO_NO_UNIT;
-			vu.teletext = VIDEO_NO_UNIT;
-			if (copy_to_user(arg, &vu, sizeof(vu)))
-				return -EFAULT;
-			return 0;
-		}
-	case VIDIOCSPLAYMODE:
-		{
-			struct video_play_mode pmode;
-			if (copy_from_user((void *)&pmode, arg,
-					sizeof(struct video_play_mode)))
-				return -EFAULT;
-			switch (pmode.mode) {
-			case VID_PLAY_VID_OUT_MODE:
-				if (pmode.p1 != VIDEO_MODE_NTSC &&
-						pmode.p1 != VIDEO_MODE_PAL)
-					return -EINVAL;
-				set_out_format(saa, pmode.p1);
-				return 0;
-			case VID_PLAY_GENLOCK:
-				debiwrite(saa, debNormal, XILINX_CTL0,
-					pmode.p1 ? 0x8000 : 0x8080, 2);
-				if (NewCard)
-					set_genlock_offset(saa, pmode.p2);
-				return 0;
-			case VID_PLAY_NORMAL:
-				debiwrite(saa, debNormal,
-					IBM_MP2_CHIP_CONTROL, ChipControl, 2);
-				ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
-				saa->playmode = pmode.mode;
-				return 0;
-			case VID_PLAY_PAUSE:
-				/* IBM removed the PAUSE command */
-				/* they say use SINGLE_FRAME now */
-			case VID_PLAY_SINGLE_FRAME:
-				ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0);
-				if (saa->playmode == pmode.mode) {
-					debiwrite(saa, debNormal,
-						IBM_MP2_CHIP_CONTROL,
-						ChipControl, 2);
-				}
-				saa->playmode = pmode.mode;
-				return 0;
-			case VID_PLAY_FAST_FORWARD:
-				ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0);
-				saa->playmode = pmode.mode;
-				return 0;
-			case VID_PLAY_SLOW_MOTION:
-				ibm_send_command(saa, IBM_MP2_SLOW_MOTION,
-					pmode.p1, 0);
-				saa->playmode = pmode.mode;
-				return 0;
-			case VID_PLAY_IMMEDIATE_NORMAL:
-				/* ensure transfers resume */
-				debiwrite(saa, debNormal,
-					IBM_MP2_CHIP_CONTROL, ChipControl, 2);
-				ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY,
-					0, 0);
-				saa->playmode = VID_PLAY_NORMAL;
-				return 0;
-			case VID_PLAY_SWITCH_CHANNELS:
-				saa->audhead = saa->audtail = 0;
-				saa->vidhead = saa->vidtail = 0;
-				ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1);
-				ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE,
-					0, 1);
-				debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
-					0, 2);
-				ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH,
-					0, 1);
-				debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
-					ChipControl, 2);
-				ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
-				saa->playmode = VID_PLAY_NORMAL;
-				return 0;
-			case VID_PLAY_FREEZE_FRAME:
-				ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0);
-				saa->playmode = pmode.mode;
-				return 0;
-			case VID_PLAY_STILL_MODE:
-				ibm_send_command(saa, IBM_MP2_SET_STILL_MODE,
-					0, 0);
-				saa->playmode = pmode.mode;
-				return 0;
-			case VID_PLAY_MASTER_MODE:
-				if (pmode.p1 == VID_PLAY_MASTER_NONE)
-					saa->boardcfg[1] = 0x13;
-				else if (pmode.p1 == VID_PLAY_MASTER_VIDEO)
-					saa->boardcfg[1] = 0x23;
-				else if (pmode.p1 == VID_PLAY_MASTER_AUDIO)
-					saa->boardcfg[1] = 0x43;
-				else
-					return -EINVAL;
-				debiwrite(saa, debNormal,
-					  IBM_MP2_CHIP_CONTROL, ChipControl, 2);
-				return 0;
-			case VID_PLAY_ACTIVE_SCANLINES:
-				if (CurrentMode == VIDEO_MODE_PAL) {
-					if (pmode.p1 < 1 || pmode.p2 > 625)
-						return -EINVAL;
-					saa->boardcfg[5] = pmode.p1;
-					saa->boardcfg[55] = (pmode.p1 +
-						(pmode.p2 / 2) - 1) & 0xff;
-				} else {
-					if (pmode.p1 < 4 || pmode.p2 > 525)
-						return -EINVAL;
-					saa->boardcfg[4] = pmode.p1;
-					saa->boardcfg[54] = (pmode.p1 +
-						(pmode.p2 / 2) - 4) & 0xff;
-				}
-				set_out_format(saa, CurrentMode);
-			case VID_PLAY_RESET:
-				return do_ibm_reset(saa);
-			case VID_PLAY_END_MARK:
-				if (saa->endmarktail < saa->endmarkhead) {
-					if (saa->endmarkhead -
-							saa->endmarktail < 2)
-						return -ENOSPC;
-				} else if (saa->endmarkhead <=saa->endmarktail){
-					if (saa->endmarktail - saa->endmarkhead
-							> (MAX_MARKS - 2))
-						return -ENOSPC;
-				} else
-					return -ENOSPC;
-				saa->endmark[saa->endmarktail] = saa->audtail;
-				saa->endmarktail++;
-				if (saa->endmarktail >= MAX_MARKS)
-					saa->endmarktail = 0;
-			}
-			return -EINVAL;
-		}
-	case VIDIOCSWRITEMODE:
-		{
-			int mode;
-			if (copy_from_user((void *)&mode, arg, sizeof(int)))
-				return -EFAULT;
-			if (mode == VID_WRITE_MPEG_AUD ||
-					mode == VID_WRITE_MPEG_VID ||
-					mode == VID_WRITE_CC ||
-					mode == VID_WRITE_TTX ||
-					mode == VID_WRITE_OSD) {
-				saa->writemode = mode;
-				return 0;
-			}
-			return -EINVAL;
-		}
-	case VIDIOCSMICROCODE:
-		{
-			struct video_code ucode;
-			__u8 *udata;
-			int i;
-			if (copy_from_user(&ucode, arg, sizeof(ucode)))
-				return -EFAULT;
-			if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
-					strncmp(ucode.loadwhat, "dec", 3))
-				return -EINVAL;
-			if ((udata = vmalloc(ucode.datasize)) == NULL)
-				return -ENOMEM;
-			if (copy_from_user(udata, ucode.data, ucode.datasize)) {
-				vfree(udata);
-				return -EFAULT;
-			}
-			ucode.data = udata;
-			if (!strncmp(ucode.loadwhat, "decoder.aud", 11) ||
-				!strncmp(ucode.loadwhat, "decoder.vid", 11))
-				i = initialize_ibmmpeg2(&ucode);
-			else
-				i = initialize_fpga(&ucode);
-			vfree(udata);
-			if (i)
-				return -EINVAL;
-			return 0;
-
-		}
-	case VIDIOCGCHAN:	/* this makes xawtv happy */
-		{
-			struct video_channel v;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			v.flags = VIDEO_VC_AUDIO;
-			v.tuners = 0;
-			v.type = VID_TYPE_MPEG_DECODER;
-			v.norm = CurrentMode;
-			strcpy(v.name, "MPEG2");
-			if (copy_to_user(arg, &v, sizeof(v)))
-				return -EFAULT;
-			return 0;
-		}
-	case VIDIOCSCHAN:	/* this makes xawtv happy */
-		{
-			struct video_channel v;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			/* do nothing */
-			return 0;
-		}
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static int saa_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct saa7146 *saa = file->private_data;
-	printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr);
-	return -EINVAL;
-}
-
-static ssize_t saa_read(struct file *file, char __user * buf,
-	size_t count, loff_t * ppos)
-{
-	return -EINVAL;
-}
-
-static ssize_t saa_write(struct file *file, const char __user * buf,
-	size_t count, loff_t * ppos)
-{
-	struct saa7146 *saa = file->private_data;
-	unsigned long todo = count;
-	int blocksize, split;
-	unsigned long flags;
-
-	while (todo > 0) {
-		if (saa->writemode == VID_WRITE_MPEG_AUD) {
-			spin_lock_irqsave(&saa->lock, flags);
-			if (saa->audhead <= saa->audtail)
-				blocksize = 65536 -
-					(saa->audtail - saa->audhead);
-			else
-				blocksize = saa->audhead - saa->audtail;
-			spin_unlock_irqrestore(&saa->lock, flags);
-			if (blocksize < 16384) {
-				saawrite(SAA7146_PSR_DEBI_S |
-					SAA7146_PSR_PIN1, SAA7146_IER);
-				saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
-				/* wait for buffer space to open */
-				interruptible_sleep_on(&saa->audq);
-			}
-			spin_lock_irqsave(&saa->lock, flags);
-			if (saa->audhead <= saa->audtail) {
-				blocksize = 65536 -
-					(saa->audtail - saa->audhead);
-				split = 65536 - saa->audtail;
-			} else {
-				blocksize = saa->audhead - saa->audtail;
-				split = 65536;
-			}
-			spin_unlock_irqrestore(&saa->lock, flags);
-			blocksize--;
-			if (blocksize > todo)
-				blocksize = todo;
-			/* double check that we really have space */
-			if (!blocksize)
-				return -ENOSPC;
-			if (split < blocksize) {
-				if (copy_from_user(saa->audbuf +
-						saa->audtail, buf, split))
-					return -EFAULT;
-				buf += split;
-				todo -= split;
-				blocksize -= split;
-				saa->audtail = 0;
-			}
-			if (copy_from_user(saa->audbuf + saa->audtail, buf,
-					blocksize))
-				return -EFAULT;
-			saa->audtail += blocksize;
-			todo -= blocksize;
-			buf += blocksize;
-			saa->audtail &= 0xffff;
-		} else if (saa->writemode == VID_WRITE_MPEG_VID) {
-			spin_lock_irqsave(&saa->lock, flags);
-			if (saa->vidhead <= saa->vidtail)
-				blocksize = 524288 -
-					(saa->vidtail - saa->vidhead);
-			else
-				blocksize = saa->vidhead - saa->vidtail;
-			spin_unlock_irqrestore(&saa->lock, flags);
-			if (blocksize < 65536) {
-				saawrite(SAA7146_PSR_DEBI_S |
-					SAA7146_PSR_PIN1, SAA7146_IER);
-				saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
-				/* wait for buffer space to open */
-				interruptible_sleep_on(&saa->vidq);
-			}
-			spin_lock_irqsave(&saa->lock, flags);
-			if (saa->vidhead <= saa->vidtail) {
-				blocksize = 524288 -
-					(saa->vidtail - saa->vidhead);
-				split = 524288 - saa->vidtail;
-			} else {
-				blocksize = saa->vidhead - saa->vidtail;
-				split = 524288;
-			}
-			spin_unlock_irqrestore(&saa->lock, flags);
-			blocksize--;
-			if (blocksize > todo)
-				blocksize = todo;
-			/* double check that we really have space */
-			if (!blocksize)
-				return -ENOSPC;
-			if (split < blocksize) {
-				if (copy_from_user(saa->vidbuf +
-						saa->vidtail, buf, split))
-					return -EFAULT;
-				buf += split;
-				todo -= split;
-				blocksize -= split;
-				saa->vidtail = 0;
-			}
-			if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
-					blocksize))
-				return -EFAULT;
-			saa->vidtail += blocksize;
-			todo -= blocksize;
-			buf += blocksize;
-			saa->vidtail &= 0x7ffff;
-		} else if (saa->writemode == VID_WRITE_OSD) {
-			if (count > 131072)
-				return -ENOSPC;
-			if (copy_from_user(saa->osdbuf, buf, count))
-				return -EFAULT;
-			buf += count;
-			saa->osdhead = 0;
-			saa->osdtail = count;
-			debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2);
-			debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
-			debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
-			debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
-				debiread(saa, debNormal,
-					IBM_MP2_DISP_MODE, 2) | 1, 2);
-			/* trigger osd data transfer */
-			saawrite(SAA7146_PSR_DEBI_S |
-				 SAA7146_PSR_PIN1, SAA7146_IER);
-			saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
-		}
-	}
-	return count;
-}
-
-static int saa_open(struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
-
-	lock_kernel();
-	file->private_data = saa;
-
-	saa->user++;
-	if (saa->user > 1) {
-		saa->user--;
-		unlock_kernel();
-		return 0;	/* device open already, don't reset */
-	}
-	saa->writemode = VID_WRITE_MPEG_VID;	/* default to video */
-	unlock_kernel();
-	return 0;
-}
-
-static int saa_release(struct file *file)
-{
-	struct saa7146 *saa = file->private_data;
-	saa->user--;
-
-	if (saa->user > 0)	/* still someone using device */
-		return 0;
-	saawrite(0x007f0000, SAA7146_MC1);	/* stop all overlay dma */
-	return 0;
-}
-
-static const struct v4l2_file_operations saa_fops = {
-	.owner = THIS_MODULE,
-	.open = saa_open,
-	.release = saa_release,
-	.ioctl = saa_ioctl,
-	.read = saa_read,
-	.write = saa_write,
-	.mmap = saa_mmap,
-};
-
-/* template for video_device-structure */
-static struct video_device saa_template = {
-	.name = "SAA7146A",
-	.fops = &saa_fops,
-	.release = video_device_release_empty,
-};
-
-static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
-{
-	int retval;
-	struct saa7146 *saa = pci_get_drvdata(pdev);
-
-	saa->endmarkhead = saa->endmarktail = 0;
-	saa->win.x = saa->win.y = 0;
-	saa->win.width = saa->win.cropwidth = 720;
-	saa->win.height = saa->win.cropheight = 480;
-	saa->win.cropx = saa->win.cropy = 0;
-	saa->win.bpp = 2;
-	saa->win.depth = 16;
-	saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565];
-	saa->win.bpl = 1024 * saa->win.bpp;
-	saa->win.swidth = 1024;
-	saa->win.sheight = 768;
-	saa->picture.brightness = 32768;
-	saa->picture.contrast = 38768;
-	saa->picture.colour = 32768;
-	saa->cap = 0;
-	saa->nr = num;
-	saa->playmode = VID_PLAY_NORMAL;
-	memset(saa->boardcfg, 0, 64);	/* clear board config area */
-	saa->saa7146_mem = NULL;
-	saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in =
-	    saa->dmaa1out = saa->dmaa2in = saa->dmaa2out =
-	    saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in =
-	    saa->pagea1out = saa->pagea2in = saa->pagea2out =
-	    saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 =
-	    saa->pageRPS2 = NULL;
-	saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL;
-	saa->audhead = saa->vidtail = 0;
-
-	init_waitqueue_head(&saa->i2cq);
-	init_waitqueue_head(&saa->audq);
-	init_waitqueue_head(&saa->debiq);
-	init_waitqueue_head(&saa->vidq);
-	spin_lock_init(&saa->lock);
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num);
-		goto err;
-	}
-
-	saa->id = pdev->device;
-	saa->irq = pdev->irq;
-	saa->saa7146_adr = pci_resource_start(pdev, 0);
-	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
-
-	saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200);
-	if (saa->saa7146_mem == NULL) {
-		dev_err(&pdev->dev, "%d: ioremap failed!\n", num);
-		retval = -EIO;
-		goto err;
-	}
-
-	memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
-	saawrite(0, SAA7146_IER);	/* turn off all interrupts */
-
-	retval = request_irq(saa->irq, saa7146_irq, IRQF_SHARED | IRQF_DISABLED,
-		"stradis", saa);
-	if (retval == -EINVAL)
-		dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num);
-	else if (retval == -EBUSY)
-		dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config "
-			"in BIOS\n", num, saa->irq);
-	if (retval < 0)
-		goto errio;
-
-	pci_set_master(pdev);
-	retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER,
-		video_nr);
-	if (retval < 0) {
-		dev_err(&pdev->dev, "%d: error in registering video device!\n",
-			num);
-		goto errirq;
-	}
-
-	return 0;
-
-errirq:
-	free_irq(saa->irq, saa);
-errio:
-	iounmap(saa->saa7146_mem);
-err:
-	return retval;
-}
-
-static int __devinit init_saa7146(struct pci_dev *pdev)
-{
-	struct saa7146 *saa = pci_get_drvdata(pdev);
-
-	saa->user = 0;
-	/* reset the saa7146 */
-	saawrite(0xffff0000, SAA7146_MC1);
-	mdelay(5);
-	/* enable debi and i2c transfers and pins */
-	saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C |
-		   SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1);
-	/* ensure proper state of chip */
-	saawrite(0x00000000, SAA7146_PAGE1);
-	saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1);
-	saawrite(0x00000000, SAA7146_PAGE2);
-	saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2);
-	saawrite(0x00000000, SAA7146_DD1_INIT);
-	saawrite(0x00000000, SAA7146_DD1_STREAM_B);
-	saawrite(0x00000000, SAA7146_DD1_STREAM_A);
-	saawrite(0x00000000, SAA7146_BRS_CTRL);
-	saawrite(0x80400040, SAA7146_BCS_CTRL);
-	saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL);
-	saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL);
-	saawrite(0x00000000, SAA7146_ACON1);
-	saawrite(0x00000000, SAA7146_ACON2);
-	saawrite(0x00000600, SAA7146_I2C_STATUS);
-	saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A |
-		SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
-		SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
-		SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
-		SAA7146_MC2);
-	/* setup arbitration control registers */
-	saawrite(0x1412121a, SAA7146_PCI_BT_V1);
-
-	/* allocate 32k dma buffer + 4k for page table */
-	if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) {
-		dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr);
-		goto err;
-	}
-#if 0
-	saa->pagedebi = saa->dmadebi + 32768;	/* top 4k is for mmu */
-	saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE);
-	for (i = 0; i < 12; i++)	/* setup mmu page table */
-		saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096));
-#endif
-	saa->audhead = saa->vidhead = saa->osdhead = 0;
-	saa->audtail = saa->vidtail = saa->osdtail = 0;
-	if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) {
-		dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
-		goto err;
-	}
-	if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
-		dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
-		goto errfree;
-	}
-	if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
-		dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
-		goto errfree;
-	}
-	/* allocate 81920 byte buffer for clipping */
-	if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
-		dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
-		goto errfree;
-	}
-	/* setup clipping registers */
-	saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
-	saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2);
-	saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE,
-		 SAA7146_PROT_ADDR2);
-	saawrite(256, SAA7146_PITCH2);
-	saawrite(4, SAA7146_PAGE2);	/* dma direction: read, no byteswap */
-	saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
-		 SAA7146_MC2);
-	I2CBusScan(saa);
-
-	return 0;
-errfree:
-	vfree(saa->osdbuf);
-	vfree(saa->audbuf);
-	vfree(saa->vidbuf);
-	saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
-err:
-	return -ENOMEM;
-}
-
-static void stradis_release_saa(struct pci_dev *pdev)
-{
-	u8 command;
-	struct saa7146 *saa = pci_get_drvdata(pdev);
-
-	/* turn off all capturing, DMA and IRQs */
-	saawrite(0xffff0000, SAA7146_MC1);	/* reset chip */
-	saawrite(0, SAA7146_MC2);
-	saawrite(0, SAA7146_IER);
-	saawrite(0xffffffffUL, SAA7146_ISR);
-
-	/* disable PCI bus-mastering */
-	pci_read_config_byte(pdev, PCI_COMMAND, &command);
-	command &= ~PCI_COMMAND_MASTER;
-	pci_write_config_byte(pdev, PCI_COMMAND, command);
-
-	/* unmap and free memory */
-	saa->audhead = saa->audtail = saa->osdhead = 0;
-	saa->vidhead = saa->vidtail = saa->osdtail = 0;
-	vfree(saa->vidbuf);
-	vfree(saa->audbuf);
-	vfree(saa->osdbuf);
-	kfree(saa->dmavid2);
-	saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
-	saa->dmavid2 = NULL;
-	kfree(saa->dmadebi);
-	kfree(saa->dmavid1);
-	kfree(saa->dmavid3);
-	kfree(saa->dmaa1in);
-	kfree(saa->dmaa1out);
-	kfree(saa->dmaa2in);
-	kfree(saa->dmaa2out);
-	kfree(saa->dmaRPS1);
-	kfree(saa->dmaRPS2);
-	free_irq(saa->irq, saa);
-	if (saa->saa7146_mem)
-		iounmap(saa->saa7146_mem);
-	if (video_is_registered(&saa->video_dev))
-		video_unregister_device(&saa->video_dev);
-}
-
-static int __devinit stradis_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	int retval = -EINVAL;
-
-	if (saa_num >= SAA7146_MAX)
-		goto err;
-
-	if (!pdev->subsystem_vendor)
-		dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num);
-	else
-		dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num);
-
-	pci_set_drvdata(pdev, &saa7146s[saa_num]);
-
-	retval = configure_saa7146(pdev, saa_num);
-	if (retval) {
-		dev_err(&pdev->dev, "%d: error in configuring\n", saa_num);
-		goto err;
-	}
-
-	if (init_saa7146(pdev) < 0) {
-		dev_err(&pdev->dev, "%d: error in initialization\n", saa_num);
-		retval = -EIO;
-		goto errrel;
-	}
-
-	saa_num++;
-
-	return 0;
-errrel:
-	stradis_release_saa(pdev);
-err:
-	return retval;
-}
-
-static void __devexit stradis_remove(struct pci_dev *pdev)
-{
-	stradis_release_saa(pdev);
-}
-
-static struct pci_device_id stradis_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) },
-	{ 0 }
-};
-
-
-static struct pci_driver stradis_driver = {
-	.name = "stradis",
-	.id_table = stradis_pci_tbl,
-	.probe = stradis_probe,
-	.remove = __devexit_p(stradis_remove)
-};
-
-static int __init stradis_init(void)
-{
-	int retval;
-
-	saa_num = 0;
-
-	retval = pci_register_driver(&stradis_driver);
-	if (retval)
-		printk(KERN_ERR "stradis: Unable to register pci driver.\n");
-
-	return retval;
-}
-
-static void __exit stradis_exit(void)
-{
-	pci_unregister_driver(&stradis_driver);
-	printk(KERN_INFO "stradis: module cleanup complete\n");
-}
-
-module_init(stradis_init);
-module_exit(stradis_exit);
diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h
index 1c1f157..1159a50 100644
--- a/drivers/staging/tidspbridge/core/_tiomap.h
+++ b/drivers/staging/tidspbridge/core/_tiomap.h
@@ -19,8 +19,19 @@
 #ifndef _TIOMAP_
 #define _TIOMAP_
 
-#include <plat/powerdomain.h>
-#include <plat/clockdomain.h>
+/*
+ * XXX These powerdomain.h/clockdomain.h includes are wrong and should
+ * be removed.  No driver should call pwrdm_* or clkdm_* functions
+ * directly; they should rely on OMAP core code to do this.
+ */
+#include <mach-omap2/powerdomain.h>
+#include <mach-omap2/clockdomain.h>
+/*
+ * XXX These mach-omap2/ includes are wrong and should be removed.  No
+ * driver should read or write to PRM/CM registers directly; they
+ * should rely on OMAP core code to do this.
+ */
+#include <mach-omap2/cm2xxx_3xxx.h>
 #include <mach-omap2/prm-regbits-34xx.h>
 #include <mach-omap2/cm-regbits-34xx.h>
 #include <dspbridge/devdefs.h>
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig
index de7ebb9..114eec8 100644
--- a/drivers/staging/tm6000/Kconfig
+++ b/drivers/staging/tm6000/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_TM6000
 	tristate "TV Master TM5600/6000/6010 driver"
-	depends on VIDEO_DEV && I2C && INPUT && IR_CORE && USB && EXPERIMENTAL
+	depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL
 	select VIDEO_TUNER
 	select MEDIA_TUNER_XC2028
 	select MEDIA_TUNER_XC5000
diff --git a/drivers/staging/tm6000/TODO b/drivers/staging/tm6000/TODO
index 34780fc..135d0ea 100644
--- a/drivers/staging/tm6000/TODO
+++ b/drivers/staging/tm6000/TODO
@@ -1,4 +1,6 @@
 There a few things to do before putting this driver in production:
+	- IR NEC with tm5600/6000 TV cards
+	- IR RC5 with tm5600/6000/6010 TV cards
 	- CodingStyle;
 	- Fix audio;
 	- Fix some panic/OOPS conditions.
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index b143258..455038b 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -328,6 +328,47 @@
 	{ },
 };
 
+/* Control power led for show some activity */
+void tm6000_flash_led(struct tm6000_core *dev, u8 state)
+{
+	/* Power LED unconfigured */
+	if (!dev->gpio.power_led)
+		return;
+
+	/* ON Power LED */
+	if (state) {
+		switch (dev->model) {
+		case TM6010_BOARD_HAUPPAUGE_900H:
+		case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+		case TM6010_BOARD_TWINHAN_TU501:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x00);
+			break;
+		case TM6010_BOARD_BEHOLD_WANDER:
+		case TM6010_BOARD_BEHOLD_VOYAGER:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x01);
+			break;
+		}
+	}
+	/* OFF Power LED */
+	else {
+		switch (dev->model) {
+		case TM6010_BOARD_HAUPPAUGE_900H:
+		case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+		case TM6010_BOARD_TWINHAN_TU501:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x01);
+			break;
+		case TM6010_BOARD_BEHOLD_WANDER:
+		case TM6010_BOARD_BEHOLD_VOYAGER:
+			tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+				dev->gpio.power_led, 0x00);
+			break;
+		}
+	}
+}
+
 /* Tuner callback to provide the proper gpio changes needed for xc5000 */
 int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
 {
@@ -521,13 +562,6 @@
 				printk(KERN_ERR "Error %i doing tuner reset\n", rc);
 				return rc;
 			}
-			msleep(10);
-
-			if (!i) {
-				rc = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
-				if (rc >= 0)
-					printk(KERN_DEBUG "board=0x%08x\n", rc);
-			}
 		}
 	} else {
 		printk(KERN_ERR "Tuner reset is not configured\n");
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
index 40a0206..96aed4a 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/staging/tm6000/tm6000-core.c
@@ -542,6 +542,26 @@
 	int board, rc = 0, i, size;
 	struct reg_init *tab;
 
+	/* Check board revision */
+	board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
+	if (board >= 0) {
+		switch (board & 0xff) {
+		case 0xf3:
+			printk(KERN_INFO "Found tm6000\n");
+			if (dev->dev_type != TM6000)
+				dev->dev_type = TM6000;
+			break;
+		case 0xf4:
+			printk(KERN_INFO "Found tm6010\n");
+			if (dev->dev_type != TM6010)
+				dev->dev_type = TM6010;
+			break;
+		default:
+			printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
+		}
+	} else
+		printk(KERN_ERR "Error %i while retrieving board version\n", board);
+
 	if (dev->dev_type == TM6010) {
 		tab = tm6010_init_tab;
 		size = ARRAY_SIZE(tm6010_init_tab);
@@ -563,13 +583,6 @@
 
 	msleep(5); /* Just to be conservative */
 
-	/* Check board version - maybe 10Moons specific */
-	board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
-	if (board >= 0)
-		printk(KERN_INFO "Board version = 0x%08x\n", board);
-	else
-		printk(KERN_ERR "Error %i while retrieving board version\n", board);
-
 	rc = tm6000_cards_setup(dev);
 
 	return rc;
@@ -709,5 +722,5 @@
 				ops->fini(dev);
 		}
 	}
-	mutex_lock(&tm6000_devlist_mutex);
+	mutex_unlock(&tm6000_devlist_mutex);
 }
diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c
index 93f625f..18de474 100644
--- a/drivers/staging/tm6000/tm6000-i2c.c
+++ b/drivers/staging/tm6000/tm6000-i2c.c
@@ -301,33 +301,11 @@
 	return I2C_FUNC_SMBUS_EMUL;
 }
 
-#define mass_write(addr, reg, data...)					\
-	{ static const u8 _val[] = data;				\
-	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,	\
-	REQ_16_SET_GET_I2C_WR1_RDN, (reg<<8)+addr, 0x00, (u8 *) _val,	\
-	ARRAY_SIZE(_val));						\
-	if (rc < 0) {							\
-		printk(KERN_ERR "Error on line %d: %d\n", __LINE__, rc);	\
-		return rc;						\
-	}								\
-	msleep(10);							\
-	}
-
-static struct i2c_algorithm tm6000_algo = {
+static const struct i2c_algorithm tm6000_algo = {
 	.master_xfer   = tm6000_i2c_xfer,
 	.functionality = functionality,
 };
 
-static struct i2c_adapter tm6000_adap_template = {
-	.owner = THIS_MODULE,
-	.name = "tm6000",
-	.algo = &tm6000_algo,
-};
-
-static struct i2c_client tm6000_client_template = {
-	.name = "tm6000 internal",
-};
-
 /* ----------------------------------------------------------- */
 
 /*
@@ -337,17 +315,20 @@
 int tm6000_i2c_register(struct tm6000_core *dev)
 {
 	unsigned char eedata[256];
+	int rc;
 
-	dev->i2c_adap = tm6000_adap_template;
+	dev->i2c_adap.owner = THIS_MODULE;
+	dev->i2c_adap.algo = &tm6000_algo;
 	dev->i2c_adap.dev.parent = &dev->udev->dev;
-	strcpy(dev->i2c_adap.name, dev->name);
+	strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
 	dev->i2c_adap.algo_data = dev;
-	i2c_add_adapter(&dev->i2c_adap);
-
-	dev->i2c_client = tm6000_client_template;
-	dev->i2c_client.adapter = &dev->i2c_adap;
-
 	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+	rc = i2c_add_adapter(&dev->i2c_adap);
+	if (rc)
+		return rc;
+
+	dev->i2c_client.adapter = &dev->i2c_adap;
+	strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
 
 	tm6000_i2c_eeprom(dev, eedata, sizeof(eedata));
 
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c
index 6022caa..21e7da4 100644
--- a/drivers/staging/tm6000/tm6000-input.c
+++ b/drivers/staging/tm6000/tm6000-input.c
@@ -24,8 +24,7 @@
 #include <linux/input.h>
 #include <linux/usb.h>
 
-#include <media/ir-core.h>
-#include <media/ir-common.h>
+#include <media/rc-core.h>
 
 #include "tm6000.h"
 #include "tm6000-regs.h"
@@ -38,6 +37,10 @@
 module_param(enable_ir, int, 0644);
 MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
 
+/* number of 50ms for ON-OFF-ON power led */
+/* show IR activity */
+#define PWLED_OFF 2
+
 #undef dprintk
 
 #define dprintk(fmt, arg...) \
@@ -51,8 +54,7 @@
 
 struct tm6000_IR {
 	struct tm6000_core	*dev;
-	struct ir_input_dev	*input;
-	struct ir_input_state	ir;
+	struct rc_dev		*rc;
 	char			name[32];
 	char			phys[32];
 
@@ -61,13 +63,16 @@
 	struct delayed_work	work;
 	u8			wait:1;
 	u8			key:1;
+	u8			pwled:1;
+	u8			pwledcnt;
+	u16			key_addr;
 	struct urb		*int_urb;
 	u8			*urb_data;
 
 	int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
 
 	/* IR device properties */
-	struct ir_dev_props	props;
+	u64			rc_type;
 };
 
 
@@ -91,26 +96,49 @@
 	u8 buf[10];
 	int rc;
 
-	/* hack */
-	buf[0] = 0xff;
-	buf[1] = 0xff;
-	buf[2] = 0xf2;
-	buf[3] = 0x2b;
-	buf[4] = 0x20;
-	buf[5] = 0x35;
-	buf[6] = 0x60;
-	buf[7] = 0x04;
-	buf[8] = 0xc0;
-	buf[9] = 0x08;
+	switch (ir->rc_type) {
+	case RC_TYPE_NEC:
+		/* Setup IR decoder for NEC standard 12MHz system clock */
+		/* IR_LEADER_CNT = 0.9ms             */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
+		/* IR_PULSE_CNT = 0.7ms              */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
+		/* Remote WAKEUP = enable */
+		tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
+		/* IR_WKUP_SEL = Low byte in decoded IR data */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
+		/* IR_WKU_ADD code */
+		tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
+		tm6000_flash_led(dev, 0);
+		msleep(100);
+		tm6000_flash_led(dev, 1);
+		break;
+	default:
+		/* hack */
+		buf[0] = 0xff;
+		buf[1] = 0xff;
+		buf[2] = 0xf2;
+		buf[3] = 0x2b;
+		buf[4] = 0x20;
+		buf[5] = 0x35;
+		buf[6] = 0x60;
+		buf[7] = 0x04;
+		buf[8] = 0xc0;
+		buf[9] = 0x08;
 
-	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
-		USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
-	msleep(100);
+		rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+			USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
+		msleep(100);
 
-	if (rc < 0) {
-		printk(KERN_INFO "IR configuration failed");
-		return rc;
+		if (rc < 0) {
+			printk(KERN_INFO "IR configuration failed");
+			return rc;
+		}
+		break;
 	}
+
 	return 0;
 }
 
@@ -145,17 +173,28 @@
 		return 0;
 
 	if (&dev->int_in) {
-		if (ir->ir.ir_type == IR_TYPE_RC5)
+		switch (ir->rc_type) {
+		case RC_TYPE_RC5:
 			poll_result->rc_data = ir->urb_data[0];
-		else
-			poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8;
+			break;
+		case RC_TYPE_NEC:
+			if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) {
+				poll_result->rc_data = ir->urb_data[0]
+							| ir->urb_data[1] << 8;
+			}
+			break;
+		default:
+			poll_result->rc_data = ir->urb_data[0]
+					| ir->urb_data[1] << 8;
+			break;
+		}
 	} else {
 		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
 		msleep(10);
 		tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
 		msleep(10);
 
-		if (ir->ir.ir_type == IR_TYPE_RC5) {
+		if (ir->rc_type == RC_TYPE_RC5) {
 			rc = tm6000_read_write_usb(dev, USB_DIR_IN |
 				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				REQ_02_GET_IR_CODE, 0, 0, buf, 1);
@@ -188,6 +227,7 @@
 
 static void tm6000_ir_handle_key(struct tm6000_IR *ir)
 {
+	struct tm6000_core *dev = ir->dev;
 	int result;
 	struct tm6000_ir_poll_result poll_result;
 
@@ -200,12 +240,21 @@
 
 	dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
 
-	if (ir->key) {
-		ir_input_keydown(ir->input->input_dev, &ir->ir,
-				(u32)poll_result.rc_data);
+	if (ir->pwled) {
+		if (ir->pwledcnt >= PWLED_OFF) {
+			ir->pwled = 0;
+			ir->pwledcnt = 0;
+			tm6000_flash_led(dev, 1);
+		} else
+			ir->pwledcnt += 1;
+	}
 
-		ir_input_nokey(ir->input->input_dev, &ir->ir);
+	if (ir->key) {
+		rc_keydown(ir->rc, poll_result.rc_data, 0);
 		ir->key = 0;
+		ir->pwled = 1;
+		ir->pwledcnt = 0;
+		tm6000_flash_led(dev, 0);
 	}
 	return;
 }
@@ -218,9 +267,9 @@
 	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 }
 
-static int tm6000_ir_start(void *priv)
+static int tm6000_ir_start(struct rc_dev *rc)
 {
-	struct tm6000_IR *ir = priv;
+	struct tm6000_IR *ir = rc->priv;
 
 	INIT_DELAYED_WORK(&ir->work, tm6000_ir_work);
 	schedule_delayed_work(&ir->work, 0);
@@ -228,30 +277,91 @@
 	return 0;
 }
 
-static void tm6000_ir_stop(void *priv)
+static void tm6000_ir_stop(struct rc_dev *rc)
 {
-	struct tm6000_IR *ir = priv;
+	struct tm6000_IR *ir = rc->priv;
 
 	cancel_delayed_work_sync(&ir->work);
 }
 
-int tm6000_ir_change_protocol(void *priv, u64 ir_type)
+int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
-	struct tm6000_IR *ir = priv;
+	struct tm6000_IR *ir = rc->priv;
+
+	if (!ir)
+		return 0;
+
+	if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
+		ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
 
 	ir->get_key = default_polling_getkey;
+	ir->rc_type = rc_type;
 
 	tm6000_ir_config(ir);
 	/* TODO */
 	return 0;
 }
 
+int tm6000_ir_int_start(struct tm6000_core *dev)
+{
+	struct tm6000_IR *ir = dev->ir;
+	int pipe, size;
+	int err = -ENOMEM;
+
+
+	if (!ir)
+		return -ENODEV;
+
+	ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+	pipe = usb_rcvintpipe(dev->udev,
+		dev->int_in.endp->desc.bEndpointAddress
+		& USB_ENDPOINT_NUMBER_MASK);
+
+	size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+	dprintk("IR max size: %d\n", size);
+
+	ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+	if (ir->int_urb->transfer_buffer == NULL) {
+		usb_free_urb(ir->int_urb);
+		return err;
+	}
+	dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
+	usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
+		ir->int_urb->transfer_buffer, size,
+		tm6000_ir_urb_received, dev,
+		dev->int_in.endp->desc.bInterval);
+	err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
+	if (err) {
+		kfree(ir->int_urb->transfer_buffer);
+		usb_free_urb(ir->int_urb);
+		return err;
+	}
+	ir->urb_data = kzalloc(size, GFP_KERNEL);
+
+	return 0;
+}
+
+void tm6000_ir_int_stop(struct tm6000_core *dev)
+{
+	struct tm6000_IR *ir = dev->ir;
+
+	if (!ir)
+		return;
+
+	usb_kill_urb(ir->int_urb);
+	kfree(ir->int_urb->transfer_buffer);
+	usb_free_urb(ir->int_urb);
+	ir->int_urb = NULL;
+	kfree(ir->urb_data);
+	ir->urb_data = NULL;
+}
+
 int tm6000_ir_init(struct tm6000_core *dev)
 {
 	struct tm6000_IR *ir;
-	struct ir_input_dev *ir_input_dev;
+	struct rc_dev *rc;
 	int err = -ENOMEM;
-	int pipe, size, rc;
 
 	if (!enable_ir)
 		return -ENODEV;
@@ -263,26 +373,27 @@
 		return 0;
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-	ir_input_dev = kzalloc(sizeof(*ir_input_dev), GFP_KERNEL);
-	ir_input_dev->input_dev = input_allocate_device();
-	if (!ir || !ir_input_dev || !ir_input_dev->input_dev)
-		goto err_out_free;
+	rc = rc_allocate_device();
+	if (!ir | !rc)
+		goto out;
 
 	/* record handles to ourself */
 	ir->dev = dev;
 	dev->ir = ir;
-
-	ir->input = ir_input_dev;
+	ir->rc = rc;
 
 	/* input einrichten */
-	ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC;
-	ir->props.priv = ir;
-	ir->props.change_protocol = tm6000_ir_change_protocol;
-	ir->props.open = tm6000_ir_start;
-	ir->props.close = tm6000_ir_stop;
-	ir->props.driver_type = RC_DRIVER_SCANCODE;
+	rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+	rc->priv = ir;
+	rc->change_protocol = tm6000_ir_change_protocol;
+	rc->open = tm6000_ir_start;
+	rc->close = tm6000_ir_stop;
+	rc->driver_type = RC_DRIVER_SCANCODE;
 
 	ir->polling = 50;
+	ir->pwled = 0;
+	ir->pwledcnt = 0;
+
 
 	snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
 						dev->name);
@@ -290,64 +401,37 @@
 	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
 	strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
-	tm6000_ir_change_protocol(ir, IR_TYPE_UNKNOWN);
-	err = ir_input_init(ir_input_dev->input_dev, &ir->ir, IR_TYPE_OTHER);
-	if (err < 0)
-		goto err_out_free;
+	tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
 
-	ir_input_dev->input_dev->name = ir->name;
-	ir_input_dev->input_dev->phys = ir->phys;
-	ir_input_dev->input_dev->id.bustype = BUS_USB;
-	ir_input_dev->input_dev->id.version = 1;
-	ir_input_dev->input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-	ir_input_dev->input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-	ir_input_dev->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->map_name = dev->ir_codes;
+	rc->driver_name = "tm6000";
+	rc->dev.parent = &dev->udev->dev;
 
 	if (&dev->int_in) {
 		dprintk("IR over int\n");
 
-		ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+		err = tm6000_ir_int_start(dev);
 
-		pipe = usb_rcvintpipe(dev->udev,
-			dev->int_in.endp->desc.bEndpointAddress
-			& USB_ENDPOINT_NUMBER_MASK);
-
-		size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-		dprintk("IR max size: %d\n", size);
-
-		ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
-		if (ir->int_urb->transfer_buffer == NULL) {
-			usb_free_urb(ir->int_urb);
-			goto err_out_stop;
-		}
-		dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
-		usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
-			ir->int_urb->transfer_buffer, size,
-			tm6000_ir_urb_received, dev,
-			dev->int_in.endp->desc.bInterval);
-		rc = usb_submit_urb(ir->int_urb, GFP_KERNEL);
-		if (rc) {
-			kfree(ir->int_urb->transfer_buffer);
-			usb_free_urb(ir->int_urb);
-			err = rc;
-			goto err_out_stop;
-		}
-		ir->urb_data = kzalloc(size, GFP_KERNEL);
+		if (err)
+			goto out;
 	}
 
 	/* ir register */
-	err = ir_input_register(ir->input->input_dev, dev->ir_codes,
-		&ir->props, "tm6000");
+	err = rc_register_device(rc);
 	if (err)
-		goto err_out_stop;
+		goto out;
 
 	return 0;
 
-err_out_stop:
+out:
 	dev->ir = NULL;
-err_out_free:
-	kfree(ir_input_dev);
+	rc_free_device(rc);
 	kfree(ir);
 	return err;
 }
@@ -361,19 +445,12 @@
 	if (!ir)
 		return 0;
 
-	ir_input_unregister(ir->input->input_dev);
+	rc_unregister_device(ir->rc);
 
 	if (ir->int_urb) {
-		usb_kill_urb(ir->int_urb);
-		kfree(ir->int_urb->transfer_buffer);
-		usb_free_urb(ir->int_urb);
-		ir->int_urb = NULL;
-		kfree(ir->urb_data);
-		ir->urb_data = NULL;
+		tm6000_ir_int_stop(dev);
 	}
 
-	kfree(ir->input);
-	ir->input = NULL;
 	kfree(ir);
 	dev->ir = NULL;
 
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c
index c5690b2..8fe017c 100644
--- a/drivers/staging/tm6000/tm6000-video.c
+++ b/drivers/staging/tm6000/tm6000-video.c
@@ -545,11 +545,16 @@
 
 	/* De-allocates all pending stuff */
 	tm6000_uninit_isoc(dev);
+	/* Stop interrupt USB pipe */
+	tm6000_ir_int_stop(dev);
 
 	usb_set_interface(dev->udev,
 			  dev->isoc_in.bInterfaceNumber,
 			  dev->isoc_in.bAlternateSetting);
 
+	/* Start interrupt USB pipe */
+	tm6000_ir_int_start(dev);
+
 	pipe = usb_rcvisocpipe(dev->udev,
 			       dev->isoc_in.endp->desc.bEndpointAddress &
 			       USB_ENDPOINT_NUMBER_MASK);
@@ -986,15 +991,6 @@
 				file->f_flags & O_NONBLOCK);
 }
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
-{
-	struct tm6000_fh  *fh = priv;
-
-	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
-}
-#endif
-
 static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct tm6000_fh  *fh = priv;
@@ -1438,9 +1434,6 @@
 	.vidioc_querybuf          = vidioc_querybuf,
 	.vidioc_qbuf              = vidioc_qbuf,
 	.vidioc_dqbuf             = vidioc_dqbuf,
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	.vidiocgmbuf              = vidiocgmbuf,
-#endif
 };
 
 static struct video_device tm6000_template = {
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
index 46017b60..bf11eee 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/staging/tm6000/tm6000.h
@@ -266,6 +266,7 @@
 int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
 int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
 int tm6000_cards_setup(struct tm6000_core *dev);
+void tm6000_flash_led(struct tm6000_core *dev, u8 state);
 
 /* In tm6000-core.c */
 
@@ -332,6 +333,8 @@
 int tm6000_ir_init(struct tm6000_core *dev);
 int tm6000_ir_fini(struct tm6000_core *dev);
 void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
+int tm6000_ir_int_start(struct tm6000_core *dev);
+void tm6000_ir_int_stop(struct tm6000_core *dev);
 
 /* Debug stuff */
 
diff --git a/drivers/staging/udlfb/Kconfig b/drivers/staging/udlfb/Kconfig
deleted file mode 100644
index 65bd5db..0000000
--- a/drivers/staging/udlfb/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-config FB_UDL
-	tristate "Displaylink USB Framebuffer support"
-	depends on FB && USB
-	select FB_MODE_HELPERS
-	select FB_SYS_FILLRECT
-	select FB_SYS_COPYAREA
-	select FB_SYS_IMAGEBLIT
-	select FB_SYS_FOPS
-	select FB_DEFERRED_IO
-	---help---
-	  This is a kernel framebuffer driver for DisplayLink USB devices.
-	  Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
-	  mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
-	  To compile as a module, choose M here: the module name is udlfb.
diff --git a/drivers/staging/udlfb/Makefile b/drivers/staging/udlfb/Makefile
deleted file mode 100644
index 30d9e67..0000000
--- a/drivers/staging/udlfb/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_FB_UDL)		+= udlfb.o
diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
deleted file mode 100644
index b7ac160..0000000
--- a/drivers/staging/udlfb/udlfb.c
+++ /dev/null
@@ -1,1916 +0,0 @@
-/*
- * udlfb.c -- Framebuffer driver for DisplayLink USB controller
- *
- * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
- * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
- * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License v2. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
- * usb-skeleton by GregKH.
- *
- * Device-specific portions based on information from Displaylink, with work
- * from Florian Echtler, Henrik Bjerregaard Pedersen, and others.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/uaccess.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include "udlfb.h"
-
-static struct fb_fix_screeninfo dlfb_fix = {
-	.id =           "udlfb",
-	.type =         FB_TYPE_PACKED_PIXELS,
-	.visual =       FB_VISUAL_TRUECOLOR,
-	.xpanstep =     0,
-	.ypanstep =     0,
-	.ywrapstep =    0,
-	.accel =        FB_ACCEL_NONE,
-};
-
-static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
-#ifdef FBINFO_VIRTFB
-		FBINFO_VIRTFB |
-#endif
-		FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
-		FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
-
-/*
- * There are many DisplayLink-based products, all with unique PIDs. We are able
- * to support all volume ones (circa 2009) with a single driver, so we match
- * globally on VID. TODO: Probe() needs to detect when we might be running
- * "future" chips, and bail on those, so a compatible driver can match.
- */
-static struct usb_device_id id_table[] = {
-	{.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
-	{},
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-/* module options */
-static int console;   /* Optionally allow fbcon to consume first framebuffer */
-static int fb_defio;  /* Optionally enable experimental fb_defio mmap support */
-
-/* dlfb keeps a list of urbs for efficient bulk transfers */
-static void dlfb_urb_completion(struct urb *urb);
-static struct urb *dlfb_get_urb(struct dlfb_data *dev);
-static int dlfb_submit_urb(struct dlfb_data *dev, struct urb * urb, size_t len);
-static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size);
-static void dlfb_free_urb_list(struct dlfb_data *dev);
-
-/*
- * All DisplayLink bulk operations start with 0xAF, followed by specific code
- * All operations are written to buffers which then later get sent to device
- */
-static char *dlfb_set_register(char *buf, u8 reg, u8 val)
-{
-	*buf++ = 0xAF;
-	*buf++ = 0x20;
-	*buf++ = reg;
-	*buf++ = val;
-	return buf;
-}
-
-static char *dlfb_vidreg_lock(char *buf)
-{
-	return dlfb_set_register(buf, 0xFF, 0x00);
-}
-
-static char *dlfb_vidreg_unlock(char *buf)
-{
-	return dlfb_set_register(buf, 0xFF, 0xFF);
-}
-
-/*
- * On/Off for driving the DisplayLink framebuffer to the display
- *  0x00 H and V sync on
- *  0x01 H and V sync off (screen blank but powered)
- *  0x07 DPMS powerdown (requires modeset to come back)
- */
-static char *dlfb_enable_hvsync(char *buf, bool enable)
-{
-	if (enable)
-		return dlfb_set_register(buf, 0x1F, 0x00);
-	else
-		return dlfb_set_register(buf, 0x1F, 0x07);
-}
-
-static char *dlfb_set_color_depth(char *buf, u8 selection)
-{
-	return dlfb_set_register(buf, 0x00, selection);
-}
-
-static char *dlfb_set_base16bpp(char *wrptr, u32 base)
-{
-	/* the base pointer is 16 bits wide, 0x20 is hi byte. */
-	wrptr = dlfb_set_register(wrptr, 0x20, base >> 16);
-	wrptr = dlfb_set_register(wrptr, 0x21, base >> 8);
-	return dlfb_set_register(wrptr, 0x22, base);
-}
-
-/*
- * DisplayLink HW has separate 16bpp and 8bpp framebuffers.
- * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
- */
-static char *dlfb_set_base8bpp(char *wrptr, u32 base)
-{
-	wrptr = dlfb_set_register(wrptr, 0x26, base >> 16);
-	wrptr = dlfb_set_register(wrptr, 0x27, base >> 8);
-	return dlfb_set_register(wrptr, 0x28, base);
-}
-
-static char *dlfb_set_register_16(char *wrptr, u8 reg, u16 value)
-{
-	wrptr = dlfb_set_register(wrptr, reg, value >> 8);
-	return dlfb_set_register(wrptr, reg+1, value);
-}
-
-/*
- * This is kind of weird because the controller takes some
- * register values in a different byte order than other registers.
- */
-static char *dlfb_set_register_16be(char *wrptr, u8 reg, u16 value)
-{
-	wrptr = dlfb_set_register(wrptr, reg, value);
-	return dlfb_set_register(wrptr, reg+1, value >> 8);
-}
-
-/*
- * LFSR is linear feedback shift register. The reason we have this is
- * because the display controller needs to minimize the clock depth of
- * various counters used in the display path. So this code reverses the
- * provided value into the lfsr16 value by counting backwards to get
- * the value that needs to be set in the hardware comparator to get the
- * same actual count. This makes sense once you read above a couple of
- * times and think about it from a hardware perspective.
- */
-static u16 dlfb_lfsr16(u16 actual_count)
-{
-	u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */
-
-	while (actual_count--) {
-		lv =	 ((lv << 1) |
-			(((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1))
-			& 0xFFFF;
-	}
-
-	return (u16) lv;
-}
-
-/*
- * This does LFSR conversion on the value that is to be written.
- * See LFSR explanation above for more detail.
- */
-static char *dlfb_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
-{
-	return dlfb_set_register_16(wrptr, reg, dlfb_lfsr16(value));
-}
-
-/*
- * This takes a standard fbdev screeninfo struct and all of its monitor mode
- * details and converts them into the DisplayLink equivalent register commands.
- */
-static char *dlfb_set_vid_cmds(char *wrptr, struct fb_var_screeninfo *var)
-{
-	u16 xds, yds;
-	u16 xde, yde;
-	u16 yec;
-
-	/* x display start */
-	xds = var->left_margin + var->hsync_len;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x01, xds);
-	/* x display end */
-	xde = xds + var->xres;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x03, xde);
-
-	/* y display start */
-	yds = var->upper_margin + var->vsync_len;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x05, yds);
-	/* y display end */
-	yde = yds + var->yres;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x07, yde);
-
-	/* x end count is active + blanking - 1 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x09,
-			xde + var->right_margin - 1);
-
-	/* libdlo hardcodes hsync start to 1 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0B, 1);
-
-	/* hsync end is width of sync pulse + 1 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0D, var->hsync_len + 1);
-
-	/* hpixels is active pixels */
-	wrptr = dlfb_set_register_16(wrptr, 0x0F, var->xres);
-
-	/* yendcount is vertical active + vertical blanking */
-	yec = var->yres + var->upper_margin + var->lower_margin +
-			var->vsync_len;
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x11, yec);
-
-	/* libdlo hardcodes vsync start to 0 */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x13, 0);
-
-	/* vsync end is width of vsync pulse */
-	wrptr = dlfb_set_register_lfsr16(wrptr, 0x15, var->vsync_len);
-
-	/* vpixels is active pixels */
-	wrptr = dlfb_set_register_16(wrptr, 0x17, var->yres);
-
-	/* convert picoseconds to 5kHz multiple for pclk5k = x * 1E12/5k */
-	wrptr = dlfb_set_register_16be(wrptr, 0x1B,
-			200*1000*1000/var->pixclock);
-
-	return wrptr;
-}
-
-/*
- * This takes a standard fbdev screeninfo struct that was fetched or prepared
- * and then generates the appropriate command sequence that then drives the
- * display controller.
- */
-static int dlfb_set_video_mode(struct dlfb_data *dev,
-				struct fb_var_screeninfo *var)
-{
-	char *buf;
-	char *wrptr;
-	int retval = 0;
-	int writesize;
-	struct urb *urb;
-
-	if (!atomic_read(&dev->usb_active))
-		return -EPERM;
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return -ENOMEM;
-
-	buf = (char *) urb->transfer_buffer;
-
-	/*
-	* This first section has to do with setting the base address on the
-	* controller * associated with the display. There are 2 base
-	* pointers, currently, we only * use the 16 bpp segment.
-	*/
-	wrptr = dlfb_vidreg_lock(buf);
-	wrptr = dlfb_set_color_depth(wrptr, 0x00);
-	/* set base for 16bpp segment to 0 */
-	wrptr = dlfb_set_base16bpp(wrptr, 0);
-	/* set base for 8bpp segment to end of fb */
-	wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
-
-	wrptr = dlfb_set_vid_cmds(wrptr, var);
-	wrptr = dlfb_enable_hvsync(wrptr, true);
-	wrptr = dlfb_vidreg_unlock(wrptr);
-
-	writesize = wrptr - buf;
-
-	retval = dlfb_submit_urb(dev, urb, writesize);
-
-	return retval;
-}
-
-static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	unsigned long start = vma->vm_start;
-	unsigned long size = vma->vm_end - vma->vm_start;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	unsigned long page, pos;
-
-	if (offset + size > info->fix.smem_len)
-		return -EINVAL;
-
-	pos = (unsigned long)info->fix.smem_start + offset;
-
-	dl_notice("mmap() framebuffer addr:%lu size:%lu\n",
-		  pos, size);
-
-	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;
-	}
-
-	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
-	return 0;
-}
-
-/*
- * Trims identical data from front and back of line
- * Sets new front buffer address and width
- * And returns byte count of identical pixels
- * Assumes CPU natural alignment (unsigned long)
- * for back and front buffer ptrs and width
- */
-static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
-{
-	int j, k;
-	const unsigned long *back = (const unsigned long *) bback;
-	const unsigned long *front = (const unsigned long *) *bfront;
-	const int width = *width_bytes / sizeof(unsigned long);
-	int identical = width;
-	int start = width;
-	int end = width;
-
-	prefetch((void *) front);
-	prefetch((void *) back);
-
-	for (j = 0; j < width; j++) {
-		if (back[j] != front[j]) {
-			start = j;
-			break;
-		}
-	}
-
-	for (k = width - 1; k > j; k--) {
-		if (back[k] != front[k]) {
-			end = k+1;
-			break;
-		}
-	}
-
-	identical = start + (width - end);
-	*bfront = (u8 *) &front[start];
-	*width_bytes = (end - start) * sizeof(unsigned long);
-
-	return identical * sizeof(unsigned long);
-}
-
-/*
- * Render a command stream for an encoded horizontal line segment of pixels.
- *
- * A command buffer holds several commands.
- * It always begins with a fresh command header
- * (the protocol doesn't require this, but we enforce it to allow
- * multiple buffers to be potentially encoded and sent in parallel).
- * A single command encodes one contiguous horizontal line of pixels
- *
- * The function relies on the client to do all allocation, so that
- * rendering can be done directly to output buffers (e.g. USB URBs).
- * The function fills the supplied command buffer, providing information
- * on where it left off, so the client may call in again with additional
- * buffers if the line will take several buffers to complete.
- *
- * A single command can transmit a maximum of 256 pixels,
- * regardless of the compression ratio (protocol design limit).
- * To the hardware, 0 for a size byte means 256
- *
- * Rather than 256 pixel commands which are either rl or raw encoded,
- * the rlx command simply assumes alternating raw and rl spans within one cmd.
- * This has a slightly larger header overhead, but produces more even results.
- * It also processes all data (read and write) in a single pass.
- * Performance benchmarks of common cases show it having just slightly better
- * compression than 256 pixel raw or rle commands, with similar CPU consumpion.
- * But for very rl friendly data, will compress not quite as well.
- */
-static void dlfb_compress_hline(
-	const uint16_t **pixel_start_ptr,
-	const uint16_t *const pixel_end,
-	uint32_t *device_address_ptr,
-	uint8_t **command_buffer_ptr,
-	const uint8_t *const cmd_buffer_end)
-{
-	const uint16_t *pixel = *pixel_start_ptr;
-	uint32_t dev_addr  = *device_address_ptr;
-	uint8_t *cmd = *command_buffer_ptr;
-	const int bpp = 2;
-
-	while ((pixel_end > pixel) &&
-	       (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) {
-		uint8_t *raw_pixels_count_byte = 0;
-		uint8_t *cmd_pixels_count_byte = 0;
-		const uint16_t *raw_pixel_start = 0;
-		const uint16_t *cmd_pixel_start, *cmd_pixel_end = 0;
-
-		prefetchw((void *) cmd); /* pull in one cache line at least */
-
-		*cmd++ = 0xAF;
-		*cmd++ = 0x6B;
-		*cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
-		*cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
-		*cmd++ = (uint8_t) ((dev_addr) & 0xFF);
-
-		cmd_pixels_count_byte = cmd++; /*  we'll know this later */
-		cmd_pixel_start = pixel;
-
-		raw_pixels_count_byte = cmd++; /*  we'll know this later */
-		raw_pixel_start = pixel;
-
-		cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
-			min((int)(pixel_end - pixel),
-			    (int)(cmd_buffer_end - cmd) / bpp));
-
-		prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
-
-		while (pixel < cmd_pixel_end) {
-			const uint16_t * const repeating_pixel = pixel;
-
-			*(uint16_t *)cmd = cpu_to_be16p(pixel);
-			cmd += 2;
-			pixel++;
-
-			if (unlikely((pixel < cmd_pixel_end) &&
-				     (*pixel == *repeating_pixel))) {
-				/* go back and fill in raw pixel count */
-				*raw_pixels_count_byte = ((repeating_pixel -
-						raw_pixel_start) + 1) & 0xFF;
-
-				while ((pixel < cmd_pixel_end)
-				       && (*pixel == *repeating_pixel)) {
-					pixel++;
-				}
-
-				/* immediately after raw data is repeat byte */
-				*cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
-
-				/* Then start another raw pixel span */
-				raw_pixel_start = pixel;
-				raw_pixels_count_byte = cmd++;
-			}
-		}
-
-		if (pixel > raw_pixel_start) {
-			/* finalize last RAW span */
-			*raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
-		}
-
-		*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
-		dev_addr += (pixel - cmd_pixel_start) * bpp;
-	}
-
-	if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
-		/* Fill leftover bytes with no-ops */
-		if (cmd_buffer_end > cmd)
-			memset(cmd, 0xAF, cmd_buffer_end - cmd);
-		cmd = (uint8_t *) cmd_buffer_end;
-	}
-
-	*command_buffer_ptr = cmd;
-	*pixel_start_ptr = pixel;
-	*device_address_ptr = dev_addr;
-
-	return;
-}
-
-/*
- * There are 3 copies of every pixel: The front buffer that the fbdev
- * client renders to, the actual framebuffer across the USB bus in hardware
- * (that we can only write to, slowly, and can never read), and (optionally)
- * our shadow copy that tracks what's been sent to that hardware buffer.
- */
-static int dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
-			      const char *front, char **urb_buf_ptr,
-			      u32 byte_offset, u32 byte_width,
-			      int *ident_ptr, int *sent_ptr)
-{
-	const u8 *line_start, *line_end, *next_pixel;
-	u32 dev_addr = dev->base16 + byte_offset;
-	struct urb *urb = *urb_ptr;
-	u8 *cmd = *urb_buf_ptr;
-	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
-
-	line_start = (u8 *) (front + byte_offset);
-	next_pixel = line_start;
-	line_end = next_pixel + byte_width;
-
-	if (dev->backing_buffer) {
-		int offset;
-		const u8 *back_start = (u8 *) (dev->backing_buffer
-						+ byte_offset);
-
-		*ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
-			&byte_width);
-
-		offset = next_pixel - line_start;
-		line_end = next_pixel + byte_width;
-		dev_addr += offset;
-		back_start += offset;
-		line_start += offset;
-
-		memcpy((char *)back_start, (char *) line_start,
-		       byte_width);
-	}
-
-	while (next_pixel < line_end) {
-
-		dlfb_compress_hline((const uint16_t **) &next_pixel,
-			     (const uint16_t *) line_end, &dev_addr,
-			(u8 **) &cmd, (u8 *) cmd_end);
-
-		if (cmd >= cmd_end) {
-			int len = cmd - (u8 *) urb->transfer_buffer;
-			if (dlfb_submit_urb(dev, urb, len))
-				return 1; /* lost pixels is set */
-			*sent_ptr += len;
-			urb = dlfb_get_urb(dev);
-			if (!urb)
-				return 1; /* lost_pixels is set */
-			*urb_ptr = urb;
-			cmd = urb->transfer_buffer;
-			cmd_end = &cmd[urb->transfer_buffer_length];
-		}
-	}
-
-	*urb_buf_ptr = cmd;
-
-	return 0;
-}
-
-int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
-	       int width, int height, char *data)
-{
-	int i, ret;
-	char *cmd;
-	cycles_t start_cycles, end_cycles;
-	int bytes_sent = 0;
-	int bytes_identical = 0;
-	struct urb *urb;
-	int aligned_x;
-
-	start_cycles = get_cycles();
-
-	aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
-	width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
-	x = aligned_x;
-
-	if ((width <= 0) ||
-	    (x + width > dev->info->var.xres) ||
-	    (y + height > dev->info->var.yres))
-		return -EINVAL;
-
-	if (!atomic_read(&dev->usb_active))
-		return 0;
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return 0;
-	cmd = urb->transfer_buffer;
-
-	for (i = y; i < y + height ; i++) {
-		const int line_offset = dev->info->fix.line_length * i;
-		const int byte_offset = line_offset + (x * BPP);
-
-		if (dlfb_render_hline(dev, &urb,
-				      (char *) dev->info->fix.smem_start,
-				      &cmd, byte_offset, width * BPP,
-				      &bytes_identical, &bytes_sent))
-			goto error;
-	}
-
-	if (cmd > (char *) urb->transfer_buffer) {
-		/* Send partial buffer remaining before exiting */
-		int len = cmd - (char *) urb->transfer_buffer;
-		ret = dlfb_submit_urb(dev, urb, len);
-		bytes_sent += len;
-	} else
-		dlfb_urb_completion(urb);
-
-error:
-	atomic_add(bytes_sent, &dev->bytes_sent);
-	atomic_add(bytes_identical, &dev->bytes_identical);
-	atomic_add(width*height*2, &dev->bytes_rendered);
-	end_cycles = get_cycles();
-	atomic_add(((unsigned int) ((end_cycles - start_cycles)
-		    >> 10)), /* Kcycles */
-		   &dev->cpu_kcycles_used);
-
-	return 0;
-}
-
-static ssize_t dlfb_ops_read(struct fb_info *info, char __user *buf,
-			 size_t count, loff_t *ppos)
-{
-	ssize_t result = -ENOSYS;
-
-#if defined CONFIG_FB_SYS_FOPS || defined CONFIG_FB_SYS_FOPS_MODULE
-	result = fb_sys_read(info, buf, count, ppos);
-#endif
-
-	return result;
-}
-
-/*
- * Path triggered by usermode clients who write to filesystem
- * e.g. cat filename > /dev/fb1
- * Not used by X Windows or text-mode console. But useful for testing.
- * Slow because of extra copy and we must assume all pixels dirty.
- */
-static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
-			  size_t count, loff_t *ppos)
-{
-	ssize_t result = -ENOSYS;
-	struct dlfb_data *dev = info->par;
-	u32 offset = (u32) *ppos;
-
-#if defined CONFIG_FB_SYS_FOPS || defined CONFIG_FB_SYS_FOPS_MODULE
-
-	result = fb_sys_write(info, buf, count, ppos);
-
-	if (result > 0) {
-		int start = max((int)(offset / info->fix.line_length) - 1, 0);
-		int lines = min((u32)((result / info->fix.line_length) + 1),
-				(u32)info->var.yres);
-
-		dlfb_handle_damage(dev, 0, start, info->var.xres,
-			lines, info->screen_base);
-	}
-#endif
-
-	return result;
-}
-
-/* hardware has native COPY command (see libdlo), but not worth it for fbcon */
-static void dlfb_ops_copyarea(struct fb_info *info,
-				const struct fb_copyarea *area)
-{
-
-	struct dlfb_data *dev = info->par;
-
-#if defined CONFIG_FB_SYS_COPYAREA || defined CONFIG_FB_SYS_COPYAREA_MODULE
-
-	sys_copyarea(info, area);
-
-	dlfb_handle_damage(dev, area->dx, area->dy,
-			area->width, area->height, info->screen_base);
-#endif
-
-}
-
-static void dlfb_ops_imageblit(struct fb_info *info,
-				const struct fb_image *image)
-{
-	struct dlfb_data *dev = info->par;
-
-#if defined CONFIG_FB_SYS_IMAGEBLIT || defined CONFIG_FB_SYS_IMAGEBLIT_MODULE
-
-	sys_imageblit(info, image);
-
-	dlfb_handle_damage(dev, image->dx, image->dy,
-			image->width, image->height, info->screen_base);
-
-#endif
-
-}
-
-static void dlfb_ops_fillrect(struct fb_info *info,
-			  const struct fb_fillrect *rect)
-{
-	struct dlfb_data *dev = info->par;
-
-#if defined CONFIG_FB_SYS_FILLRECT || defined CONFIG_FB_SYS_FILLRECT_MODULE
-
-	sys_fillrect(info, rect);
-
-	dlfb_handle_damage(dev, rect->dx, rect->dy, rect->width,
-			      rect->height, info->screen_base);
-#endif
-
-}
-
-#ifdef CONFIG_FB_DEFERRED_IO
-/*
- * NOTE: fb_defio.c is holding info->fbdefio.mutex
- *   Touching ANY framebuffer memory that triggers a page fault
- *   in fb_defio will cause a deadlock, when it also tries to
- *   grab the same mutex.
- */
-static void dlfb_dpy_deferred_io(struct fb_info *info,
-				struct list_head *pagelist)
-{
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct dlfb_data *dev = info->par;
-	struct urb *urb;
-	char *cmd;
-	cycles_t start_cycles, end_cycles;
-	int bytes_sent = 0;
-	int bytes_identical = 0;
-	int bytes_rendered = 0;
-
-	if (!fb_defio)
-		return;
-
-	if (!atomic_read(&dev->usb_active))
-		return;
-
-	start_cycles = get_cycles();
-
-	urb = dlfb_get_urb(dev);
-	if (!urb)
-		return;
-
-	cmd = urb->transfer_buffer;
-
-	/* walk the written page list and render each to device */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-
-		if (dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
-				  &cmd, cur->index << PAGE_SHIFT,
-				  PAGE_SIZE, &bytes_identical, &bytes_sent))
-			goto error;
-		bytes_rendered += PAGE_SIZE;
-	}
-
-	if (cmd > (char *) urb->transfer_buffer) {
-		/* Send partial buffer remaining before exiting */
-		int len = cmd - (char *) urb->transfer_buffer;
-		dlfb_submit_urb(dev, urb, len);
-		bytes_sent += len;
-	} else
-		dlfb_urb_completion(urb);
-
-error:
-	atomic_add(bytes_sent, &dev->bytes_sent);
-	atomic_add(bytes_identical, &dev->bytes_identical);
-	atomic_add(bytes_rendered, &dev->bytes_rendered);
-	end_cycles = get_cycles();
-	atomic_add(((unsigned int) ((end_cycles - start_cycles)
-		    >> 10)), /* Kcycles */
-		   &dev->cpu_kcycles_used);
-}
-
-#endif
-
-static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
-{
-	int i;
-	int ret;
-	char *rbuf;
-
-	rbuf = kmalloc(2, GFP_KERNEL);
-	if (!rbuf)
-		return 0;
-
-	for (i = 0; i < len; i++) {
-		ret = usb_control_msg(dev->udev,
-				    usb_rcvctrlpipe(dev->udev, 0), (0x02),
-				    (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
-				    HZ);
-		if (ret < 1) {
-			dl_err("Read EDID byte %d failed err %x\n", i, ret);
-			i--;
-			break;
-		}
-		edid[i] = rbuf[1];
-	}
-
-	kfree(rbuf);
-
-	return i;
-}
-
-static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
-				unsigned long arg)
-{
-
-	struct dlfb_data *dev = info->par;
-	struct dloarea *area = NULL;
-
-	if (!atomic_read(&dev->usb_active))
-		return 0;
-
-	/* TODO: Update X server to get this from sysfs instead */
-	if (cmd == DLFB_IOCTL_RETURN_EDID) {
-		char *edid = (char *)arg;
-		if (copy_to_user(edid, dev->edid, dev->edid_size))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
-	if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
-
-		/*
-		 * If we have a damage-aware client, turn fb_defio "off"
-		 * To avoid perf imact of unecessary page fault handling.
-		 * Done by resetting the delay for this fb_info to a very
-		 * long period. Pages will become writable and stay that way.
-		 * Reset to normal value when all clients have closed this fb.
-		 */
-		if (info->fbdefio)
-			info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
-
-		area = (struct dloarea *)arg;
-
-		if (area->x < 0)
-			area->x = 0;
-
-		if (area->x > info->var.xres)
-			area->x = info->var.xres;
-
-		if (area->y < 0)
-			area->y = 0;
-
-		if (area->y > info->var.yres)
-			area->y = info->var.yres;
-
-		dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
-			   info->screen_base);
-	}
-
-	return 0;
-}
-
-/* taken from vesafb */
-static int
-dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
-	       unsigned blue, unsigned transp, struct fb_info *info)
-{
-	int err = 0;
-
-	if (regno >= info->cmap.len)
-		return 1;
-
-	if (regno < 16) {
-		if (info->var.red.offset == 10) {
-			/* 1:5:5:5 */
-			((u32 *) (info->pseudo_palette))[regno] =
-			    ((red & 0xf800) >> 1) |
-			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
-		} else {
-			/* 0:5:6:5 */
-			((u32 *) (info->pseudo_palette))[regno] =
-			    ((red & 0xf800)) |
-			    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
-		}
-	}
-
-	return err;
-}
-
-/*
- * It's common for several clients to have framebuffer open simultaneously.
- * e.g. both fbcon and X. Makes things interesting.
- * Assumes caller is holding info->lock (for open and release at least)
- */
-static int dlfb_ops_open(struct fb_info *info, int user)
-{
-	struct dlfb_data *dev = info->par;
-
-	/*
-	 * fbcon aggressively connects to first framebuffer it finds,
-	 * preventing other clients (X) from working properly. Usually
-	 * not what the user wants. Fail by default with option to enable.
-	 */
-	if ((user == 0) & (!console))
-		return -EBUSY;
-
-	/* If the USB device is gone, we don't accept new opens */
-	if (dev->virtualized)
-		return -ENODEV;
-
-	dev->fb_count++;
-
-	kref_get(&dev->kref);
-
-#ifdef CONFIG_FB_DEFERRED_IO
-	if (fb_defio && (info->fbdefio == NULL)) {
-		/* enable defio at last moment if not disabled by client */
-
-		struct fb_deferred_io *fbdefio;
-
-		fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
-
-		if (fbdefio) {
-			fbdefio->delay = DL_DEFIO_WRITE_DELAY;
-			fbdefio->deferred_io = dlfb_dpy_deferred_io;
-		}
-
-		info->fbdefio = fbdefio;
-		fb_deferred_io_init(info);
-	}
-#endif
-
-	dl_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
-	    info->node, user, info, dev->fb_count);
-
-	return 0;
-}
-
-/*
- * Called when all client interfaces to start transactions have been disabled,
- * and all references to our device instance (dlfb_data) are released.
- * Every transaction must have a reference, so we know are fully spun down
- */
-static void dlfb_free(struct kref *kref)
-{
-	struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
-
-	/* this function will wait for all in-flight urbs to complete */
-	if (dev->urbs.count > 0)
-		dlfb_free_urb_list(dev);
-
-	if (dev->backing_buffer)
-		vfree(dev->backing_buffer);
-
-	kfree(dev->edid);
-
-	dl_warn("freeing dlfb_data %p\n", dev);
-
-	kfree(dev);
-}
-
-static void dlfb_release_urb_work(struct work_struct *work)
-{
-	struct urb_node *unode = container_of(work, struct urb_node,
-					      release_urb_work.work);
-
-	up(&unode->dev->urbs.limit_sem);
-}
-
-static void dlfb_free_framebuffer_work(struct work_struct *work)
-{
-	struct dlfb_data *dev = container_of(work, struct dlfb_data,
-					     free_framebuffer_work.work);
-	struct fb_info *info = dev->info;
-	int node = info->node;
-
-	unregister_framebuffer(info);
-
-	if (info->cmap.len != 0)
-		fb_dealloc_cmap(&info->cmap);
-	if (info->monspecs.modedb)
-		fb_destroy_modedb(info->monspecs.modedb);
-	if (info->screen_base)
-		vfree(info->screen_base);
-
-	fb_destroy_modelist(&info->modelist);
-
-	dev->info = 0;
-
-	/* Assume info structure is freed after this point */
-	framebuffer_release(info);
-
-	dl_warn("fb_info for /dev/fb%d has been freed\n", node);
-
-	/* ref taken in probe() as part of registering framebfufer */
-	kref_put(&dev->kref, dlfb_free);
-}
-
-/*
- * Assumes caller is holding info->lock mutex (for open and release at least)
- */
-static int dlfb_ops_release(struct fb_info *info, int user)
-{
-	struct dlfb_data *dev = info->par;
-
-	dev->fb_count--;
-
-	/* We can't free fb_info here - fbmem will touch it when we return */
-	if (dev->virtualized && (dev->fb_count == 0))
-		schedule_delayed_work(&dev->free_framebuffer_work, HZ);
-
-#ifdef CONFIG_FB_DEFERRED_IO
-	if ((dev->fb_count == 0) && (info->fbdefio)) {
-		fb_deferred_io_cleanup(info);
-		kfree(info->fbdefio);
-		info->fbdefio = NULL;
-		info->fbops->fb_mmap = dlfb_ops_mmap;
-	}
-#endif
-
-	dl_warn("released /dev/fb%d user=%d count=%d\n",
-		  info->node, user, dev->fb_count);
-
-	kref_put(&dev->kref, dlfb_free);
-
-	return 0;
-}
-
-/*
- * Check whether a video mode is supported by the DisplayLink chip
- * We start from monitor's modes, so don't need to filter that here
- */
-static int dlfb_is_valid_mode(struct fb_videomode *mode,
-		struct fb_info *info)
-{
-	struct dlfb_data *dev = info->par;
-
-	if (mode->xres * mode->yres > dev->sku_pixel_limit) {
-		dl_warn("%dx%d beyond chip capabilities\n",
-		       mode->xres, mode->yres);
-		return 0;
-	}
-
-	dl_info("%dx%d valid mode\n", mode->xres, mode->yres);
-
-	return 1;
-}
-
-static void dlfb_var_color_format(struct fb_var_screeninfo *var)
-{
-	const struct fb_bitfield red = { 11, 5, 0 };
-	const struct fb_bitfield green = { 5, 6, 0 };
-	const struct fb_bitfield blue = { 0, 5, 0 };
-
-	var->bits_per_pixel = 16;
-	var->red = red;
-	var->green = green;
-	var->blue = blue;
-}
-
-static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
-				struct fb_info *info)
-{
-	struct fb_videomode mode;
-
-	/* TODO: support dynamically changing framebuffer size */
-	if ((var->xres * var->yres * 2) > info->fix.smem_len)
-		return -EINVAL;
-
-	/* set device-specific elements of var unrelated to mode */
-	dlfb_var_color_format(var);
-
-	fb_var_to_videomode(&mode, var);
-
-	if (!dlfb_is_valid_mode(&mode, info))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int dlfb_ops_set_par(struct fb_info *info)
-{
-	struct dlfb_data *dev = info->par;
-	int result;
-	u16 *pix_framebuffer;
-	int i;
-
-	dl_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
-
-	result = dlfb_set_video_mode(dev, &info->var);
-
-	if ((result == 0) && (dev->fb_count == 0)) {
-
-		/* paint greenscreen */
-
-		pix_framebuffer = (u16 *) info->screen_base;
-		for (i = 0; i < info->fix.smem_len / 2; i++)
-			pix_framebuffer[i] = 0x37e6;
-
-		dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
-				   info->screen_base);
-	}
-
-	return result;
-}
-
-/*
- * In order to come back from full DPMS off, we need to set the mode again
- */
-static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
-{
-	struct dlfb_data *dev = info->par;
-
-	if (blank_mode != FB_BLANK_UNBLANK) {
-		char *bufptr;
-		struct urb *urb;
-
-		urb = dlfb_get_urb(dev);
-		if (!urb)
-			return 0;
-
-		bufptr = (char *) urb->transfer_buffer;
-		bufptr = dlfb_vidreg_lock(bufptr);
-		bufptr = dlfb_enable_hvsync(bufptr, false);
-		bufptr = dlfb_vidreg_unlock(bufptr);
-
-		dlfb_submit_urb(dev, urb, bufptr -
-				(char *) urb->transfer_buffer);
-	} else {
-		dlfb_set_video_mode(dev, &info->var);
-	}
-
-	return 0;
-}
-
-static struct fb_ops dlfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_read = dlfb_ops_read,
-	.fb_write = dlfb_ops_write,
-	.fb_setcolreg = dlfb_ops_setcolreg,
-	.fb_fillrect = dlfb_ops_fillrect,
-	.fb_copyarea = dlfb_ops_copyarea,
-	.fb_imageblit = dlfb_ops_imageblit,
-	.fb_mmap = dlfb_ops_mmap,
-	.fb_ioctl = dlfb_ops_ioctl,
-	.fb_open = dlfb_ops_open,
-	.fb_release = dlfb_ops_release,
-	.fb_blank = dlfb_ops_blank,
-	.fb_check_var = dlfb_ops_check_var,
-	.fb_set_par = dlfb_ops_set_par,
-};
-
-
-/*
- * Assumes &info->lock held by caller
- * Assumes no active clients have framebuffer open
- */
-static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
-{
-	int retval = -ENOMEM;
-	int old_len = info->fix.smem_len;
-	int new_len;
-	unsigned char *old_fb = info->screen_base;
-	unsigned char *new_fb;
-	unsigned char *new_back;
-
-	dl_warn("Reallocating framebuffer. Addresses will change!\n");
-
-	new_len = info->fix.line_length * info->var.yres;
-
-	if (PAGE_ALIGN(new_len) > old_len) {
-		/*
-		 * Alloc system memory for virtual framebuffer
-		 */
-		new_fb = vmalloc(new_len);
-		if (!new_fb) {
-			dl_err("Virtual framebuffer alloc failed\n");
-			goto error;
-		}
-
-		if (info->screen_base) {
-			memcpy(new_fb, old_fb, old_len);
-			vfree(info->screen_base);
-		}
-
-		info->screen_base = new_fb;
-		info->fix.smem_len = PAGE_ALIGN(new_len);
-		info->fix.smem_start = (unsigned long) new_fb;
-		info->flags = udlfb_info_flags;
-
-		/*
-		 * Second framebuffer copy to mirror the framebuffer state
-		 * on the physical USB device. We can function without this.
-		 * But with imperfect damage info we may send pixels over USB
-		 * that were, in fact, unchanged - wasting limited USB bandwidth
-		 */
-		new_back = vmalloc(new_len);
-		if (!new_back)
-			dl_info("No shadow/backing buffer allcoated\n");
-		else {
-			if (dev->backing_buffer)
-				vfree(dev->backing_buffer);
-			dev->backing_buffer = new_back;
-			memset(dev->backing_buffer, 0, new_len);
-		}
-	}
-
-	retval = 0;
-
-error:
-	return retval;
-}
-
-/*
- * 1) Get EDID from hw, or use sw default
- * 2) Parse into various fb_info structs
- * 3) Allocate virtual framebuffer memory to back highest res mode
- *
- * Parses EDID into three places used by various parts of fbdev:
- * fb_var_screeninfo contains the timing of the monitor's preferred mode
- * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
- * fb_info.modelist is a linked list of all monitor & VESA modes which work
- *
- * If EDID is not readable/valid, then modelist is all VESA modes,
- * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
- * Returns 0 if successful
- */
-static int dlfb_setup_modes(struct dlfb_data *dev,
-			   struct fb_info *info,
-			   char *default_edid, size_t default_edid_size)
-{
-	int i;
-	const struct fb_videomode *default_vmode = NULL;
-	int result = 0;
-	char *edid;
-	int tries = 3;
-
-	if (info->dev) /* only use mutex if info has been registered */
-		mutex_lock(&info->lock);
-
-	edid = kmalloc(MAX_EDID_SIZE, GFP_KERNEL);
-	if (!edid) {
-		result = -ENOMEM;
-		goto error;
-	}
-
-	fb_destroy_modelist(&info->modelist);
-	memset(&info->monspecs, 0, sizeof(info->monspecs));
-
-	/*
-	 * Try to (re)read EDID from hardware first
-	 * EDID data may return, but not parse as valid
-	 * Try again a few times, in case of e.g. analog cable noise
-	 */
-	while (tries--) {
-
-		i = dlfb_get_edid(dev, edid, MAX_EDID_SIZE);
-
-		if (i >= MIN_EDID_SIZE)
-			fb_edid_to_monspecs(edid, &info->monspecs);
-
-		if (info->monspecs.modedb_len > 0) {
-			dev->edid = edid;
-			dev->edid_size = i;
-			break;
-		}
-	}
-
-	/* If that fails, use a previously returned EDID if available */
-	if (info->monspecs.modedb_len == 0) {
-
-		dl_err("Unable to get valid EDID from device/display\n");
-
-		if (dev->edid) {
-			fb_edid_to_monspecs(dev->edid, &info->monspecs);
-			if (info->monspecs.modedb_len > 0)
-				dl_err("Using previously queried EDID\n");
-		}
-	}
-
-	/* If that fails, use the default EDID we were handed */
-	if (info->monspecs.modedb_len == 0) {
-		if (default_edid_size >= MIN_EDID_SIZE) {
-			fb_edid_to_monspecs(default_edid, &info->monspecs);
-			if (info->monspecs.modedb_len > 0) {
-				memcpy(edid, default_edid, default_edid_size);
-				dev->edid = edid;
-				dev->edid_size = default_edid_size;
-				dl_err("Using default/backup EDID\n");
-			}
-		}
-	}
-
-	/* If we've got modes, let's pick a best default mode */
-	if (info->monspecs.modedb_len > 0) {
-
-		for (i = 0; i < info->monspecs.modedb_len; i++) {
-			if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info))
-				fb_add_videomode(&info->monspecs.modedb[i],
-					&info->modelist);
-			else /* if we've removed top/best mode */
-				info->monspecs.misc &= ~FB_MISC_1ST_DETAIL;
-		}
-
-		default_vmode = fb_find_best_display(&info->monspecs,
-						     &info->modelist);
-	}
-
-	/* If everything else has failed, fall back to safe default mode */
-	if (default_vmode == NULL) {
-
-		struct fb_videomode fb_vmode = {0};
-
-		/*
-		 * Add the standard VESA modes to our modelist
-		 * Since we don't have EDID, there may be modes that
-		 * overspec monitor and/or are incorrect aspect ratio, etc.
-		 * But at least the user has a chance to choose
-		 */
-		for (i = 0; i < VESA_MODEDB_SIZE; i++) {
-			if (dlfb_is_valid_mode((struct fb_videomode *)
-						&vesa_modes[i], info))
-				fb_add_videomode(&vesa_modes[i],
-						 &info->modelist);
-		}
-
-		/*
-		 * default to resolution safe for projectors
-		 * (since they are most common case without EDID)
-		 */
-		fb_vmode.xres = 800;
-		fb_vmode.yres = 600;
-		fb_vmode.refresh = 60;
-		default_vmode = fb_find_nearest_mode(&fb_vmode,
-						     &info->modelist);
-	}
-
-	/* If we have good mode and no active clients*/
-	if ((default_vmode != NULL) && (dev->fb_count == 0)) {
-
-		fb_videomode_to_var(&info->var, default_vmode);
-		dlfb_var_color_format(&info->var);
-
-		/*
-		 * with mode size info, we can now alloc our framebuffer.
-		 */
-		memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
-		info->fix.line_length = info->var.xres *
-			(info->var.bits_per_pixel / 8);
-
-		result = dlfb_realloc_framebuffer(dev, info);
-
-	} else
-		result = -EINVAL;
-
-error:
-	if (edid && (dev->edid != edid))
-		kfree(edid);
-
-	if (info->dev)
-		mutex_unlock(&info->lock);
-
-	return result;
-}
-
-static ssize_t metrics_bytes_rendered_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->bytes_rendered));
-}
-
-static ssize_t metrics_bytes_identical_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->bytes_identical));
-}
-
-static ssize_t metrics_bytes_sent_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->bytes_sent));
-}
-
-static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
-				   struct device_attribute *a, char *buf) {
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			atomic_read(&dev->cpu_kcycles_used));
-}
-
-static ssize_t edid_show(
-			struct file *filp,
-			struct kobject *kobj, struct bin_attribute *a,
-			 char *buf, loff_t off, size_t count) {
-	struct device *fbdev = container_of(kobj, struct device, kobj);
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-
-	if (dev->edid == NULL)
-		return 0;
-
-	if ((off >= dev->edid_size) || (count > dev->edid_size))
-		return 0;
-
-	if (off + count > dev->edid_size)
-		count = dev->edid_size - off;
-
-	dl_info("sysfs edid copy %p to %p, %d bytes\n",
-		dev->edid, buf, (int) count);
-
-	memcpy(buf, dev->edid, count);
-
-	return count;
-}
-
-static ssize_t edid_store(
-			struct file *filp,
-			struct kobject *kobj, struct bin_attribute *a,
-			char *src, loff_t src_off, size_t src_size) {
-	struct device *fbdev = container_of(kobj, struct device, kobj);
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-
-	/* We only support write of entire EDID at once, no offset*/
-	if ((src_size < MIN_EDID_SIZE) ||
-	    (src_size > MAX_EDID_SIZE) ||
-	    (src_off != 0))
-		return 0;
-
-	dlfb_setup_modes(dev, fb_info, src, src_size);
-
-	if (dev->edid && (memcmp(src, dev->edid, src_size) == 0)) {
-		dl_info("sysfs written EDID is new default\n");
-		dlfb_ops_set_par(fb_info);
-		return src_size;
-	} else
-		return 0;
-}
-
-static ssize_t metrics_reset_store(struct device *fbdev,
-			   struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct fb_info *fb_info = dev_get_drvdata(fbdev);
-	struct dlfb_data *dev = fb_info->par;
-
-	atomic_set(&dev->bytes_rendered, 0);
-	atomic_set(&dev->bytes_identical, 0);
-	atomic_set(&dev->bytes_sent, 0);
-	atomic_set(&dev->cpu_kcycles_used, 0);
-
-	return count;
-}
-
-static struct bin_attribute edid_attr = {
-	.attr.name = "edid",
-	.attr.mode = 0666,
-	.size = MAX_EDID_SIZE,
-	.read = edid_show,
-	.write = edid_store
-};
-
-static struct device_attribute fb_device_attrs[] = {
-	__ATTR_RO(metrics_bytes_rendered),
-	__ATTR_RO(metrics_bytes_identical),
-	__ATTR_RO(metrics_bytes_sent),
-	__ATTR_RO(metrics_cpu_kcycles_used),
-	__ATTR(metrics_reset, S_IWUSR, NULL, metrics_reset_store),
-};
-
-/*
- * This is necessary before we can communicate with the display controller.
- */
-static int dlfb_select_std_channel(struct dlfb_data *dev)
-{
-	int ret;
-	u8 set_def_chn[] = {	   0x57, 0xCD, 0xDC, 0xA7,
-				0x1C, 0x88, 0x5E, 0x15,
-				0x60, 0xFE, 0xC6, 0x97,
-				0x16, 0x3D, 0x47, 0xF2  };
-
-	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-			NR_USB_REQUEST_CHANNEL,
-			(USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
-			set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
-	return ret;
-}
-
-static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
-					struct usb_device *usbdev)
-{
-	char *desc;
-	char *buf;
-	char *desc_end;
-
-	u8 total_len = 0;
-
-	buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
-	if (!buf)
-		return false;
-	desc = buf;
-
-	total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
-				    0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
-	if (total_len > 5) {
-		dl_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
-			"%02x %02x %02x %02x %02x %02x %02x\n",
-			total_len, desc[0],
-			desc[1], desc[2], desc[3], desc[4], desc[5], desc[6],
-			desc[7], desc[8], desc[9], desc[10]);
-
-		if ((desc[0] != total_len) || /* descriptor length */
-		    (desc[1] != 0x5f) ||   /* vendor descriptor type */
-		    (desc[2] != 0x01) ||   /* version (2 bytes) */
-		    (desc[3] != 0x00) ||
-		    (desc[4] != total_len - 2)) /* length after type */
-			goto unrecognized;
-
-		desc_end = desc + total_len;
-		desc += 5; /* the fixed header we've already parsed */
-
-		while (desc < desc_end) {
-			u8 length;
-			u16 key;
-
-			key = *((u16 *) desc);
-			desc += sizeof(u16);
-			length = *desc;
-			desc++;
-
-			switch (key) {
-			case 0x0200: { /* max_area */
-				u32 max_area;
-				max_area = le32_to_cpu(*((u32 *)desc));
-				dl_warn("DL chip limited to %d pixel modes\n",
-					max_area);
-				dev->sku_pixel_limit = max_area;
-				break;
-			}
-			default:
-				break;
-			}
-			desc += length;
-		}
-	}
-
-	goto success;
-
-unrecognized:
-	/* allow udlfb to load for now even if firmware unrecognized */
-	dl_err("Unrecognized vendor firmware descriptor\n");
-
-success:
-	kfree(buf);
-	return true;
-}
-static int dlfb_usb_probe(struct usb_interface *interface,
-			const struct usb_device_id *id)
-{
-	struct usb_device *usbdev;
-	struct dlfb_data *dev = 0;
-	struct fb_info *info = 0;
-	int retval = -ENOMEM;
-	int i;
-
-	/* usb initialization */
-
-	usbdev = interface_to_usbdev(interface);
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (dev == NULL) {
-		err("dlfb_usb_probe: failed alloc of dev struct\n");
-		goto error;
-	}
-
-	/* we need to wait for both usb and fbdev to spin down on disconnect */
-	kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
-	kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
-
-	dev->udev = usbdev;
-	dev->gdev = &usbdev->dev; /* our generic struct device * */
-	usb_set_intfdata(interface, dev);
-
-	dl_info("%s %s - serial #%s\n",
-		usbdev->manufacturer, usbdev->product, usbdev->serial);
-	dl_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
-		usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-		usbdev->descriptor.bcdDevice, dev);
-	dl_info("console enable=%d\n", console);
-	dl_info("fb_defio enable=%d\n", fb_defio);
-
-	dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
-
-	if (!dlfb_parse_vendor_descriptor(dev, usbdev)) {
-		dl_err("firmware not recognized. Assume incompatible device\n");
-		goto error;
-	}
-
-	if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
-		retval = -ENOMEM;
-		dl_err("dlfb_alloc_urb_list failed\n");
-		goto error;
-	}
-
-	/* We don't register a new USB class. Our client interface is fbdev */
-
-	/* allocates framebuffer driver structure, not framebuffer memory */
-	info = framebuffer_alloc(0, &usbdev->dev);
-	if (!info) {
-		retval = -ENOMEM;
-		dl_err("framebuffer_alloc failed\n");
-		goto error;
-	}
-
-	dev->info = info;
-	info->par = dev;
-	info->pseudo_palette = dev->pseudo_palette;
-	info->fbops = &dlfb_ops;
-
-	retval = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (retval < 0) {
-		dl_err("fb_alloc_cmap failed %x\n", retval);
-		goto error;
-	}
-
-	INIT_DELAYED_WORK(&dev->free_framebuffer_work,
-			  dlfb_free_framebuffer_work);
-
-	INIT_LIST_HEAD(&info->modelist);
-
-	retval = dlfb_setup_modes(dev, info, NULL, 0);
-	if (retval != 0) {
-		dl_err("unable to find common mode for display and adapter\n");
-		goto error;
-	}
-
-	/* ready to begin using device */
-
-	atomic_set(&dev->usb_active, 1);
-	dlfb_select_std_channel(dev);
-
-	dlfb_ops_check_var(&info->var, info);
-	dlfb_ops_set_par(info);
-
-	retval = register_framebuffer(info);
-	if (retval < 0) {
-		dl_err("register_framebuffer failed %d\n", retval);
-		goto error;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
-		device_create_file(info->dev, &fb_device_attrs[i]);
-
-	device_create_bin_file(info->dev, &edid_attr);
-
-	dl_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
-			" Using %dK framebuffer memory\n", info->node,
-			info->var.xres, info->var.yres,
-			((dev->backing_buffer) ?
-			info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
-	return 0;
-
-error:
-	if (dev) {
-
-		if (info) {
-			if (info->cmap.len != 0)
-				fb_dealloc_cmap(&info->cmap);
-			if (info->monspecs.modedb)
-				fb_destroy_modedb(info->monspecs.modedb);
-			if (info->screen_base)
-				vfree(info->screen_base);
-
-			fb_destroy_modelist(&info->modelist);
-
-			framebuffer_release(info);
-		}
-
-		if (dev->backing_buffer)
-			vfree(dev->backing_buffer);
-
-		kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
-		kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
-
-		/* dev has been deallocated. Do not dereference */
-	}
-
-	return retval;
-}
-
-static void dlfb_usb_disconnect(struct usb_interface *interface)
-{
-	struct dlfb_data *dev;
-	struct fb_info *info;
-	int i;
-
-	dev = usb_get_intfdata(interface);
-	info = dev->info;
-
-	dl_info("USB disconnect starting\n");
-
-	/* we virtualize until all fb clients release. Then we free */
-	dev->virtualized = true;
-
-	/* When non-active we'll update virtual framebuffer, but no new urbs */
-	atomic_set(&dev->usb_active, 0);
-
-	/* remove udlfb's sysfs interfaces */
-	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
-		device_remove_file(info->dev, &fb_device_attrs[i]);
-	device_remove_bin_file(info->dev, &edid_attr);
-
-	usb_set_intfdata(interface, NULL);
-
-	/* if clients still have us open, will be freed on last close */
-	if (dev->fb_count == 0)
-		schedule_delayed_work(&dev->free_framebuffer_work, 0);
-
-	/* release reference taken by kref_init in probe() */
-	kref_put(&dev->kref, dlfb_free);
-
-	/* consider dlfb_data freed */
-
-	return;
-}
-
-static struct usb_driver dlfb_driver = {
-	.name = "udlfb",
-	.probe = dlfb_usb_probe,
-	.disconnect = dlfb_usb_disconnect,
-	.id_table = id_table,
-};
-
-static int __init dlfb_module_init(void)
-{
-	int res;
-
-	res = usb_register(&dlfb_driver);
-	if (res)
-		err("usb_register failed. Error number %d", res);
-
-	return res;
-}
-
-static void __exit dlfb_module_exit(void)
-{
-	usb_deregister(&dlfb_driver);
-}
-
-module_init(dlfb_module_init);
-module_exit(dlfb_module_exit);
-
-static void dlfb_urb_completion(struct urb *urb)
-{
-	struct urb_node *unode = urb->context;
-	struct dlfb_data *dev = unode->dev;
-	unsigned long flags;
-
-	/* sync/async unlink faults aren't errors */
-	if (urb->status) {
-		if (!(urb->status == -ENOENT ||
-		    urb->status == -ECONNRESET ||
-		    urb->status == -ESHUTDOWN)) {
-			dl_err("%s - nonzero write bulk status received: %d\n",
-				__func__, urb->status);
-			atomic_set(&dev->lost_pixels, 1);
-		}
-	}
-
-	urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
-
-	spin_lock_irqsave(&dev->urbs.lock, flags);
-	list_add_tail(&unode->entry, &dev->urbs.list);
-	dev->urbs.available++;
-	spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-	/*
-	 * When using fb_defio, we deadlock if up() is called
-	 * while another is waiting. So queue to another process.
-	 */
-	if (fb_defio)
-		schedule_delayed_work(&unode->release_urb_work, 0);
-	else
-		up(&dev->urbs.limit_sem);
-}
-
-static void dlfb_free_urb_list(struct dlfb_data *dev)
-{
-	int count = dev->urbs.count;
-	struct list_head *node;
-	struct urb_node *unode;
-	struct urb *urb;
-	int ret;
-	unsigned long flags;
-
-	dl_notice("Waiting for completes and freeing all render urbs\n");
-
-	/* keep waiting and freeing, until we've got 'em all */
-	while (count--) {
-
-		/* Getting interrupted means a leak, but ok at shutdown*/
-		ret = down_interruptible(&dev->urbs.limit_sem);
-		if (ret)
-			break;
-
-		spin_lock_irqsave(&dev->urbs.lock, flags);
-
-		node = dev->urbs.list.next; /* have reserved one with sem */
-		list_del_init(node);
-
-		spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-		unode = list_entry(node, struct urb_node, entry);
-		urb = unode->urb;
-
-		/* Free each separately allocated piece */
-		usb_free_coherent(urb->dev, dev->urbs.size,
-				  urb->transfer_buffer, urb->transfer_dma);
-		usb_free_urb(urb);
-		kfree(node);
-	}
-
-}
-
-static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
-{
-	int i = 0;
-	struct urb *urb;
-	struct urb_node *unode;
-	char *buf;
-
-	spin_lock_init(&dev->urbs.lock);
-
-	dev->urbs.size = size;
-	INIT_LIST_HEAD(&dev->urbs.list);
-
-	while (i < count) {
-		unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
-		if (!unode)
-			break;
-		unode->dev = dev;
-
-		INIT_DELAYED_WORK(&unode->release_urb_work,
-			  dlfb_release_urb_work);
-
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb) {
-			kfree(unode);
-			break;
-		}
-		unode->urb = urb;
-
-		buf = usb_alloc_coherent(dev->udev, MAX_TRANSFER, GFP_KERNEL,
-					 &urb->transfer_dma);
-		if (!buf) {
-			kfree(unode);
-			usb_free_urb(urb);
-			break;
-		}
-
-		/* urb->transfer_buffer_length set to actual before submit */
-		usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
-			buf, size, dlfb_urb_completion, unode);
-		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-		list_add_tail(&unode->entry, &dev->urbs.list);
-
-		i++;
-	}
-
-	sema_init(&dev->urbs.limit_sem, i);
-	dev->urbs.count = i;
-	dev->urbs.available = i;
-
-	dl_notice("allocated %d %d byte urbs\n", i, (int) size);
-
-	return i;
-}
-
-static struct urb *dlfb_get_urb(struct dlfb_data *dev)
-{
-	int ret = 0;
-	struct list_head *entry;
-	struct urb_node *unode;
-	struct urb *urb = NULL;
-	unsigned long flags;
-
-	/* Wait for an in-flight buffer to complete and get re-queued */
-	ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
-	if (ret) {
-		atomic_set(&dev->lost_pixels, 1);
-		dl_warn("wait for urb interrupted: %x available: %d\n",
-		       ret, dev->urbs.available);
-		goto error;
-	}
-
-	spin_lock_irqsave(&dev->urbs.lock, flags);
-
-	BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
-	entry = dev->urbs.list.next;
-	list_del_init(entry);
-	dev->urbs.available--;
-
-	spin_unlock_irqrestore(&dev->urbs.lock, flags);
-
-	unode = list_entry(entry, struct urb_node, entry);
-	urb = unode->urb;
-
-error:
-	return urb;
-}
-
-static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
-{
-	int ret;
-
-	BUG_ON(len > dev->urbs.size);
-
-	urb->transfer_buffer_length = len; /* set to actual payload len */
-	ret = usb_submit_urb(urb, GFP_KERNEL);
-	if (ret) {
-		dlfb_urb_completion(urb); /* because no one else will */
-		atomic_set(&dev->lost_pixels, 1);
-		dl_err("usb_submit_urb error %x\n", ret);
-	}
-	return ret;
-}
-
-module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found");
-
-module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*");
-
-MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
-	      "Jaya Kumar <jayakumar.lkml@gmail.com>, "
-	      "Bernie Thompson <bernie@plugable.com>");
-MODULE_DESCRIPTION("DisplayLink kernel framebuffer driver");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
deleted file mode 100644
index 6f9785e..0000000
--- a/drivers/staging/udlfb/udlfb.h
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef UDLFB_H
-#define UDLFB_H
-
-/*
- * TODO: Propose standard fb.h ioctl for reporting damage,
- * using _IOWR() and one of the existing area structs from fb.h
- * Consider these ioctls deprecated, but they're still used by the
- * DisplayLink X server as yet - need both to be modified in tandem
- * when new ioctl(s) are ready.
- */
-#define DLFB_IOCTL_RETURN_EDID	 0xAD
-#define DLFB_IOCTL_REPORT_DAMAGE 0xAA
-struct dloarea {
-	int x, y;
-	int w, h;
-	int x2, y2;
-};
-
-struct urb_node {
-	struct list_head entry;
-	struct dlfb_data *dev;
-	struct delayed_work release_urb_work;
-	struct urb *urb;
-};
-
-struct urb_list {
-	struct list_head list;
-	spinlock_t lock;
-	struct semaphore limit_sem;
-	int available;
-	int count;
-	size_t size;
-};
-
-struct dlfb_data {
-	struct usb_device *udev;
-	struct device *gdev; /* &udev->dev */
-	struct fb_info *info;
-	struct urb_list urbs;
-	struct kref kref;
-	char *backing_buffer;
-	int fb_count;
-	bool virtualized; /* true when physical usb device not present */
-	struct delayed_work free_framebuffer_work;
-	atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
-	atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
-	char *edid; /* null until we read edid from hw or get from sysfs */
-	size_t edid_size;
-	int sku_pixel_limit;
-	int base16;
-	int base8;
-	u32 pseudo_palette[256];
-	/* blit-only rendering path metrics, exposed through sysfs */
-	atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
-	atomic_t bytes_identical; /* saved effort with backbuffer comparison */
-	atomic_t bytes_sent; /* to usb, after compression including overhead */
-	atomic_t cpu_kcycles_used; /* transpired during pixel processing */
-};
-
-#define NR_USB_REQUEST_I2C_SUB_IO 0x02
-#define NR_USB_REQUEST_CHANNEL 0x12
-
-/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
-#define BULK_SIZE 512
-#define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
-#define WRITES_IN_FLIGHT (4)
-
-#define MIN_EDID_SIZE 128
-#define MAX_EDID_SIZE 128
-
-#define MAX_VENDOR_DESCRIPTOR_SIZE 256
-
-#define GET_URB_TIMEOUT	HZ
-#define FREE_URB_TIMEOUT (HZ*2)
-
-#define BPP                     2
-#define MAX_CMD_PIXELS		255
-
-#define RLX_HEADER_BYTES	7
-#define MIN_RLX_PIX_BYTES       4
-#define MIN_RLX_CMD_BYTES	(RLX_HEADER_BYTES + MIN_RLX_PIX_BYTES)
-
-#define RLE_HEADER_BYTES	6
-#define MIN_RLE_PIX_BYTES	3
-#define MIN_RLE_CMD_BYTES	(RLE_HEADER_BYTES + MIN_RLE_PIX_BYTES)
-
-#define RAW_HEADER_BYTES	6
-#define MIN_RAW_PIX_BYTES	2
-#define MIN_RAW_CMD_BYTES	(RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES)
-
-#define DL_DEFIO_WRITE_DELAY    5 /* fb_deferred_io.delay in jiffies */
-#define DL_DEFIO_WRITE_DISABLE  (HZ*60) /* "disable" with long delay */
-
-/* remove these once align.h patch is taken into kernel */
-#define DL_ALIGN_UP(x, a) ALIGN(x, a)
-#define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a)
-
-/* remove once this gets added to sysfs.h */
-#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
-
-/*
- * udlfb is both a usb device, and a framebuffer device.
- * They may exist at the same time, but during various stages
- * inactivity, teardown, or "virtual" operation, only one or the
- * other will exist (one will outlive the other).  So we can't
- * call the dev_*() macros, because we don't have a stable dev object.
- */
-#define dl_err(format, arg...) \
-	pr_err("udlfb: " format, ## arg)
-#define dl_warn(format, arg...) \
-	pr_warning("udlfb: " format, ## arg)
-#define dl_notice(format, arg...) \
-	pr_notice("udlfb: " format, ## arg)
-#define dl_info(format, arg...) \
-	pr_info("udlfb: " format, ## arg)
-
-#endif
diff --git a/drivers/staging/usbvideo/Kconfig b/drivers/staging/usbvideo/Kconfig
new file mode 100644
index 0000000..566d659
--- /dev/null
+++ b/drivers/staging/usbvideo/Kconfig
@@ -0,0 +1,15 @@
+config VIDEO_USBVIDEO
+	tristate
+
+config USB_VICAM
+	tristate "USB 3com HomeConnect (aka vicam) support (DEPRECATED)"
+	depends on VIDEO_DEV && VIDEO_V4L2_COMMON && USB
+	select VIDEO_USBVIDEO
+	---help---
+	  Say Y here if you have 3com homeconnect camera (vicam).
+
+	  This driver uses the deprecated V4L1 API and will be removed in
+	  2.6.39, unless someone converts it to the V4L2 API.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vicam.
diff --git a/drivers/staging/usbvideo/Makefile b/drivers/staging/usbvideo/Makefile
new file mode 100644
index 0000000..3c99a9a
--- /dev/null
+++ b/drivers/staging/usbvideo/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VIDEO_USBVIDEO)    += usbvideo.o
+obj-$(CONFIG_USB_VICAM)         += vicam.o
diff --git a/drivers/staging/usbvideo/TODO b/drivers/staging/usbvideo/TODO
new file mode 100644
index 0000000..3b2c038
--- /dev/null
+++ b/drivers/staging/usbvideo/TODO
@@ -0,0 +1,5 @@
+This is an obsolete driver for some old webcams that still use V4L1 API. 
+As V4L1 support is being removed from kernel, if nobody take care on it, 
+the driver will be removed for 2.6.39.
+
+Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/staging/usbvideo/usbvideo.c
similarity index 100%
rename from drivers/media/video/usbvideo/usbvideo.c
rename to drivers/staging/usbvideo/usbvideo.c
diff --git a/drivers/staging/usbvideo/usbvideo.h b/drivers/staging/usbvideo/usbvideo.h
new file mode 100644
index 0000000..95638a0
--- /dev/null
+++ b/drivers/staging/usbvideo/usbvideo.h
@@ -0,0 +1,395 @@
+/*
+ * This program is free software; you can redistribute 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 "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 --git a/drivers/staging/usbvideo/vicam.c b/drivers/staging/usbvideo/vicam.c
new file mode 100644
index 0000000..ecdb121
--- /dev/null
+++ b/drivers/staging/usbvideo/vicam.c
@@ -0,0 +1,952 @@
+/*
+ * 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 "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 = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev);
+	if (err) {
+		printk(KERN_ERR "Failed to load \"vicam/firmware.fw\": %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");
+MODULE_FIRMWARE("vicam/firmware.fw");
diff --git a/drivers/staging/usbvideo/videodev.h b/drivers/staging/usbvideo/videodev.h
new file mode 100644
index 0000000..f11efbe
--- /dev/null
+++ b/drivers/staging/usbvideo/videodev.h
@@ -0,0 +1,318 @@
+/*
+ *	Video for Linux version 1 - OBSOLETE
+ *
+ *	Header file for v4l1 drivers and applications, for
+ *	Linux kernels 2.2.x or 2.4.x.
+ *
+ *	Provides header for legacy drivers and applications
+ *
+ *	See http://linuxtv.org for more info
+ *
+ */
+#ifndef __LINUX_VIDEODEV_H
+#define __LINUX_VIDEODEV_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/videodev2.h>
+
+#define VID_TYPE_CAPTURE	1	/* Can capture */
+#define VID_TYPE_TUNER		2	/* Can tune */
+#define VID_TYPE_TELETEXT	4	/* Does teletext */
+#define VID_TYPE_OVERLAY	8	/* Overlay onto frame buffer */
+#define VID_TYPE_CHROMAKEY	16	/* Overlay by chromakey */
+#define VID_TYPE_CLIPPING	32	/* Can clip */
+#define VID_TYPE_FRAMERAM	64	/* Uses the frame buffer memory */
+#define VID_TYPE_SCALES		128	/* Scalable */
+#define VID_TYPE_MONOCHROME	256	/* Monochrome only */
+#define VID_TYPE_SUBCAPTURE	512	/* Can capture subareas of the image */
+#define VID_TYPE_MPEG_DECODER	1024	/* Can decode MPEG streams */
+#define VID_TYPE_MPEG_ENCODER	2048	/* Can encode MPEG streams */
+#define VID_TYPE_MJPEG_DECODER	4096	/* Can decode MJPEG streams */
+#define VID_TYPE_MJPEG_ENCODER	8192	/* Can encode MJPEG streams */
+
+struct video_capability
+{
+	char name[32];
+	int type;
+	int channels;	/* Num channels */
+	int audios;	/* Num audio devices */
+	int maxwidth;	/* Supported width */
+	int maxheight;	/* And height */
+	int minwidth;	/* Supported width */
+	int minheight;	/* And height */
+};
+
+
+struct video_channel
+{
+	int channel;
+	char name[32];
+	int tuners;
+	__u32  flags;
+#define VIDEO_VC_TUNER		1	/* Channel has a tuner */
+#define VIDEO_VC_AUDIO		2	/* Channel has audio */
+	__u16  type;
+#define VIDEO_TYPE_TV		1
+#define VIDEO_TYPE_CAMERA	2
+	__u16 norm;			/* Norm set by channel */
+};
+
+struct video_tuner
+{
+	int tuner;
+	char name[32];
+	unsigned long rangelow, rangehigh;	/* Tuner range */
+	__u32 flags;
+#define VIDEO_TUNER_PAL		1
+#define VIDEO_TUNER_NTSC	2
+#define VIDEO_TUNER_SECAM	4
+#define VIDEO_TUNER_LOW		8	/* Uses KHz not MHz */
+#define VIDEO_TUNER_NORM	16	/* Tuner can set norm */
+#define VIDEO_TUNER_STEREO_ON	128	/* Tuner is seeing stereo */
+#define VIDEO_TUNER_RDS_ON      256     /* Tuner is seeing an RDS datastream */
+#define VIDEO_TUNER_MBS_ON      512     /* Tuner is seeing an MBS datastream */
+	__u16 mode;			/* PAL/NTSC/SECAM/OTHER */
+#define VIDEO_MODE_PAL		0
+#define VIDEO_MODE_NTSC		1
+#define VIDEO_MODE_SECAM	2
+#define VIDEO_MODE_AUTO		3
+	__u16 signal;			/* Signal strength 16bit scale */
+};
+
+struct video_picture
+{
+	__u16	brightness;
+	__u16	hue;
+	__u16	colour;
+	__u16	contrast;
+	__u16	whiteness;	/* Black and white only */
+	__u16	depth;		/* Capture depth */
+	__u16   palette;	/* Palette in use */
+#define VIDEO_PALETTE_GREY	1	/* Linear greyscale */
+#define VIDEO_PALETTE_HI240	2	/* High 240 cube (BT848) */
+#define VIDEO_PALETTE_RGB565	3	/* 565 16 bit RGB */
+#define VIDEO_PALETTE_RGB24	4	/* 24bit RGB */
+#define VIDEO_PALETTE_RGB32	5	/* 32bit RGB */
+#define VIDEO_PALETTE_RGB555	6	/* 555 15bit RGB */
+#define VIDEO_PALETTE_YUV422	7	/* YUV422 capture */
+#define VIDEO_PALETTE_YUYV	8
+#define VIDEO_PALETTE_UYVY	9	/* The great thing about standards is ... */
+#define VIDEO_PALETTE_YUV420	10
+#define VIDEO_PALETTE_YUV411	11	/* YUV411 capture */
+#define VIDEO_PALETTE_RAW	12	/* RAW capture (BT848) */
+#define VIDEO_PALETTE_YUV422P	13	/* YUV 4:2:2 Planar */
+#define VIDEO_PALETTE_YUV411P	14	/* YUV 4:1:1 Planar */
+#define VIDEO_PALETTE_YUV420P	15	/* YUV 4:2:0 Planar */
+#define VIDEO_PALETTE_YUV410P	16	/* YUV 4:1:0 Planar */
+#define VIDEO_PALETTE_PLANAR	13	/* start of planar entries */
+#define VIDEO_PALETTE_COMPONENT 7	/* start of component entries */
+};
+
+struct video_audio
+{
+	int	audio;		/* Audio channel */
+	__u16	volume;		/* If settable */
+	__u16	bass, treble;
+	__u32	flags;
+#define VIDEO_AUDIO_MUTE	1
+#define VIDEO_AUDIO_MUTABLE	2
+#define VIDEO_AUDIO_VOLUME	4
+#define VIDEO_AUDIO_BASS	8
+#define VIDEO_AUDIO_TREBLE	16
+#define VIDEO_AUDIO_BALANCE	32
+	char    name[16];
+#define VIDEO_SOUND_MONO	1
+#define VIDEO_SOUND_STEREO	2
+#define VIDEO_SOUND_LANG1	4
+#define VIDEO_SOUND_LANG2	8
+	__u16   mode;
+	__u16	balance;	/* Stereo balance */
+	__u16	step;		/* Step actual volume uses */
+};
+
+struct video_clip
+{
+	__s32	x,y;
+	__s32	width, height;
+	struct	video_clip *next;	/* For user use/driver use only */
+};
+
+struct video_window
+{
+	__u32	x,y;			/* Position of window */
+	__u32	width,height;		/* Its size */
+	__u32	chromakey;
+	__u32	flags;
+	struct	video_clip __user *clips;	/* Set only */
+	int	clipcount;
+#define VIDEO_WINDOW_INTERLACE	1
+#define VIDEO_WINDOW_CHROMAKEY	16	/* Overlay by chromakey */
+#define VIDEO_CLIP_BITMAP	-1
+/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
+#define VIDEO_CLIPMAP_SIZE	(128 * 625)
+};
+
+struct video_capture
+{
+	__u32 	x,y;			/* Offsets into image */
+	__u32	width, height;		/* Area to capture */
+	__u16	decimation;		/* Decimation divider */
+	__u16	flags;			/* Flags for capture */
+#define VIDEO_CAPTURE_ODD		0	/* Temporal */
+#define VIDEO_CAPTURE_EVEN		1
+};
+
+struct video_buffer
+{
+	void	*base;
+	int	height,width;
+	int	depth;
+	int	bytesperline;
+};
+
+struct video_mmap
+{
+	unsigned	int frame;		/* Frame (0 - n) for double buffer */
+	int		height,width;
+	unsigned	int format;		/* should be VIDEO_PALETTE_* */
+};
+
+struct video_key
+{
+	__u8	key[8];
+	__u32	flags;
+};
+
+struct video_mbuf
+{
+	int	size;		/* Total memory to map */
+	int	frames;		/* Frames */
+	int	offsets[VIDEO_MAX_FRAME];
+};
+
+#define 	VIDEO_NO_UNIT	(-1)
+
+struct video_unit
+{
+	int 	video;		/* Video minor */
+	int	vbi;		/* VBI minor */
+	int	radio;		/* Radio minor */
+	int	audio;		/* Audio minor */
+	int	teletext;	/* Teletext minor */
+};
+
+struct vbi_format {
+	__u32	sampling_rate;	/* in Hz */
+	__u32	samples_per_line;
+	__u32	sample_format;	/* VIDEO_PALETTE_RAW only (1 byte) */
+	__s32	start[2];	/* starting line for each frame */
+	__u32	count[2];	/* count of lines for each frame */
+	__u32	flags;
+#define	VBI_UNSYNC	1	/* can distingues between top/bottom field */
+#define	VBI_INTERLACED	2	/* lines are interlaced */
+};
+
+/* video_info is biased towards hardware mpeg encode/decode */
+/* but it could apply generically to any hardware compressor/decompressor */
+struct video_info
+{
+	__u32	frame_count;	/* frames output since decode/encode began */
+	__u32	h_size;		/* current unscaled horizontal size */
+	__u32	v_size;		/* current unscaled veritcal size */
+	__u32	smpte_timecode;	/* current SMPTE timecode (for current GOP) */
+	__u32	picture_type;	/* current picture type */
+	__u32	temporal_reference;	/* current temporal reference */
+	__u8	user_data[256];	/* user data last found in compressed stream */
+	/* user_data[0] contains user data flags, user_data[1] has count */
+};
+
+/* generic structure for setting playback modes */
+struct video_play_mode
+{
+	int	mode;
+	int	p1;
+	int	p2;
+};
+
+/* for loading microcode / fpga programming */
+struct video_code
+{
+	char	loadwhat[16];	/* name or tag of file being passed */
+	int	datasize;
+	__u8	*data;
+};
+
+#define VIDIOCGCAP		_IOR('v',1,struct video_capability)	/* Get capabilities */
+#define VIDIOCGCHAN		_IOWR('v',2,struct video_channel)	/* Get channel info (sources) */
+#define VIDIOCSCHAN		_IOW('v',3,struct video_channel)	/* Set channel 	*/
+#define VIDIOCGTUNER		_IOWR('v',4,struct video_tuner)		/* Get tuner abilities */
+#define VIDIOCSTUNER		_IOW('v',5,struct video_tuner)		/* Tune the tuner for the current channel */
+#define VIDIOCGPICT		_IOR('v',6,struct video_picture)	/* Get picture properties */
+#define VIDIOCSPICT		_IOW('v',7,struct video_picture)	/* Set picture properties */
+#define VIDIOCCAPTURE		_IOW('v',8,int)				/* Start, end capture */
+#define VIDIOCGWIN		_IOR('v',9, struct video_window)	/* Get the video overlay window */
+#define VIDIOCSWIN		_IOW('v',10, struct video_window)	/* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
+#define VIDIOCGFBUF		_IOR('v',11, struct video_buffer)	/* Get frame buffer */
+#define VIDIOCSFBUF		_IOW('v',12, struct video_buffer)	/* Set frame buffer - root only */
+#define VIDIOCKEY		_IOR('v',13, struct video_key)		/* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
+#define VIDIOCGFREQ		_IOR('v',14, unsigned long)		/* Set tuner */
+#define VIDIOCSFREQ		_IOW('v',15, unsigned long)		/* Set tuner */
+#define VIDIOCGAUDIO		_IOR('v',16, struct video_audio)	/* Get audio info */
+#define VIDIOCSAUDIO		_IOW('v',17, struct video_audio)	/* Audio source, mute etc */
+#define VIDIOCSYNC		_IOW('v',18, int)			/* Sync with mmap grabbing */
+#define VIDIOCMCAPTURE		_IOW('v',19, struct video_mmap)		/* Grab frames */
+#define VIDIOCGMBUF		_IOR('v',20, struct video_mbuf)		/* Memory map buffer info */
+#define VIDIOCGUNIT		_IOR('v',21, struct video_unit)		/* Get attached units */
+#define VIDIOCGCAPTURE		_IOR('v',22, struct video_capture)	/* Get subcapture */
+#define VIDIOCSCAPTURE		_IOW('v',23, struct video_capture)	/* Set subcapture */
+#define VIDIOCSPLAYMODE		_IOW('v',24, struct video_play_mode)	/* Set output video mode/feature */
+#define VIDIOCSWRITEMODE	_IOW('v',25, int)			/* Set write mode */
+#define VIDIOCGPLAYINFO		_IOR('v',26, struct video_info)		/* Get current playback info from hardware */
+#define VIDIOCSMICROCODE	_IOW('v',27, struct video_code)		/* Load microcode into hardware */
+#define	VIDIOCGVBIFMT		_IOR('v',28, struct vbi_format)		/* Get VBI information */
+#define	VIDIOCSVBIFMT		_IOW('v',29, struct vbi_format)		/* Set VBI information */
+
+
+#define BASE_VIDIOCPRIVATE	192		/* 192-255 are private */
+
+/* VIDIOCSWRITEMODE */
+#define VID_WRITE_MPEG_AUD		0
+#define VID_WRITE_MPEG_VID		1
+#define VID_WRITE_OSD			2
+#define VID_WRITE_TTX			3
+#define VID_WRITE_CC			4
+#define VID_WRITE_MJPEG			5
+
+/* VIDIOCSPLAYMODE */
+#define VID_PLAY_VID_OUT_MODE		0
+	/* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
+#define VID_PLAY_GENLOCK		1
+	/* p1: 0 = OFF, 1 = ON */
+	/* p2: GENLOCK FINE DELAY value */
+#define VID_PLAY_NORMAL			2
+#define VID_PLAY_PAUSE			3
+#define VID_PLAY_SINGLE_FRAME		4
+#define VID_PLAY_FAST_FORWARD		5
+#define VID_PLAY_SLOW_MOTION		6
+#define VID_PLAY_IMMEDIATE_NORMAL	7
+#define VID_PLAY_SWITCH_CHANNELS	8
+#define VID_PLAY_FREEZE_FRAME		9
+#define VID_PLAY_STILL_MODE		10
+#define VID_PLAY_MASTER_MODE		11
+	/* p1: see below */
+#define		VID_PLAY_MASTER_NONE	1
+#define		VID_PLAY_MASTER_VIDEO	2
+#define		VID_PLAY_MASTER_AUDIO	3
+#define VID_PLAY_ACTIVE_SCANLINES	12
+	/* p1 = first active; p2 = last active */
+#define VID_PLAY_RESET			13
+#define VID_PLAY_END_MARK		14
+
+#endif /* __LINUX_VIDEODEV_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 8c3c057..d0e9e02 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -435,12 +435,6 @@
 	int ret = 0;
 	struct zram *zram = queue->queuedata;
 
-	if (unlikely(!zram->init_done)) {
-		set_bit(BIO_UPTODATE, &bio->bi_flags);
-		bio_endio(bio, 0);
-		return 0;
-	}
-
 	if (!valid_io_request(zram, bio)) {
 		zram_stat64_inc(zram, &zram->stats.invalid_io);
 		bio_io_error(bio);
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c5f8e5b..44b8412 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -19,7 +19,7 @@
  *
  * TO DO:
  *	Mostly done:	ioctls for setting modes/timing
- *	Partly done: 	hooks so you can pull off frames to non tty devs
+ *	Partly done:	hooks so you can pull off frames to non tty devs
  *	Restart DLCI 0 when it closes ?
  *	Test basic encoding
  *	Improve the tx engine
@@ -73,8 +73,10 @@
 #define T2	(2 * HZ)
 #endif
 
-/* Semi-arbitary buffer size limits. 0710 is normally run with 32-64 byte
-   limits so this is plenty */
+/*
+ * Semi-arbitary buffer size limits. 0710 is normally run with 32-64 byte
+ * limits so this is plenty
+ */
 #define MAX_MRU 512
 #define MAX_MTU 512
 
@@ -184,6 +186,9 @@
 #define GSM_DATA		5
 #define GSM_FCS			6
 #define GSM_OVERRUN		7
+#define GSM_LEN0		8
+#define GSM_LEN1		9
+#define GSM_SSOF		10
 	unsigned int len;
 	unsigned int address;
 	unsigned int count;
@@ -191,6 +196,7 @@
 	int encoding;
 	u8 control;
 	u8 fcs;
+	u8 received_fcs;
 	u8 *txframe;			/* TX framing buffer */
 
 	/* Methods for the receiver side */
@@ -286,7 +292,7 @@
 #define MDM_DV			0x40
 
 #define GSM0_SOF		0xF9
-#define GSM1_SOF 		0x7E
+#define GSM1_SOF		0x7E
 #define GSM1_ESCAPE		0x7D
 #define GSM1_ESCAPE_BITS	0x20
 #define XON			0x11
@@ -429,61 +435,63 @@
 	if (!(debug & 1))
 		return;
 
-	printk(KERN_INFO "%s %d) %c: ", hdr, addr, "RC"[cr]);
+	pr_info("%s %d) %c: ", hdr, addr, "RC"[cr]);
 
 	switch (control & ~PF) {
 	case SABM:
-		printk(KERN_CONT "SABM");
+		pr_cont("SABM");
 		break;
 	case UA:
-		printk(KERN_CONT "UA");
+		pr_cont("UA");
 		break;
 	case DISC:
-		printk(KERN_CONT "DISC");
+		pr_cont("DISC");
 		break;
 	case DM:
-		printk(KERN_CONT "DM");
+		pr_cont("DM");
 		break;
 	case UI:
-		printk(KERN_CONT "UI");
+		pr_cont("UI");
 		break;
 	case UIH:
-		printk(KERN_CONT "UIH");
+		pr_cont("UIH");
 		break;
 	default:
 		if (!(control & 0x01)) {
-			printk(KERN_CONT "I N(S)%d N(R)%d",
-				(control & 0x0E) >> 1, (control & 0xE)>> 5);
+			pr_cont("I N(S)%d N(R)%d",
+				(control & 0x0E) >> 1, (control & 0xE) >> 5);
 		} else switch (control & 0x0F) {
-		case RR:
-			printk("RR(%d)", (control & 0xE0) >> 5);
-			break;
-		case RNR:
-			printk("RNR(%d)", (control & 0xE0) >> 5);
-			break;
-		case REJ:
-			printk("REJ(%d)", (control & 0xE0) >> 5);
-			break;
-		default:
-			printk(KERN_CONT "[%02X]", control);
+			case RR:
+				pr_cont("RR(%d)", (control & 0xE0) >> 5);
+				break;
+			case RNR:
+				pr_cont("RNR(%d)", (control & 0xE0) >> 5);
+				break;
+			case REJ:
+				pr_cont("REJ(%d)", (control & 0xE0) >> 5);
+				break;
+			default:
+				pr_cont("[%02X]", control);
 		}
 	}
 
 	if (control & PF)
-		printk(KERN_CONT "(P)");
+		pr_cont("(P)");
 	else
-		printk(KERN_CONT "(F)");
+		pr_cont("(F)");
 
 	if (dlen) {
 		int ct = 0;
 		while (dlen--) {
-			if (ct % 8 == 0)
-				printk(KERN_CONT "\n    ");
-			printk(KERN_CONT "%02X ", *data++);
+			if (ct % 8 == 0) {
+				pr_cont("\n");
+				pr_debug("    ");
+			}
+			pr_cont("%02X ", *data++);
 			ct++;
 		}
 	}
-	printk(KERN_CONT "\n");
+	pr_cont("\n");
 }
 
 
@@ -522,11 +530,13 @@
 {
 	int i;
 	for (i = 0; i < len; i++) {
-		if (i && (i % 16) == 0)
-			printk("\n");
-		printk("%02X ", *p++);
+		if (i && (i % 16) == 0) {
+			pr_cont("\n");
+			pr_debug("");
+		}
+		pr_cont("%02X ", *p++);
 	}
-	printk("\n");
+	pr_cont("\n");
 }
 
 /**
@@ -676,7 +686,7 @@
 		}
 
 		if (debug & 4) {
-			printk("gsm_data_kick: \n");
+			pr_debug("gsm_data_kick:\n");
 			hex_packet(gsm->txframe, len);
 		}
 
@@ -1231,7 +1241,7 @@
 }
 
 /**
- *	gsm_control_transmit 	-	send control packet
+ *	gsm_control_transmit	-	send control packet
  *	@gsm: gsm mux
  *	@ctrl: frame to send
  *
@@ -1361,7 +1371,7 @@
 {
 	del_timer(&dlci->t1);
 	if (debug & 8)
-		printk("DLCI %d goes closed.\n", dlci->addr);
+		pr_debug("DLCI %d goes closed.\n", dlci->addr);
 	dlci->state = DLCI_CLOSED;
 	if (dlci->addr != 0) {
 		struct tty_struct  *tty = tty_port_tty_get(&dlci->port);
@@ -1392,7 +1402,7 @@
 	/* This will let a tty open continue */
 	dlci->state = DLCI_OPEN;
 	if (debug & 8)
-		printk("DLCI %d goes open.\n", dlci->addr);
+		pr_debug("DLCI %d goes open.\n", dlci->addr);
 	wake_up(&dlci->gsm->event);
 }
 
@@ -1494,29 +1504,29 @@
 	unsigned int modem = 0;
 
 	if (debug & 16)
-		printk("%d bytes for tty %p\n", len, tty);
+		pr_debug("%d bytes for tty %p\n", len, tty);
 	if (tty) {
 		switch (dlci->adaption)  {
-			/* Unsupported types */
-			/* Packetised interruptible data */
-			case 4:
-				break;
-			/* Packetised uininterruptible voice/data */
-			case 3:
-				break;
-			/* Asynchronous serial with line state in each frame */
-			case 2:
-				while (gsm_read_ea(&modem, *data++) == 0) {
-					len--;
-					if (len == 0)
-						return;
-				}
-				gsm_process_modem(tty, dlci, modem);
-			/* Line state will go via DLCI 0 controls only */
-			case 1:
-			default:
-				tty_insert_flip_string(tty, data, len);
-				tty_flip_buffer_push(tty);
+		/* Unsupported types */
+		/* Packetised interruptible data */
+		case 4:
+			break;
+		/* Packetised uininterruptible voice/data */
+		case 3:
+			break;
+		/* Asynchronous serial with line state in each frame */
+		case 2:
+			while (gsm_read_ea(&modem, *data++) == 0) {
+				len--;
+				if (len == 0)
+					return;
+			}
+			gsm_process_modem(tty, dlci, modem);
+		/* Line state will go via DLCI 0 controls only */
+		case 1:
+		default:
+			tty_insert_flip_string(tty, data, len);
+			tty_flip_buffer_push(tty);
 		}
 		tty_kref_put(tty);
 	}
@@ -1625,7 +1635,6 @@
 	kfree(dlci);
 }
 
-
 /*
  *	LAPBish link layer logic
  */
@@ -1650,10 +1659,12 @@
 
 	if ((gsm->control & ~PF) == UI)
 		gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
+	/* generate final CRC with received FCS */
+	gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
 	if (gsm->fcs != GOOD_FCS) {
 		gsm->bad_fcs++;
 		if (debug & 4)
-			printk("BAD FCS %02x\n", gsm->fcs);
+			pr_debug("BAD FCS %02x\n", gsm->fcs);
 		return;
 	}
 	address = gsm->address >> 1;
@@ -1748,6 +1759,8 @@
 
 static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
 {
+	unsigned int len;
+
 	switch (gsm->state) {
 	case GSM_SEARCH:	/* SOF marker */
 		if (c == GSM0_SOF) {
@@ -1756,8 +1769,8 @@
 			gsm->len = 0;
 			gsm->fcs = INIT_FCS;
 		}
-		break;		/* Address EA */
-	case GSM_ADDRESS:
+		break;
+	case GSM_ADDRESS:	/* Address EA */
 		gsm->fcs = gsm_fcs_add(gsm->fcs, c);
 		if (gsm_read_ea(&gsm->address, c))
 			gsm->state = GSM_CONTROL;
@@ -1765,9 +1778,9 @@
 	case GSM_CONTROL:	/* Control Byte */
 		gsm->fcs = gsm_fcs_add(gsm->fcs, c);
 		gsm->control = c;
-		gsm->state = GSM_LEN;
+		gsm->state = GSM_LEN0;
 		break;
-	case GSM_LEN:		/* Length EA */
+	case GSM_LEN0:		/* Length EA */
 		gsm->fcs = gsm_fcs_add(gsm->fcs, c);
 		if (gsm_read_ea(&gsm->len, c)) {
 			if (gsm->len > gsm->mru) {
@@ -1776,8 +1789,28 @@
 				break;
 			}
 			gsm->count = 0;
-			gsm->state = GSM_DATA;
+			if (!gsm->len)
+				gsm->state = GSM_FCS;
+			else
+				gsm->state = GSM_DATA;
+			break;
 		}
+		gsm->state = GSM_LEN1;
+		break;
+	case GSM_LEN1:
+		gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+		len = c;
+		gsm->len |= len << 7;
+		if (gsm->len > gsm->mru) {
+			gsm->bad_size++;
+			gsm->state = GSM_SEARCH;
+			break;
+		}
+		gsm->count = 0;
+		if (!gsm->len)
+			gsm->state = GSM_FCS;
+		else
+			gsm->state = GSM_DATA;
 		break;
 	case GSM_DATA:		/* Data */
 		gsm->buf[gsm->count++] = c;
@@ -1785,16 +1818,25 @@
 			gsm->state = GSM_FCS;
 		break;
 	case GSM_FCS:		/* FCS follows the packet */
-		gsm->fcs = c;
+		gsm->received_fcs = c;
+		if (c == GSM0_SOF) {
+			gsm->state = GSM_SEARCH;
+			break;
+		}
 		gsm_queue(gsm);
-		/* And then back for the next frame */
-		gsm->state = GSM_SEARCH;
+		gsm->state = GSM_SSOF;
+		break;
+	case GSM_SSOF:
+		if (c == GSM0_SOF) {
+			gsm->state = GSM_SEARCH;
+			break;
+		}
 		break;
 	}
 }
 
 /**
- *	gsm0_receive	-	perform processing for non-transparency
+ *	gsm1_receive	-	perform processing for non-transparency
  *	@gsm: gsm data for this ldisc instance
  *	@c: character
  *
@@ -1856,7 +1898,7 @@
 		gsm->state = GSM_DATA;
 		break;
 	case GSM_DATA:		/* Data */
-		if (gsm->count > gsm->mru ) {	/* Allow one for the FCS */
+		if (gsm->count > gsm->mru) {	/* Allow one for the FCS */
 			gsm->state = GSM_OVERRUN;
 			gsm->bad_size++;
 		} else
@@ -2034,9 +2076,6 @@
 }
 EXPORT_SYMBOL_GPL(gsm_alloc_mux);
 
-
-
-
 /**
  *	gsmld_output		-	write to link
  *	@gsm: our mux
@@ -2054,7 +2093,7 @@
 		return -ENOSPC;
 	}
 	if (debug & 4) {
-		printk("-->%d bytes out\n", len);
+		pr_debug("-->%d bytes out\n", len);
 		hex_packet(data, len);
 	}
 	gsm->tty->ops->write(gsm->tty, data, len);
@@ -2111,7 +2150,7 @@
 	char flags;
 
 	if (debug & 4) {
-		printk("Inbytes %dd\n", count);
+		pr_debug("Inbytes %dd\n", count);
 		hex_packet(cp, count);
 	}
 
@@ -2128,7 +2167,7 @@
 			gsm->error(gsm, *dp, flags);
 			break;
 		default:
-			printk(KERN_ERR "%s: unknown flag %d\n",
+			WARN_ONCE("%s: unknown flag %d\n",
 			       tty_name(tty, buf), flags);
 			break;
 		}
@@ -2323,7 +2362,7 @@
 	int need_restart = 0;
 
 	/* Stuff we don't support yet - UI or I frame transport, windowing */
-	if ((c->adaption !=1 && c->adaption != 2) || c->k)
+	if ((c->adaption != 1 && c->adaption != 2) || c->k)
 		return -EOPNOTSUPP;
 	/* Check the MRU/MTU range looks sane */
 	if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8)
@@ -2418,7 +2457,7 @@
 			c.i = 1;
 		else
 			c.i = 2;
-		printk("Ftype %d i %d\n", gsm->ftype, c.i);
+		pr_debug("Ftype %d i %d\n", gsm->ftype, c.i);
 		c.mru = gsm->mru;
 		c.mtu = gsm->mtu;
 		c.k = 0;
@@ -2712,14 +2751,15 @@
 	/* Fill in our line protocol discipline, and register it */
 	int status = tty_register_ldisc(N_GSM0710, &tty_ldisc_packet);
 	if (status != 0) {
-		printk(KERN_ERR "n_gsm: can't register line discipline (err = %d)\n", status);
+		pr_err("n_gsm: can't register line discipline (err = %d)\n",
+								status);
 		return status;
 	}
 
 	gsm_tty_driver = alloc_tty_driver(256);
 	if (!gsm_tty_driver) {
 		tty_unregister_ldisc(N_GSM0710);
-		printk(KERN_ERR "gsm_init: tty allocation failed.\n");
+		pr_err("gsm_init: tty allocation failed.\n");
 		return -EINVAL;
 	}
 	gsm_tty_driver->owner	= THIS_MODULE;
@@ -2730,7 +2770,7 @@
 	gsm_tty_driver->type		= TTY_DRIVER_TYPE_SERIAL;
 	gsm_tty_driver->subtype	= SERIAL_TYPE_NORMAL;
 	gsm_tty_driver->flags	= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV
-							| TTY_DRIVER_HARDWARE_BREAK;
+						| TTY_DRIVER_HARDWARE_BREAK;
 	gsm_tty_driver->init_termios	= tty_std_termios;
 	/* Fixme */
 	gsm_tty_driver->init_termios.c_lflag &= ~ECHO;
@@ -2741,10 +2781,11 @@
 	if (tty_register_driver(gsm_tty_driver)) {
 		put_tty_driver(gsm_tty_driver);
 		tty_unregister_ldisc(N_GSM0710);
-		printk(KERN_ERR "gsm_init: tty registration failed.\n");
+		pr_err("gsm_init: tty registration failed.\n");
 		return -EBUSY;
 	}
-	printk(KERN_INFO "gsm_init: loaded as %d,%d.\n", gsm_tty_driver->major, gsm_tty_driver->minor_start);
+	pr_debug("gsm_init: loaded as %d,%d.\n",
+			gsm_tty_driver->major, gsm_tty_driver->minor_start);
 	return 0;
 }
 
@@ -2752,10 +2793,10 @@
 {
 	int status = tty_unregister_ldisc(N_GSM0710);
 	if (status != 0)
-		printk(KERN_ERR "n_gsm: can't unregister line discipline (err = %d)\n", status);
+		pr_err("n_gsm: can't unregister line discipline (err = %d)\n",
+								status);
 	tty_unregister_driver(gsm_tty_driver);
 	put_tty_driver(gsm_tty_driver);
-	printk(KERN_INFO "gsm_init: unloaded.\n");
 }
 
 module_init(gsm_init);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 35480dd..464d09d 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2627,6 +2627,11 @@
 		return put_user(tty->ldisc->ops->num, (int __user *)p);
 	case TIOCSETD:
 		return tiocsetd(tty, p);
+	case TIOCGDEV:
+	{
+		unsigned int ret = new_encode_dev(tty_devnum(real_tty));
+		return put_user(ret, (unsigned int __user *)p);
+	}
 	/*
 	 * Break handling
 	 */
@@ -3241,9 +3246,45 @@
 postcore_initcall(tty_class_init);
 
 /* 3/2004 jmc: why do these devices exist? */
-
 static struct cdev tty_cdev, console_cdev;
 
+static ssize_t show_cons_active(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct console *cs[16];
+	int i = 0;
+	struct console *c;
+	ssize_t count = 0;
+
+	acquire_console_sem();
+	for (c = console_drivers; c; c = c->next) {
+		if (!c->device)
+			continue;
+		if (!c->write)
+			continue;
+		if ((c->flags & CON_ENABLED) == 0)
+			continue;
+		cs[i++] = c;
+		if (i >= ARRAY_SIZE(cs))
+			break;
+	}
+	while (i--)
+		count += sprintf(buf + count, "%s%d%c",
+				 cs[i]->name, cs[i]->index, i ? ' ':'\n');
+	release_console_sem();
+
+	return count;
+}
+static DEVICE_ATTR(active, S_IRUGO, show_cons_active, NULL);
+
+static struct device *consdev;
+
+void console_sysfs_notify(void)
+{
+	if (consdev)
+		sysfs_notify(&consdev->kobj, NULL, "active");
+}
+
 /*
  * Ok, now we can initialize the rest of the tty devices and can count
  * on memory allocations, interrupts etc..
@@ -3254,15 +3295,18 @@
 	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
 		panic("Couldn't register /dev/tty driver\n");
-	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
-			      "tty");
+	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
 
 	cdev_init(&console_cdev, &console_fops);
 	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
 		panic("Couldn't register /dev/console driver\n");
-	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
+	consdev = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
 			      "console");
+	if (IS_ERR(consdev))
+		consdev = NULL;
+	else
+		device_create_file(consdev, &dev_attr_active);
 
 #ifdef CONFIG_VT
 	vty_init(&console_fops);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index a8ec48e..76407ec 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -236,6 +236,14 @@
 };
 
 /*
+ * /sys/class/tty/tty0/
+ *
+ * the attribute 'active' contains the name of the current vc
+ * console and it supports poll() to detect vc switches
+ */
+static struct device *tty0dev;
+
+/*
  * Notifier list for console events.
  */
 static ATOMIC_NOTIFIER_HEAD(vt_notifier_list);
@@ -688,6 +696,8 @@
 			save_screen(old_vc);
 			set_origin(old_vc);
 		}
+		if (tty0dev)
+			sysfs_notify(&tty0dev->kobj, NULL, "active");
 	} else {
 		hide_cursor(vc);
 		redraw = 1;
@@ -2967,13 +2977,24 @@
 
 static struct cdev vc0_cdev;
 
+static ssize_t show_tty_active(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "tty%d\n", fg_console + 1);
+}
+static DEVICE_ATTR(active, S_IRUGO, show_tty_active, NULL);
+
 int __init vty_init(const struct file_operations *console_fops)
 {
 	cdev_init(&vc0_cdev, console_fops);
 	if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
 	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
 		panic("Couldn't register /dev/tty0 driver\n");
-	device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+	tty0dev = device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+	if (IS_ERR(tty0dev))
+		tty0dev = NULL;
+	else
+		device_create_file(tty0dev, &dev_attr_active);
 
 	vcs_init();
 
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 67eb377..fceea5e 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -41,17 +41,14 @@
 	default y if MFD_TC6393XB
 	default y if ARCH_W90X900
 	default y if ARCH_DAVINCI_DA8XX
+	default y if ARCH_CNS3XXX
+	default y if PLAT_SPEAR
 	# PPC:
 	default y if STB03xxx
 	default y if PPC_MPC52xx
 	# MIPS:
 	default y if MIPS_ALCHEMY
 	default y if MACH_JZ4740
-	# SH:
-	default y if CPU_SUBTYPE_SH7720
-	default y if CPU_SUBTYPE_SH7721
-	default y if CPU_SUBTYPE_SH7763
-	default y if CPU_SUBTYPE_SH7786
 	# more:
 	default PCI
 
@@ -66,6 +63,10 @@
 	default y if ARCH_AT91SAM9G45
 	default y if ARCH_MXC
 	default y if ARCH_OMAP3
+	default y if ARCH_CNS3XXX
+	default y if ARCH_VT8500
+	default y if PLAT_SPEAR
+	default y if ARCH_MSM
 	default PCI
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index f383cb4..a845f8b 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -1247,7 +1247,7 @@
 	mutex_unlock(&instance->poll_state_serialize);
 
 	if (is_polling)
-		cancel_rearming_delayed_work(&instance->poll_work);
+		cancel_delayed_work_sync(&instance->poll_work);
 
 	usb_kill_urb(instance->snd_urb);
 	usb_kill_urb(instance->rcv_urb);
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 4716e70..0842cfb 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -139,7 +139,8 @@
 
 	struct speedtch_params params; /* set in probe, constant afterwards */
 
-	struct delayed_work status_checker;
+	struct timer_list status_check_timer;
+	struct work_struct status_check_work;
 
 	unsigned char last_status;
 
@@ -498,7 +499,7 @@
 {
 	struct speedtch_instance_data *instance =
 		container_of(work, struct speedtch_instance_data,
-			     status_checker.work);
+			     status_check_work);
 	struct usbatm_data *usbatm = instance->usbatm;
 	struct atm_dev *atm_dev = usbatm->atm_dev;
 	unsigned char *buf = instance->scratch_buffer;
@@ -575,11 +576,11 @@
 {
 	struct speedtch_instance_data *instance = (void *)data;
 
-	schedule_delayed_work(&instance->status_checker, 0);
+	schedule_work(&instance->status_check_work);
 
 	/* The following check is racy, but the race is harmless */
 	if (instance->poll_delay < MAX_POLL_DELAY)
-		mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(instance->poll_delay));
+		mod_timer(&instance->status_check_timer, jiffies + msecs_to_jiffies(instance->poll_delay));
 	else
 		atm_warn(instance->usbatm, "Too many failures - disabling line status polling\n");
 }
@@ -595,7 +596,7 @@
 	if (int_urb) {
 		ret = usb_submit_urb(int_urb, GFP_ATOMIC);
 		if (!ret)
-			schedule_delayed_work(&instance->status_checker, 0);
+			schedule_work(&instance->status_check_work);
 		else {
 			atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);
 			mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY));
@@ -624,7 +625,7 @@
 	}
 
 	if ((count == 6) && !memcmp(up_int, instance->int_data, 6)) {
-		del_timer(&instance->status_checker.timer);
+		del_timer(&instance->status_check_timer);
 		atm_info(usbatm, "DSL line goes up\n");
 	} else if ((count == 6) && !memcmp(down_int, instance->int_data, 6)) {
 		atm_info(usbatm, "DSL line goes down\n");
@@ -640,7 +641,7 @@
 
 	if ((int_urb = instance->int_urb)) {
 		ret = usb_submit_urb(int_urb, GFP_ATOMIC);
-		schedule_delayed_work(&instance->status_checker, 0);
+		schedule_work(&instance->status_check_work);
 		if (ret < 0) {
 			atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);
 			goto fail;
@@ -686,7 +687,7 @@
 	}
 
 	/* Start status polling */
-	mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(1000));
+	mod_timer(&instance->status_check_timer, jiffies + msecs_to_jiffies(1000));
 
 	return 0;
 }
@@ -698,7 +699,7 @@
 
 	atm_dbg(usbatm, "%s entered\n", __func__);
 
-	del_timer_sync(&instance->status_checker.timer);
+	del_timer_sync(&instance->status_check_timer);
 
 	/*
 	 * Since resubmit_timer and int_urb can schedule themselves and
@@ -717,7 +718,7 @@
 	del_timer_sync(&instance->resubmit_timer);
 	usb_free_urb(int_urb);
 
-	flush_scheduled_work();
+	flush_work_sync(&instance->status_check_work);
 }
 
 static int speedtch_pre_reset(struct usb_interface *intf)
@@ -869,10 +870,11 @@
 
 	usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
 
-	INIT_DELAYED_WORK(&instance->status_checker, speedtch_check_status);
+	INIT_WORK(&instance->status_check_work, speedtch_check_status);
+	init_timer(&instance->status_check_timer);
 
-	instance->status_checker.timer.function = speedtch_status_poll;
-	instance->status_checker.timer.data = (unsigned long)instance;
+	instance->status_check_timer.function = speedtch_status_poll;
+	instance->status_check_timer.data = (unsigned long)instance;
 	instance->last_status = 0xff;
 	instance->poll_delay = MIN_POLL_DELAY;
 
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index c0e60fb..b9278a1 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -27,7 +27,6 @@
 #include <linux/usb.h>
 #include <linux/usb/quirks.h>
 #include <linux/usb/hcd.h>
-#include <linux/pm_runtime.h>
 
 #include "usb.h"
 
@@ -1262,6 +1261,7 @@
 					udev->reset_resume);
 		}
 	}
+	usb_mark_last_busy(udev);
 
  done:
 	dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
@@ -1329,7 +1329,6 @@
 			pm_runtime_disable(dev);
 			pm_runtime_set_active(dev);
 			pm_runtime_enable(dev);
-			udev->last_busy = jiffies;
 			do_unbind_rebind(udev, DO_REBIND);
 		}
 	}
@@ -1397,33 +1396,8 @@
 {
 	int	status;
 
-	udev->last_busy = jiffies;
-	status = pm_runtime_put_sync(&udev->dev);
-	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
-			__func__, atomic_read(&udev->dev.power.usage_count),
-			status);
-}
-
-/**
- * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
- * @udev: the usb_device to autosuspend
- *
- * This routine should be called when a core subsystem thinks @udev may
- * be ready to autosuspend.
- *
- * @udev's usage counter left unchanged.  If it is 0 and all the interfaces
- * are inactive then an autosuspend will be attempted.  The attempt may
- * fail or be delayed.
- *
- * The caller must hold @udev's device lock.
- *
- * This routine can run only in process context.
- */
-void usb_try_autosuspend_device(struct usb_device *udev)
-{
-	int	status;
-
-	status = pm_runtime_idle(&udev->dev);
+	usb_mark_last_busy(udev);
+	status = pm_runtime_put_sync_autosuspend(&udev->dev);
 	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
 			__func__, atomic_read(&udev->dev.power.usage_count),
 			status);
@@ -1482,7 +1456,7 @@
 	struct usb_device	*udev = interface_to_usbdev(intf);
 	int			status;
 
-	udev->last_busy = jiffies;
+	usb_mark_last_busy(udev);
 	atomic_dec(&intf->pm_usage_cnt);
 	status = pm_runtime_put_sync(&intf->dev);
 	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
@@ -1509,32 +1483,11 @@
 void usb_autopm_put_interface_async(struct usb_interface *intf)
 {
 	struct usb_device	*udev = interface_to_usbdev(intf);
-	unsigned long		last_busy;
-	int			status = 0;
+	int			status;
 
-	last_busy = udev->last_busy;
-	udev->last_busy = jiffies;
+	usb_mark_last_busy(udev);
 	atomic_dec(&intf->pm_usage_cnt);
-	pm_runtime_put_noidle(&intf->dev);
-
-	if (udev->dev.power.runtime_auto) {
-		/* Optimization: Don't schedule a delayed autosuspend if
-		 * the timer is already running and the expiration time
-		 * wouldn't change.
-		 *
-		 * We have to use the interface's timer.  Attempts to
-		 * schedule a suspend for the device would fail because
-		 * the interface is still active.
-		 */
-		if (intf->dev.power.timer_expires == 0 ||
-				round_jiffies_up(last_busy) !=
-				round_jiffies_up(jiffies)) {
-			status = pm_schedule_suspend(&intf->dev,
-					jiffies_to_msecs(
-					round_jiffies_up_relative(
-						udev->autosuspend_delay)));
-		}
-	}
+	status = pm_runtime_put(&intf->dev);
 	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
 			__func__, atomic_read(&intf->dev.power.usage_count),
 			status);
@@ -1554,7 +1507,7 @@
 {
 	struct usb_device	*udev = interface_to_usbdev(intf);
 
-	udev->last_busy = jiffies;
+	usb_mark_last_busy(udev);
 	atomic_dec(&intf->pm_usage_cnt);
 	pm_runtime_put_noidle(&intf->dev);
 }
@@ -1612,18 +1565,9 @@
  */
 int usb_autopm_get_interface_async(struct usb_interface *intf)
 {
-	int		status = 0;
-	enum rpm_status	s;
+	int	status;
 
-	/* Don't request a resume unless the interface is already suspending
-	 * or suspended.  Doing so would force a running suspend timer to be
-	 * cancelled.
-	 */
-	pm_runtime_get_noresume(&intf->dev);
-	s = ACCESS_ONCE(intf->dev.power.runtime_status);
-	if (s == RPM_SUSPENDING || s == RPM_SUSPENDED)
-		status = pm_request_resume(&intf->dev);
-
+	status = pm_runtime_get(&intf->dev);
 	if (status < 0 && status != -EINPROGRESS)
 		pm_runtime_put_noidle(&intf->dev);
 	else
@@ -1650,7 +1594,7 @@
 {
 	struct usb_device	*udev = interface_to_usbdev(intf);
 
-	udev->last_busy = jiffies;
+	usb_mark_last_busy(udev);
 	atomic_inc(&intf->pm_usage_cnt);
 	pm_runtime_get_noresume(&intf->dev);
 }
@@ -1661,7 +1605,6 @@
 {
 	int			w, i;
 	struct usb_interface	*intf;
-	unsigned long		suspend_time, j;
 
 	/* Fail if autosuspend is disabled, or any interfaces are in use, or
 	 * any interface drivers require remote wakeup but it isn't available.
@@ -1701,87 +1644,46 @@
 		return -EOPNOTSUPP;
 	}
 	udev->do_remote_wakeup = w;
-
-	/* If everything is okay but the device hasn't been idle for long
-	 * enough, queue a delayed autosuspend request.
-	 */
-	j = ACCESS_ONCE(jiffies);
-	suspend_time = udev->last_busy + udev->autosuspend_delay;
-	if (time_before(j, suspend_time)) {
-		pm_schedule_suspend(&udev->dev, jiffies_to_msecs(
-				round_jiffies_up_relative(suspend_time - j)));
-		return -EAGAIN;
-	}
 	return 0;
 }
 
 static int usb_runtime_suspend(struct device *dev)
 {
-	int	status = 0;
+	struct usb_device	*udev = to_usb_device(dev);
+	int			status;
 
 	/* A USB device can be suspended if it passes the various autosuspend
 	 * checks.  Runtime suspend for a USB device means suspending all the
 	 * interfaces and then the device itself.
 	 */
-	if (is_usb_device(dev)) {
-		struct usb_device	*udev = to_usb_device(dev);
+	if (autosuspend_check(udev) != 0)
+		return -EAGAIN;
 
-		if (autosuspend_check(udev) != 0)
-			return -EAGAIN;
-
-		status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
-
-		/* If an interface fails the suspend, adjust the last_busy
-		 * time so that we don't get another suspend attempt right
-		 * away.
-		 */
-		if (status) {
-			udev->last_busy = jiffies +
-					(udev->autosuspend_delay == 0 ?
-						HZ/2 : 0);
-		}
-
-		/* Prevent the parent from suspending immediately after */
-		else if (udev->parent)
-			udev->parent->last_busy = jiffies;
-	}
-
-	/* Runtime suspend for a USB interface doesn't mean anything. */
+	status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
 	return status;
 }
 
 static int usb_runtime_resume(struct device *dev)
 {
+	struct usb_device	*udev = to_usb_device(dev);
+	int			status;
+
 	/* Runtime resume for a USB device means resuming both the device
 	 * and all its interfaces.
 	 */
-	if (is_usb_device(dev)) {
-		struct usb_device	*udev = to_usb_device(dev);
-		int			status;
-
-		status = usb_resume_both(udev, PMSG_AUTO_RESUME);
-		udev->last_busy = jiffies;
-		return status;
-	}
-
-	/* Runtime resume for a USB interface doesn't mean anything. */
-	return 0;
+	status = usb_resume_both(udev, PMSG_AUTO_RESUME);
+	return status;
 }
 
 static int usb_runtime_idle(struct device *dev)
 {
+	struct usb_device	*udev = to_usb_device(dev);
+
 	/* An idle USB device can be suspended if it passes the various
-	 * autosuspend checks.  An idle interface can be suspended at
-	 * any time.
+	 * autosuspend checks.
 	 */
-	if (is_usb_device(dev)) {
-		struct usb_device	*udev = to_usb_device(dev);
-
-		if (autosuspend_check(udev) != 0)
-			return 0;
-	}
-
-	pm_runtime_suspend(dev);
+	if (autosuspend_check(udev) == 0)
+		pm_runtime_autosuspend(dev);
 	return 0;
 }
 
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 3799573..b55d4607 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/pm_runtime.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index ced846a..6a95017 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -38,7 +38,6 @@
 #include <asm/unaligned.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
-#include <linux/pm_runtime.h>
 
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 27115b4..b98efae 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -24,7 +24,6 @@
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
-#include <linux/pm_runtime.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -1804,8 +1803,15 @@
 
 	/* Tell the runtime-PM framework the device is active */
 	pm_runtime_set_active(&udev->dev);
+	pm_runtime_get_noresume(&udev->dev);
+	pm_runtime_use_autosuspend(&udev->dev);
 	pm_runtime_enable(&udev->dev);
 
+	/* By default, forbid autosuspend for all devices.  It will be
+	 * allowed for hubs during binding.
+	 */
+	usb_disable_autosuspend(udev);
+
 	err = usb_enumerate_device(udev);	/* Read descriptors */
 	if (err < 0)
 		goto fail;
@@ -1831,6 +1837,8 @@
 	}
 
 	(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
+	usb_mark_last_busy(udev);
+	pm_runtime_put_sync_autosuspend(&udev->dev);
 	return err;
 
 fail:
@@ -2221,6 +2229,7 @@
 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
 		msleep(10);
 	}
+	usb_mark_last_busy(hub->hdev);
 	return status;
 }
 
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index b690aa3..1b125c2 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -343,17 +343,19 @@
 {
 	struct list_head *list;
 
-	spin_lock(&dcache_lock);
-
+	spin_lock(&dentry->d_lock);
 	list_for_each(list, &dentry->d_subdirs) {
 		struct dentry *de = list_entry(list, struct dentry, d_u.d_child);
+
+		spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED);
 		if (usbfs_positive(de)) {
-			spin_unlock(&dcache_lock);
+			spin_unlock(&de->d_lock);
+			spin_unlock(&dentry->d_lock);
 			return 0;
 		}
+		spin_unlock(&de->d_lock);
 	}
-
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
 	return 1;
 }
 
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index d6e3e41..8324874 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1804,6 +1804,7 @@
 		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
 		intf->minor = -1;
 		device_initialize(&intf->dev);
+		pm_runtime_no_callbacks(&intf->dev);
 		dev_set_name(&intf->dev, "%d-%s:%d.%d",
 			dev->bus->busnum, dev->devpath,
 			configuration, alt->desc.bInterfaceNumber);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 25719da..44c5954 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -117,21 +117,6 @@
 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
 				udev->quirks);
 
-#ifdef	CONFIG_USB_SUSPEND
-
-	/* By default, disable autosuspend for all devices.  The hub driver
-	 * will enable it for hubs.
-	 */
-	usb_disable_autosuspend(udev);
-
-	/* Autosuspend can also be disabled if the initial autosuspend_delay
-	 * is negative.
-	 */
-	if (udev->autosuspend_delay < 0)
-		usb_autoresume_device(udev);
-
-#endif
-
 	/* For the present, all devices default to USB-PERSIST enabled */
 #if 0		/* was: #ifdef CONFIG_PM */
 	/* Hubs are automatically enabled for USB-PERSIST */
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 448f5b4..6781c36 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -233,8 +233,6 @@
 
 #ifdef	CONFIG_PM
 
-static const char power_group[] = "power";
-
 static ssize_t
 show_persist(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -278,7 +276,7 @@
 		if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
 			rc = sysfs_add_file_to_group(&dev->kobj,
 					&dev_attr_persist.attr,
-					power_group);
+					power_group_name);
 	}
 	return rc;
 }
@@ -287,7 +285,7 @@
 {
 	sysfs_remove_file_from_group(&dev->kobj,
 			&dev_attr_persist.attr,
-			power_group);
+			power_group_name);
 }
 #else
 
@@ -336,44 +334,20 @@
 static ssize_t
 show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct usb_device *udev = to_usb_device(dev);
-
-	return sprintf(buf, "%d\n", udev->autosuspend_delay / HZ);
+	return sprintf(buf, "%d\n", dev->power.autosuspend_delay / 1000);
 }
 
 static ssize_t
 set_autosuspend(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct usb_device *udev = to_usb_device(dev);
-	int value, old_delay;
-	int rc;
+	int value;
 
-	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
-			value <= - INT_MAX/HZ)
+	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/1000 ||
+			value <= -INT_MAX/1000)
 		return -EINVAL;
-	value *= HZ;
 
-	usb_lock_device(udev);
-	old_delay = udev->autosuspend_delay;
-	udev->autosuspend_delay = value;
-
-	if (old_delay < 0) {	/* Autosuspend wasn't allowed */
-		if (value >= 0)
-			usb_autosuspend_device(udev);
-	} else {		/* Autosuspend was allowed */
-		if (value < 0) {
-			rc = usb_autoresume_device(udev);
-			if (rc < 0) {
-				count = rc;
-				udev->autosuspend_delay = old_delay;
-			}
-		} else {
-			usb_try_autosuspend_device(udev);
-		}
-	}
-
-	usb_unlock_device(udev);
+	pm_runtime_set_autosuspend_delay(dev, value * 1000);
 	return count;
 }
 
@@ -438,44 +412,30 @@
 
 static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
 
+static struct attribute *power_attrs[] = {
+	&dev_attr_autosuspend.attr,
+	&dev_attr_level.attr,
+	&dev_attr_connected_duration.attr,
+	&dev_attr_active_duration.attr,
+	NULL,
+};
+static struct attribute_group power_attr_group = {
+	.name	= power_group_name,
+	.attrs	= power_attrs,
+};
+
 static int add_power_attributes(struct device *dev)
 {
 	int rc = 0;
 
-	if (is_usb_device(dev)) {
-		rc = sysfs_add_file_to_group(&dev->kobj,
-				&dev_attr_autosuspend.attr,
-				power_group);
-		if (rc == 0)
-			rc = sysfs_add_file_to_group(&dev->kobj,
-					&dev_attr_level.attr,
-					power_group);
-		if (rc == 0)
-			rc = sysfs_add_file_to_group(&dev->kobj,
-					&dev_attr_connected_duration.attr,
-					power_group);
-		if (rc == 0)
-			rc = sysfs_add_file_to_group(&dev->kobj,
-					&dev_attr_active_duration.attr,
-					power_group);
-	}
+	if (is_usb_device(dev))
+		rc = sysfs_merge_group(&dev->kobj, &power_attr_group);
 	return rc;
 }
 
 static void remove_power_attributes(struct device *dev)
 {
-	sysfs_remove_file_from_group(&dev->kobj,
-			&dev_attr_active_duration.attr,
-			power_group);
-	sysfs_remove_file_from_group(&dev->kobj,
-			&dev_attr_connected_duration.attr,
-			power_group);
-	sysfs_remove_file_from_group(&dev->kobj,
-			&dev_attr_level.attr,
-			power_group);
-	sysfs_remove_file_from_group(&dev->kobj,
-			&dev_attr_autosuspend.attr,
-			power_group);
+	sysfs_unmerge_group(&dev->kobj, &power_attr_group);
 }
 
 #else
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index fdd4130..079cb57 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -445,7 +445,8 @@
 	INIT_LIST_HEAD(&dev->filelist);
 
 #ifdef	CONFIG_PM
-	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
+	pm_runtime_set_autosuspend_delay(&dev->dev,
+			usb_autosuspend_delay * 1000);
 	dev->connect_time = jiffies;
 	dev->active_duration = -jiffies;
 #endif
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index cd88220..b975450 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -75,14 +75,12 @@
 #ifdef CONFIG_USB_SUSPEND
 
 extern void usb_autosuspend_device(struct usb_device *udev);
-extern void usb_try_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
 extern int usb_remote_wakeup(struct usb_device *dev);
 
 #else
 
 #define usb_autosuspend_device(udev)		do {} while (0)
-#define usb_try_autosuspend_device(udev)	do {} while (0)
 static inline int usb_autoresume_device(struct usb_device *udev)
 {
 	return 0;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 607d0db..1dc9739 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -338,6 +338,19 @@
 	boolean "S3C2410 udc debug messages"
 	depends on USB_GADGET_S3C2410
 
+config USB_GADGET_PXA_U2O
+	boolean "PXA9xx Processor USB2.0 controller"
+	select USB_GADGET_DUALSPEED
+	help
+	  PXA9xx Processor series include a high speed USB2.0 device
+	  controller, which support high speed and full speed USB peripheral.
+
+config USB_PXA_U2O
+	tristate
+	depends on USB_GADGET_PXA_U2O
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
 #
 # Controllers available in both integrated and discrete versions
 #
@@ -414,8 +427,8 @@
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
-config USB_GADGET_CI13XXX
-	boolean "MIPS USB CI13xxx"
+config USB_GADGET_CI13XXX_PCI
+	boolean "MIPS USB CI13xxx PCI UDC"
 	depends on PCI
 	select USB_GADGET_DUALSPEED
 	help
@@ -426,9 +439,9 @@
 	  dynamically linked module called "ci13xxx_udc" and force all
 	  gadget drivers to also be dynamically linked.
 
-config USB_CI13XXX
+config USB_CI13XXX_PCI
 	tristate
-	depends on USB_GADGET_CI13XXX
+	depends on USB_GADGET_CI13XXX_PCI
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
@@ -495,6 +508,49 @@
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
+config USB_GADGET_EG20T
+	boolean "Intel EG20T(Topcliff) USB Device controller"
+	depends on PCI
+	select USB_GADGET_DUALSPEED
+	help
+	  This is a USB device driver for EG20T PCH.
+	  EG20T PCH is the platform controller hub that is used in Intel's
+	  general embedded platform. EG20T PCH has USB device interface.
+	  Using this interface, it is able to access system devices connected
+	  to USB device.
+	  This driver enables USB device function.
+	  USB device is a USB peripheral controller which
+	  supports both full and high speed USB 2.0 data transfers.
+	  This driver supports both control transfer and bulk transfer modes.
+	  This driver dose not support interrupt transfer or isochronous
+	  transfer modes.
+
+config USB_EG20T
+	tristate
+	depends on USB_GADGET_EG20T
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
+config USB_GADGET_CI13XXX_MSM
+	boolean "MIPS USB CI13xxx for MSM"
+	depends on ARCH_MSM
+	select USB_GADGET_DUALSPEED
+	select USB_MSM_OTG_72K
+	help
+	  MSM SoC has chipidea USB controller.  This driver uses
+	  ci13xxx_udc core.
+	  This driver depends on OTG driver for PHY initialization,
+	  clock management, powering up VBUS, and power management.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "ci13xxx_msm" and force all
+	  gadget drivers to also be dynamically linked.
+
+config USB_CI13XXX_MSM
+	tristate
+	depends on USB_GADGET_CI13XXX_MSM
+	default USB_GADGET
+	select USB_GADGET_SELECTED
 
 #
 # LAST -- dummy/emulated controller
@@ -685,6 +741,19 @@
          If you say "y" here, the Ethernet gadget driver will use the EEM
          protocol rather than ECM.  If unsure, say "n".
 
+config USB_G_NCM
+	tristate "Network Control Model (NCM) support"
+	depends on NET
+	select CRC32
+	help
+	  This driver implements USB CDC NCM subclass standard. NCM is
+	  an advanced protocol for Ethernet encapsulation, allows grouping
+	  of several ethernet frames into one USB transfer and diffferent
+	  alignment possibilities.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_ncm".
+
 config USB_GADGETFS
 	tristate "Gadget Filesystem (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 5780db4..55f5e8a 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -21,9 +21,13 @@
 obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
 obj-$(CONFIG_USB_R8A66597)	+= r8a66597-udc.o
 obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
-obj-$(CONFIG_USB_CI13XXX)	+= ci13xxx_udc.o
+obj-$(CONFIG_USB_CI13XXX_PCI)	+= ci13xxx_pci.o
 obj-$(CONFIG_USB_S3C_HSOTG)	+= s3c-hsotg.o
 obj-$(CONFIG_USB_LANGWELL)	+= langwell_udc.o
+obj-$(CONFIG_USB_EG20T)		+= pch_udc.o
+obj-$(CONFIG_USB_PXA_U2O)	+= mv_udc.o
+mv_udc-y			:= mv_udc_core.o mv_udc_phy.o
+obj-$(CONFIG_USB_CI13XXX_MSM)	+= ci13xxx_msm.o
 
 #
 # USB gadget drivers
@@ -43,6 +47,7 @@
 g_dbgp-y			:= dbgp.o
 g_nokia-y			:= nokia.o
 g_webcam-y			:= webcam.o
+g_ncm-y				:= ncm.o
 
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
 obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
@@ -60,3 +65,4 @@
 obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
 obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
 obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
+obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 9034e034..f8dd726 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3359,7 +3359,6 @@
 	dev_set_name(&dev->gadget.dev, "gadget");
 	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = name;
-	dev->gadget.name = name;
 	dev->gadget.is_dualspeed = 1;
 
 	/* init registers, interrupts, ... */
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 717ff65..e7c65a4 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -2057,8 +2057,10 @@
 		usba_ep_cleanup_debugfs(&usba_ep[i]);
 	usba_cleanup_debugfs(udc);
 
-	if (gpio_is_valid(udc->vbus_pin))
+	if (gpio_is_valid(udc->vbus_pin)) {
+		free_irq(gpio_to_irq(udc->vbus_pin), udc);
 		gpio_free(udc->vbus_pin);
+	}
 
 	free_irq(udc->irq, udc);
 	kfree(usba_ep);
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
new file mode 100644
index 0000000..139ac94
--- /dev/null
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -0,0 +1,134 @@
+/* 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/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/ulpi.h>
+
+#include "ci13xxx_udc.c"
+
+#define MSM_USB_BASE	(udc->regs)
+
+static irqreturn_t msm_udc_irq(int irq, void *data)
+{
+	return udc_irq();
+}
+
+static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
+{
+	struct device *dev = udc->gadget.dev.parent;
+	int val;
+
+	switch (event) {
+	case CI13XXX_CONTROLLER_RESET_EVENT:
+		dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
+		writel(0, USB_AHBBURST);
+		writel(0, USB_AHBMODE);
+		break;
+	case CI13XXX_CONTROLLER_STOPPED_EVENT:
+		dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n");
+		/*
+		 * Put the transceiver in non-driving mode. Otherwise host
+		 * may not detect soft-disconnection.
+		 */
+		val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL);
+		val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+		val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+		otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
+		break;
+	default:
+		dev_dbg(dev, "unknown ci13xxx_udc event\n");
+		break;
+	}
+}
+
+static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
+	.name			= "ci13xxx_msm",
+	.flags			= CI13XXX_REGS_SHARED |
+				  CI13XXX_REQUIRE_TRANSCEIVER |
+				  CI13XXX_PULLUP_ON_VBUS |
+				  CI13XXX_DISABLE_STREAMING,
+
+	.notify_event		= ci13xxx_msm_notify_event,
+};
+
+static int ci13xxx_msm_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	void __iomem *regs;
+	int irq;
+	int ret;
+
+	dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get platform resource mem\n");
+		return -ENXIO;
+	}
+
+	regs = ioremap(res->start, resource_size(res));
+	if (!regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		return -ENOMEM;
+	}
+
+	ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, regs);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "udc_probe failed\n");
+		goto iounmap;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "IRQ not found\n");
+		ret = -ENXIO;
+		goto udc_remove;
+	}
+
+	ret = request_irq(irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "request_irq failed\n");
+		goto udc_remove;
+	}
+
+	pm_runtime_no_callbacks(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+udc_remove:
+	udc_remove();
+iounmap:
+	iounmap(regs);
+
+	return ret;
+}
+
+static struct platform_driver ci13xxx_msm_driver = {
+	.probe = ci13xxx_msm_probe,
+	.driver = { .name = "msm_hsusb", },
+};
+
+static int __init ci13xxx_msm_init(void)
+{
+	return platform_driver_register(&ci13xxx_msm_driver);
+}
+module_init(ci13xxx_msm_init);
diff --git a/drivers/usb/gadget/ci13xxx_pci.c b/drivers/usb/gadget/ci13xxx_pci.c
new file mode 100644
index 0000000..883ab5e
--- /dev/null
+++ b/drivers/usb/gadget/ci13xxx_pci.c
@@ -0,0 +1,176 @@
+/*
+ * ci13xxx_pci.c - MIPS USB IP core family device controller
+ *
+ * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
+ *
+ * Author: David Lopo
+ *
+ * This program is free software; you can redistribute 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/pci.h>
+
+#include "ci13xxx_udc.c"
+
+/* driver name */
+#define UDC_DRIVER_NAME   "ci13xxx_pci"
+
+/******************************************************************************
+ * PCI block
+ *****************************************************************************/
+/**
+ * ci13xxx_pci_irq: interrut handler
+ * @irq:  irq number
+ * @pdev: USB Device Controller interrupt source
+ *
+ * This function returns IRQ_HANDLED if the IRQ has been handled
+ * This is an ISR don't trace, use attribute interface instead
+ */
+static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev)
+{
+	if (irq == 0) {
+		dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!");
+		return IRQ_HANDLED;
+	}
+	return udc_irq();
+}
+
+static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = {
+	.name		= UDC_DRIVER_NAME,
+};
+
+/**
+ * ci13xxx_pci_probe: PCI probe
+ * @pdev: USB device controller being probed
+ * @id:   PCI hotplug ID connecting controller to UDC framework
+ *
+ * This function returns an error code
+ * Allocates basic PCI resources for this USB device controller, and then
+ * invokes the udc_probe() method to start the UDC associated with it
+ */
+static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *id)
+{
+	void __iomem *regs = NULL;
+	int retval = 0;
+
+	if (id == NULL)
+		return -EINVAL;
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto done;
+
+	if (!pdev->irq) {
+		dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
+		retval = -ENODEV;
+		goto disable_device;
+	}
+
+	retval = pci_request_regions(pdev, UDC_DRIVER_NAME);
+	if (retval)
+		goto disable_device;
+
+	/* BAR 0 holds all the registers */
+	regs = pci_iomap(pdev, 0, 0);
+	if (!regs) {
+		dev_err(&pdev->dev, "Error mapping memory!");
+		retval = -EFAULT;
+		goto release_regions;
+	}
+	pci_set_drvdata(pdev, (__force void *)regs);
+
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	retval = udc_probe(&ci13xxx_pci_udc_driver, &pdev->dev, regs);
+	if (retval)
+		goto iounmap;
+
+	/* our device does not have MSI capability */
+
+	retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED,
+			     UDC_DRIVER_NAME, pdev);
+	if (retval)
+		goto gadget_remove;
+
+	return 0;
+
+ gadget_remove:
+	udc_remove();
+ iounmap:
+	pci_iounmap(pdev, regs);
+ release_regions:
+	pci_release_regions(pdev);
+ disable_device:
+	pci_disable_device(pdev);
+ done:
+	return retval;
+}
+
+/**
+ * ci13xxx_pci_remove: PCI remove
+ * @pdev: USB Device Controller being removed
+ *
+ * Reverses the effect of ci13xxx_pci_probe(),
+ * first invoking the udc_remove() and then releases
+ * all PCI resources allocated for this USB device controller
+ */
+static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
+{
+	free_irq(pdev->irq, pdev);
+	udc_remove();
+	pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev));
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+/**
+ * PCI device table
+ * PCI device structure
+ *
+ * Check "pci.h" for details
+ */
+static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
+	{ PCI_DEVICE(0x153F, 0x1004) },
+	{ PCI_DEVICE(0x153F, 0x1006) },
+	{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
+
+static struct pci_driver ci13xxx_pci_driver = {
+	.name         =	UDC_DRIVER_NAME,
+	.id_table     =	ci13xxx_pci_id_table,
+	.probe        =	ci13xxx_pci_probe,
+	.remove       =	__devexit_p(ci13xxx_pci_remove),
+};
+
+/**
+ * ci13xxx_pci_init: module init
+ *
+ * Driver load
+ */
+static int __init ci13xxx_pci_init(void)
+{
+	return pci_register_driver(&ci13xxx_pci_driver);
+}
+module_init(ci13xxx_pci_init);
+
+/**
+ * ci13xxx_pci_exit: module exit
+ *
+ * Driver unload
+ */
+static void __exit ci13xxx_pci_exit(void)
+{
+	pci_unregister_driver(&ci13xxx_pci_driver);
+}
+module_exit(ci13xxx_pci_exit);
+
+MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
+MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("June 2008");
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 98b36fc..31656a2 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -22,7 +22,6 @@
  * - ENDPT:  endpoint operations (Gadget API)
  * - GADGET: gadget operations (Gadget API)
  * - BUS:    bus glue code, bus abstraction layer
- * - PCI:    PCI core interface and PCI resources (interrupts, memory...)
  *
  * Compile Options
  * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities
@@ -60,11 +59,11 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 
 #include "ci13xxx_udc.h"
 
@@ -75,9 +74,6 @@
 /* ctrl register bank access */
 static DEFINE_SPINLOCK(udc_lock);
 
-/* driver name */
-#define UDC_DRIVER_NAME   "ci13xxx_udc"
-
 /* control endpoint description */
 static const struct usb_endpoint_descriptor
 ctrl_endpt_desc = {
@@ -132,6 +128,9 @@
 	size_t        size;   /* bank size */
 } hw_bank;
 
+/* MSM specific */
+#define ABS_AHBBURST        (0x0090UL)
+#define ABS_AHBMODE         (0x0098UL)
 /* UDC register map */
 #define ABS_CAPLENGTH       (0x100UL)
 #define ABS_HCCPARAMS       (0x108UL)
@@ -248,13 +247,7 @@
 	return (reg & mask) >> ffs_nr(mask);
 }
 
-/**
- * hw_device_reset: resets chip (execute without interruption)
- * @base: register base address
- *
- * This function returns an error code
- */
-static int hw_device_reset(void __iomem *base)
+static int hw_device_init(void __iomem *base)
 {
 	u32 reg;
 
@@ -271,25 +264,6 @@
 	hw_bank.size += CAP_LAST;
 	hw_bank.size /= sizeof(u32);
 
-	/* should flush & stop before reset */
-	hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
-	hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
-
-	hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
-	while (hw_cread(CAP_USBCMD, USBCMD_RST))
-		udelay(10);             /* not RTOS friendly */
-
-	/* USBMODE should be configured step by step */
-	hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
-	hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
-	hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM);  /* HW >= 2.3 */
-
-	if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
-		pr_err("cannot enter in device mode");
-		pr_err("lpm = %i", hw_bank.lpm);
-		return -ENODEV;
-	}
-
 	reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
 	if (reg == 0 || reg > ENDPT_MAX)
 		return -ENODEV;
@@ -304,6 +278,43 @@
 
 	return 0;
 }
+/**
+ * hw_device_reset: resets chip (execute without interruption)
+ * @base: register base address
+ *
+ * This function returns an error code
+ */
+static int hw_device_reset(struct ci13xxx *udc)
+{
+	/* should flush & stop before reset */
+	hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
+	hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
+
+	hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
+	while (hw_cread(CAP_USBCMD, USBCMD_RST))
+		udelay(10);             /* not RTOS friendly */
+
+
+	if (udc->udc_driver->notify_event)
+		udc->udc_driver->notify_event(udc,
+			CI13XXX_CONTROLLER_RESET_EVENT);
+
+	if (udc->udc_driver->flags && CI13XXX_DISABLE_STREAMING)
+		hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
+
+	/* USBMODE should be configured step by step */
+	hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
+	hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
+	hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM);  /* HW >= 2.3 */
+
+	if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
+		pr_err("cannot enter in device mode");
+		pr_err("lpm = %i", hw_bank.lpm);
+		return -ENODEV;
+	}
+
+	return 0;
+}
 
 /**
  * hw_device_state: enables/disables interrupts & starts/stops device (execute
@@ -1449,7 +1460,7 @@
 	mReq->ptr->page[0]  = mReq->req.dma;
 	for (i = 1; i < 5; i++)
 		mReq->ptr->page[i] =
-			(mReq->req.dma + i * PAGE_SIZE) & ~TD_RESERVED_MASK;
+			(mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
 
 	/*
 	 *  QH configuration
@@ -1540,7 +1551,7 @@
 		list_del_init(&mReq->queue);
 		mReq->req.status = -ESHUTDOWN;
 
-		if (!mReq->req.no_interrupt && mReq->req.complete != NULL) {
+		if (mReq->req.complete != NULL) {
 			spin_unlock(mEp->lock);
 			mReq->req.complete(&mEp->ep, &mReq->req);
 			spin_lock(mEp->lock);
@@ -1557,8 +1568,6 @@
  * Caller must hold lock
  */
 static int _gadget_stop_activity(struct usb_gadget *gadget)
-__releases(udc->lock)
-__acquires(udc->lock)
 {
 	struct usb_ep *ep;
 	struct ci13xxx    *udc = container_of(gadget, struct ci13xxx, gadget);
@@ -1570,8 +1579,6 @@
 	if (gadget == NULL)
 		return -EINVAL;
 
-	spin_unlock(udc->lock);
-
 	/* flush all endpoints */
 	gadget_for_each_ep(ep, gadget) {
 		usb_ep_fifo_flush(ep);
@@ -1591,8 +1598,6 @@
 		mEp->status = NULL;
 	}
 
-	spin_lock(udc->lock);
-
 	return 0;
 }
 
@@ -1621,6 +1626,7 @@
 
 	dbg_event(0xFF, "BUS RST", 0);
 
+	spin_unlock(udc->lock);
 	retval = _gadget_stop_activity(&udc->gadget);
 	if (retval)
 		goto done;
@@ -1629,10 +1635,9 @@
 	if (retval)
 		goto done;
 
-	spin_unlock(udc->lock);
 	retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc);
 	if (!retval) {
-		mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_KERNEL);
+		mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_ATOMIC);
 		if (mEp->status == NULL) {
 			usb_ep_disable(&mEp->ep);
 			retval = -ENOMEM;
@@ -1789,18 +1794,20 @@
 
 	dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
 
-	if (!mReq->req.no_interrupt && mReq->req.complete != NULL) {
+	if (!list_empty(&mEp->qh[mEp->dir].queue)) {
+		struct ci13xxx_req* mReqEnq;
+
+		mReqEnq = list_entry(mEp->qh[mEp->dir].queue.next,
+				  struct ci13xxx_req, queue);
+		_hardware_enqueue(mEp, mReqEnq);
+	}
+
+	if (mReq->req.complete != NULL) {
 		spin_unlock(mEp->lock);
 		mReq->req.complete(&mEp->ep, &mReq->req);
 		spin_lock(mEp->lock);
 	}
 
-	if (!list_empty(&mEp->qh[mEp->dir].queue)) {
-		mReq = list_entry(mEp->qh[mEp->dir].queue.next,
-				  struct ci13xxx_req, queue);
-		_hardware_enqueue(mEp, mReq);
-	}
-
  done:
 	return retval;
 }
@@ -2061,7 +2068,6 @@
 {
 	struct ci13xxx_ep  *mEp  = container_of(ep, struct ci13xxx_ep, ep);
 	struct ci13xxx_req *mReq = NULL;
-	unsigned long flags;
 
 	trace("%p, %i", ep, gfp_flags);
 
@@ -2070,8 +2076,6 @@
 		return NULL;
 	}
 
-	spin_lock_irqsave(mEp->lock, flags);
-
 	mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
 	if (mReq != NULL) {
 		INIT_LIST_HEAD(&mReq->queue);
@@ -2086,8 +2090,6 @@
 
 	dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
 
-	spin_unlock_irqrestore(mEp->lock, flags);
-
 	return (mReq == NULL) ? NULL : &mReq->req;
 }
 
@@ -2157,8 +2159,8 @@
 		goto done;
 	}
 
-	if (req->length > (4 * PAGE_SIZE)) {
-		req->length = (4 * PAGE_SIZE);
+	if (req->length > (4 * CI13XXX_PAGE_SIZE)) {
+		req->length = (4 * CI13XXX_PAGE_SIZE);
 		retval = -EMSGSIZE;
 		warn("request length truncated");
 	}
@@ -2170,8 +2172,10 @@
 	mReq->req.actual = 0;
 	list_add_tail(&mReq->queue, &mEp->qh[mEp->dir].queue);
 
-	retval = _hardware_enqueue(mEp, mReq);
-	if (retval == -EALREADY || retval == -EBUSY) {
+	if (list_is_singular(&mEp->qh[mEp->dir].queue))
+		retval = _hardware_enqueue(mEp, mReq);
+
+	if (retval == -EALREADY) {
 		dbg_event(_usb_addr(mEp), "QUEUE", retval);
 		retval = 0;
 	}
@@ -2209,7 +2213,7 @@
 	list_del_init(&mReq->queue);
 	req->status = -ECONNRESET;
 
-	if (!mReq->req.no_interrupt && mReq->req.complete != NULL) {
+	if (mReq->req.complete != NULL) {
 		spin_unlock(mEp->lock);
 		mReq->req.complete(&mEp->ep, &mReq->req);
 		spin_lock(mEp->lock);
@@ -2332,12 +2336,47 @@
 /******************************************************************************
  * GADGET block
  *****************************************************************************/
+static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+	unsigned long flags;
+	int gadget_ready = 0;
+
+	if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS))
+		return -EOPNOTSUPP;
+
+	spin_lock_irqsave(udc->lock, flags);
+	udc->vbus_active = is_active;
+	if (udc->driver)
+		gadget_ready = 1;
+	spin_unlock_irqrestore(udc->lock, flags);
+
+	if (gadget_ready) {
+		if (is_active) {
+			pm_runtime_get_sync(&_gadget->dev);
+			hw_device_reset(udc);
+			hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma);
+		} else {
+			hw_device_state(0);
+			if (udc->udc_driver->notify_event)
+				udc->udc_driver->notify_event(udc,
+				CI13XXX_CONTROLLER_STOPPED_EVENT);
+			_gadget_stop_activity(&udc->gadget);
+			pm_runtime_put_sync(&_gadget->dev);
+		}
+	}
+
+	return 0;
+}
+
 /**
  * Device operations part of the API to the USB controller hardware,
  * which don't involve endpoints (or i/o)
  * Check  "usb_gadget.h" for details
  */
-static const struct usb_gadget_ops usb_gadget_ops;
+static const struct usb_gadget_ops usb_gadget_ops = {
+	.vbus_session	= ci13xxx_vbus_session,
+};
 
 /**
  * usb_gadget_probe_driver: register a gadget driver
@@ -2358,7 +2397,6 @@
 
 	if (driver             == NULL ||
 	    bind               == NULL ||
-	    driver->unbind     == NULL ||
 	    driver->setup      == NULL ||
 	    driver->disconnect == NULL ||
 	    driver->suspend    == NULL ||
@@ -2372,13 +2410,13 @@
 	/* alloc resources */
 	udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
 				       sizeof(struct ci13xxx_qh),
-				       64, PAGE_SIZE);
+				       64, CI13XXX_PAGE_SIZE);
 	if (udc->qh_pool == NULL)
 		return -ENOMEM;
 
 	udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
 				       sizeof(struct ci13xxx_td),
-				       64, PAGE_SIZE);
+				       64, CI13XXX_PAGE_SIZE);
 	if (udc->td_pool == NULL) {
 		dma_pool_destroy(udc->qh_pool);
 		udc->qh_pool = NULL;
@@ -2390,7 +2428,6 @@
 	info("hw_ep_max = %d", hw_ep_max);
 
 	udc->driver = driver;
-	udc->gadget.ops        = NULL;
 	udc->gadget.dev.driver = NULL;
 
 	retval = 0;
@@ -2410,9 +2447,11 @@
 		/* this allocation cannot be random */
 		for (k = RX; k <= TX; k++) {
 			INIT_LIST_HEAD(&mEp->qh[k].queue);
+			spin_unlock_irqrestore(udc->lock, flags);
 			mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool,
 							GFP_KERNEL,
 							&mEp->qh[k].dma);
+			spin_lock_irqsave(udc->lock, flags);
 			if (mEp->qh[k].ptr == NULL)
 				retval = -ENOMEM;
 			else
@@ -2429,7 +2468,6 @@
 
 	/* bind gadget */
 	driver->driver.bus     = NULL;
-	udc->gadget.ops        = &usb_gadget_ops;
 	udc->gadget.dev.driver = &driver->driver;
 
 	spin_unlock_irqrestore(udc->lock, flags);
@@ -2437,12 +2475,24 @@
 	spin_lock_irqsave(udc->lock, flags);
 
 	if (retval) {
-		udc->gadget.ops        = NULL;
 		udc->gadget.dev.driver = NULL;
 		goto done;
 	}
 
+	pm_runtime_get_sync(&udc->gadget.dev);
+	if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
+		if (udc->vbus_active) {
+			if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
+				hw_device_reset(udc);
+		} else {
+			pm_runtime_put_sync(&udc->gadget.dev);
+			goto done;
+		}
+	}
+
 	retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma);
+	if (retval)
+		pm_runtime_put_sync(&udc->gadget.dev);
 
  done:
 	spin_unlock_irqrestore(udc->lock, flags);
@@ -2475,19 +2525,22 @@
 
 	spin_lock_irqsave(udc->lock, flags);
 
-	hw_device_state(0);
+	if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
+			udc->vbus_active) {
+		hw_device_state(0);
+		if (udc->udc_driver->notify_event)
+			udc->udc_driver->notify_event(udc,
+			CI13XXX_CONTROLLER_STOPPED_EVENT);
+		_gadget_stop_activity(&udc->gadget);
+		pm_runtime_put(&udc->gadget.dev);
+	}
 
 	/* unbind gadget */
-	if (udc->gadget.ops != NULL) {
-		_gadget_stop_activity(&udc->gadget);
+	spin_unlock_irqrestore(udc->lock, flags);
+	driver->unbind(&udc->gadget);               /* MAY SLEEP */
+	spin_lock_irqsave(udc->lock, flags);
 
-		spin_unlock_irqrestore(udc->lock, flags);
-		driver->unbind(&udc->gadget);               /* MAY SLEEP */
-		spin_lock_irqsave(udc->lock, flags);
-
-		udc->gadget.ops        = NULL;
-		udc->gadget.dev.driver = NULL;
-	}
+	udc->gadget.dev.driver = NULL;
 
 	/* free resources */
 	for (i = 0; i < hw_ep_max; i++) {
@@ -2544,6 +2597,14 @@
 	}
 
 	spin_lock(udc->lock);
+
+	if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
+		if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
+				USBMODE_CM_DEVICE) {
+			spin_unlock(udc->lock);
+			return IRQ_NONE;
+		}
+	}
 	intr = hw_test_and_clear_intr_active();
 	if (intr) {
 		isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr;
@@ -2602,14 +2663,16 @@
  * No interrupts active, the IRQ has not been requested yet
  * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
  */
-static int udc_probe(struct device *dev, void __iomem *regs, const char *name)
+static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
+		void __iomem *regs)
 {
 	struct ci13xxx *udc;
 	int retval = 0;
 
 	trace("%p, %p, %p", dev, regs, name);
 
-	if (dev == NULL || regs == NULL || name == NULL)
+	if (dev == NULL || regs == NULL || driver == NULL ||
+			driver->name == NULL)
 		return -EINVAL;
 
 	udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL);
@@ -2617,42 +2680,77 @@
 		return -ENOMEM;
 
 	udc->lock = &udc_lock;
+	udc->regs = regs;
+	udc->udc_driver = driver;
 
-	retval = hw_device_reset(regs);
-	if (retval)
-		goto done;
-
-	udc->gadget.ops          = NULL;
+	udc->gadget.ops          = &usb_gadget_ops;
 	udc->gadget.speed        = USB_SPEED_UNKNOWN;
 	udc->gadget.is_dualspeed = 1;
 	udc->gadget.is_otg       = 0;
-	udc->gadget.name         = name;
+	udc->gadget.name         = driver->name;
 
 	INIT_LIST_HEAD(&udc->gadget.ep_list);
 	udc->gadget.ep0 = NULL;
 
 	dev_set_name(&udc->gadget.dev, "gadget");
 	udc->gadget.dev.dma_mask = dev->dma_mask;
+	udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
 	udc->gadget.dev.parent   = dev;
 	udc->gadget.dev.release  = udc_release;
 
+	retval = hw_device_init(regs);
+	if (retval < 0)
+		goto free_udc;
+
+	udc->transceiver = otg_get_transceiver();
+
+	if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
+		if (udc->transceiver == NULL) {
+			retval = -ENODEV;
+			goto free_udc;
+		}
+	}
+
+	if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
+		retval = hw_device_reset(udc);
+		if (retval)
+			goto put_transceiver;
+	}
+
 	retval = device_register(&udc->gadget.dev);
-	if (retval)
-		goto done;
+	if (retval) {
+		put_device(&udc->gadget.dev);
+		goto put_transceiver;
+	}
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	retval = dbg_create_files(&udc->gadget.dev);
 #endif
-	if (retval) {
-		device_unregister(&udc->gadget.dev);
-		goto done;
+	if (retval)
+		goto unreg_device;
+
+	if (udc->transceiver) {
+		retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
+		if (retval)
+			goto remove_dbg;
 	}
+	pm_runtime_no_callbacks(&udc->gadget.dev);
+	pm_runtime_enable(&udc->gadget.dev);
 
 	_udc = udc;
 	return retval;
 
- done:
 	err("error = %i", retval);
+remove_dbg:
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+	dbg_remove_files(&udc->gadget.dev);
+#endif
+unreg_device:
+	device_unregister(&udc->gadget.dev);
+put_transceiver:
+	if (udc->transceiver)
+		otg_put_transceiver(udc->transceiver);
+free_udc:
 	kfree(udc);
 	_udc = NULL;
 	return retval;
@@ -2672,6 +2770,10 @@
 		return;
 	}
 
+	if (udc->transceiver) {
+		otg_set_peripheral(udc->transceiver, &udc->gadget);
+		otg_put_transceiver(udc->transceiver);
+	}
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	dbg_remove_files(&udc->gadget.dev);
 #endif
@@ -2680,156 +2782,3 @@
 	kfree(udc);
 	_udc = NULL;
 }
-
-/******************************************************************************
- * PCI block
- *****************************************************************************/
-/**
- * ci13xxx_pci_irq: interrut handler
- * @irq:  irq number
- * @pdev: USB Device Controller interrupt source
- *
- * This function returns IRQ_HANDLED if the IRQ has been handled
- * This is an ISR don't trace, use attribute interface instead
- */
-static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev)
-{
-	if (irq == 0) {
-		dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!");
-		return IRQ_HANDLED;
-	}
-	return udc_irq();
-}
-
-/**
- * ci13xxx_pci_probe: PCI probe
- * @pdev: USB device controller being probed
- * @id:   PCI hotplug ID connecting controller to UDC framework
- *
- * This function returns an error code
- * Allocates basic PCI resources for this USB device controller, and then
- * invokes the udc_probe() method to start the UDC associated with it
- */
-static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
-				       const struct pci_device_id *id)
-{
-	void __iomem *regs = NULL;
-	int retval = 0;
-
-	if (id == NULL)
-		return -EINVAL;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto done;
-
-	if (!pdev->irq) {
-		dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
-		retval = -ENODEV;
-		goto disable_device;
-	}
-
-	retval = pci_request_regions(pdev, UDC_DRIVER_NAME);
-	if (retval)
-		goto disable_device;
-
-	/* BAR 0 holds all the registers */
-	regs = pci_iomap(pdev, 0, 0);
-	if (!regs) {
-		dev_err(&pdev->dev, "Error mapping memory!");
-		retval = -EFAULT;
-		goto release_regions;
-	}
-	pci_set_drvdata(pdev, (__force void *)regs);
-
-	pci_set_master(pdev);
-	pci_try_set_mwi(pdev);
-
-	retval = udc_probe(&pdev->dev, regs, UDC_DRIVER_NAME);
-	if (retval)
-		goto iounmap;
-
-	/* our device does not have MSI capability */
-
-	retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED,
-			     UDC_DRIVER_NAME, pdev);
-	if (retval)
-		goto gadget_remove;
-
-	return 0;
-
- gadget_remove:
-	udc_remove();
- iounmap:
-	pci_iounmap(pdev, regs);
- release_regions:
-	pci_release_regions(pdev);
- disable_device:
-	pci_disable_device(pdev);
- done:
-	return retval;
-}
-
-/**
- * ci13xxx_pci_remove: PCI remove
- * @pdev: USB Device Controller being removed
- *
- * Reverses the effect of ci13xxx_pci_probe(),
- * first invoking the udc_remove() and then releases
- * all PCI resources allocated for this USB device controller
- */
-static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
-{
-	free_irq(pdev->irq, pdev);
-	udc_remove();
-	pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev));
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-}
-
-/**
- * PCI device table
- * PCI device structure
- *
- * Check "pci.h" for details
- */
-static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
-	{ PCI_DEVICE(0x153F, 0x1004) },
-	{ PCI_DEVICE(0x153F, 0x1006) },
-	{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
-
-static struct pci_driver ci13xxx_pci_driver = {
-	.name         =	UDC_DRIVER_NAME,
-	.id_table     =	ci13xxx_pci_id_table,
-	.probe        =	ci13xxx_pci_probe,
-	.remove       =	__devexit_p(ci13xxx_pci_remove),
-};
-
-/**
- * ci13xxx_pci_init: module init
- *
- * Driver load
- */
-static int __init ci13xxx_pci_init(void)
-{
-	return pci_register_driver(&ci13xxx_pci_driver);
-}
-module_init(ci13xxx_pci_init);
-
-/**
- * ci13xxx_pci_exit: module exit
- *
- * Driver unload
- */
-static void __exit ci13xxx_pci_exit(void)
-{
-	pci_unregister_driver(&ci13xxx_pci_driver);
-}
-module_exit(ci13xxx_pci_exit);
-
-MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
-MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("June 2008");
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 4026e9c..f61fed0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -19,6 +19,7 @@
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
+#define CI13XXX_PAGE_SIZE  4096ul /* page size for TD's */
 #define ENDPT_MAX          (16)
 #define CTRL_PAYLOAD_MAX   (64)
 #define RX        (0)  /* similar to USB_DIR_OUT but can be used as an index */
@@ -97,9 +98,24 @@
 	struct dma_pool                       *td_pool;
 };
 
+struct ci13xxx;
+struct ci13xxx_udc_driver {
+	const char	*name;
+	unsigned long	 flags;
+#define CI13XXX_REGS_SHARED		BIT(0)
+#define CI13XXX_REQUIRE_TRANSCEIVER	BIT(1)
+#define CI13XXX_PULLUP_ON_VBUS		BIT(2)
+#define CI13XXX_DISABLE_STREAMING	BIT(3)
+
+#define CI13XXX_CONTROLLER_RESET_EVENT		0
+#define CI13XXX_CONTROLLER_STOPPED_EVENT	1
+	void	(*notify_event) (struct ci13xxx *udc, unsigned event);
+};
+
 /* CI13XXX UDC descriptor & global resources */
 struct ci13xxx {
 	spinlock_t		  *lock;      /* ctrl register bank access */
+	void __iomem              *regs;      /* registers address space */
 
 	struct dma_pool           *qh_pool;   /* DMA pool for queue heads */
 	struct dma_pool           *td_pool;   /* DMA pool for transfer descs */
@@ -108,6 +124,9 @@
 	struct ci13xxx_ep          ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
 
 	struct usb_gadget_driver  *driver;     /* 3rd party gadget driver */
+	struct ci13xxx_udc_driver *udc_driver; /* device controller driver */
+	int                        vbus_active; /* is VBUS active */
+	struct otg_transceiver    *transceiver; /* Transceiver struct */
 };
 
 /******************************************************************************
@@ -157,6 +176,7 @@
 #define    USBMODE_CM_DEVICE  (0x02UL <<  0)
 #define    USBMODE_CM_HOST    (0x03UL <<  0)
 #define USBMODE_SLOM          BIT(3)
+#define USBMODE_SDIS          BIT(4)
 
 /* ENDPTCTRL */
 #define ENDPTCTRL_RXS         BIT(0)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 8572dad..f6ff845 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1126,7 +1126,7 @@
 	if (bcdDevice)
 		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
 
-	/* stirng overrides */
+	/* string overrides */
 	if (iManufacturer || !cdev->desc.iManufacturer) {
 		if (!iManufacturer && !composite->iManufacturer &&
 		    !*composite_manufacturer)
@@ -1188,6 +1188,8 @@
 		composite->suspend(cdev);
 
 	cdev->suspended = 1;
+
+	usb_gadget_vbus_draw(gadget, 2);
 }
 
 static void
@@ -1195,6 +1197,7 @@
 {
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	struct usb_function		*f;
+	u8				maxpower;
 
 	/* REVISIT:  should we have config level
 	 * suspend/resume callbacks?
@@ -1207,6 +1210,11 @@
 			if (f->resume)
 				f->resume(f);
 		}
+
+		maxpower = cdev->config->bMaxPower;
+
+		usb_gadget_vbus_draw(gadget, maxpower ?
+			(2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW);
 	}
 
 	cdev->suspended = 0;
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 1d2a2ab..13b9f47 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1197,6 +1197,139 @@
 #define Ep_Request	(USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
 #define Ep_InRequest	(Ep_Request | USB_DIR_IN)
 
+
+/**
+ * handle_control_request() - handles all control transfers
+ * @dum: pointer to dummy (the_controller)
+ * @urb: the urb request to handle
+ * @setup: pointer to the setup data for a USB device control
+ *	 request
+ * @status: pointer to request handling status
+ *
+ * Return 0 - if the request was handled
+ *	  1 - if the request wasn't handles
+ *	  error code on error
+ */
+static int handle_control_request(struct dummy *dum, struct urb *urb,
+				  struct usb_ctrlrequest *setup,
+				  int *status)
+{
+	struct dummy_ep		*ep2;
+	int			ret_val = 1;
+	unsigned	w_index;
+	unsigned	w_value;
+
+	w_index = le16_to_cpu(setup->wIndex);
+	w_value = le16_to_cpu(setup->wValue);
+	switch (setup->bRequest) {
+	case USB_REQ_SET_ADDRESS:
+		if (setup->bRequestType != Dev_Request)
+			break;
+		dum->address = w_value;
+		*status = 0;
+		dev_dbg(udc_dev(dum), "set_address = %d\n",
+				w_value);
+		ret_val = 0;
+		break;
+	case USB_REQ_SET_FEATURE:
+		if (setup->bRequestType == Dev_Request) {
+			ret_val = 0;
+			switch (w_value) {
+			case USB_DEVICE_REMOTE_WAKEUP:
+				break;
+			case USB_DEVICE_B_HNP_ENABLE:
+				dum->gadget.b_hnp_enable = 1;
+				break;
+			case USB_DEVICE_A_HNP_SUPPORT:
+				dum->gadget.a_hnp_support = 1;
+				break;
+			case USB_DEVICE_A_ALT_HNP_SUPPORT:
+				dum->gadget.a_alt_hnp_support = 1;
+				break;
+			default:
+				ret_val = -EOPNOTSUPP;
+			}
+			if (ret_val == 0) {
+				dum->devstatus |= (1 << w_value);
+				*status = 0;
+			}
+		} else if (setup->bRequestType == Ep_Request) {
+			/* endpoint halt */
+			ep2 = find_endpoint(dum, w_index);
+			if (!ep2 || ep2->ep.name == ep0name) {
+				ret_val = -EOPNOTSUPP;
+				break;
+			}
+			ep2->halted = 1;
+			ret_val = 0;
+			*status = 0;
+		}
+		break;
+	case USB_REQ_CLEAR_FEATURE:
+		if (setup->bRequestType == Dev_Request) {
+			ret_val = 0;
+			switch (w_value) {
+			case USB_DEVICE_REMOTE_WAKEUP:
+				w_value = USB_DEVICE_REMOTE_WAKEUP;
+				break;
+			default:
+				ret_val = -EOPNOTSUPP;
+				break;
+			}
+			if (ret_val == 0) {
+				dum->devstatus &= ~(1 << w_value);
+				*status = 0;
+			}
+		} else if (setup->bRequestType == Ep_Request) {
+			/* endpoint halt */
+			ep2 = find_endpoint(dum, w_index);
+			if (!ep2) {
+				ret_val = -EOPNOTSUPP;
+				break;
+			}
+			if (!ep2->wedged)
+				ep2->halted = 0;
+			ret_val = 0;
+			*status = 0;
+		}
+		break;
+	case USB_REQ_GET_STATUS:
+		if (setup->bRequestType == Dev_InRequest
+				|| setup->bRequestType == Intf_InRequest
+				|| setup->bRequestType == Ep_InRequest) {
+			char *buf;
+			/*
+			 * device: remote wakeup, selfpowered
+			 * interface: nothing
+			 * endpoint: halt
+			 */
+			buf = (char *)urb->transfer_buffer;
+			if (urb->transfer_buffer_length > 0) {
+				if (setup->bRequestType == Ep_InRequest) {
+					ep2 = find_endpoint(dum, w_index);
+					if (!ep2) {
+						ret_val = -EOPNOTSUPP;
+						break;
+					}
+					buf[0] = ep2->halted;
+				} else if (setup->bRequestType ==
+					   Dev_InRequest) {
+					buf[0] = (u8)dum->devstatus;
+				} else
+					buf[0] = 0;
+			}
+			if (urb->transfer_buffer_length > 1)
+				buf[1] = 0;
+			urb->actual_length = min_t(u32, 2,
+				urb->transfer_buffer_length);
+			ret_val = 0;
+			*status = 0;
+		}
+		break;
+	}
+	return ret_val;
+}
+
 /* drive both sides of the transfers; looks like irq handlers to
  * both drivers except the callbacks aren't in_irq().
  */
@@ -1299,14 +1432,8 @@
 		if (ep == &dum->ep [0] && ep->setup_stage) {
 			struct usb_ctrlrequest		setup;
 			int				value = 1;
-			struct dummy_ep			*ep2;
-			unsigned			w_index;
-			unsigned			w_value;
 
 			setup = *(struct usb_ctrlrequest*) urb->setup_packet;
-			w_index = le16_to_cpu(setup.wIndex);
-			w_value = le16_to_cpu(setup.wValue);
-
 			/* paranoia, in case of stale queued data */
 			list_for_each_entry (req, &ep->queue, queue) {
 				list_del_init (&req->queue);
@@ -1328,117 +1455,9 @@
 			ep->last_io = jiffies;
 			ep->setup_stage = 0;
 			ep->halted = 0;
-			switch (setup.bRequest) {
-			case USB_REQ_SET_ADDRESS:
-				if (setup.bRequestType != Dev_Request)
-					break;
-				dum->address = w_value;
-				status = 0;
-				dev_dbg (udc_dev(dum), "set_address = %d\n",
-						w_value);
-				value = 0;
-				break;
-			case USB_REQ_SET_FEATURE:
-				if (setup.bRequestType == Dev_Request) {
-					value = 0;
-					switch (w_value) {
-					case USB_DEVICE_REMOTE_WAKEUP:
-						break;
-					case USB_DEVICE_B_HNP_ENABLE:
-						dum->gadget.b_hnp_enable = 1;
-						break;
-					case USB_DEVICE_A_HNP_SUPPORT:
-						dum->gadget.a_hnp_support = 1;
-						break;
-					case USB_DEVICE_A_ALT_HNP_SUPPORT:
-						dum->gadget.a_alt_hnp_support
-							= 1;
-						break;
-					default:
-						value = -EOPNOTSUPP;
-					}
-					if (value == 0) {
-						dum->devstatus |=
-							(1 << w_value);
-						status = 0;
-					}
 
-				} else if (setup.bRequestType == Ep_Request) {
-					// endpoint halt
-					ep2 = find_endpoint (dum, w_index);
-					if (!ep2 || ep2->ep.name == ep0name) {
-						value = -EOPNOTSUPP;
-						break;
-					}
-					ep2->halted = 1;
-					value = 0;
-					status = 0;
-				}
-				break;
-			case USB_REQ_CLEAR_FEATURE:
-				if (setup.bRequestType == Dev_Request) {
-					switch (w_value) {
-					case USB_DEVICE_REMOTE_WAKEUP:
-						dum->devstatus &= ~(1 <<
-							USB_DEVICE_REMOTE_WAKEUP);
-						value = 0;
-						status = 0;
-						break;
-					default:
-						value = -EOPNOTSUPP;
-						break;
-					}
-				} else if (setup.bRequestType == Ep_Request) {
-					// endpoint halt
-					ep2 = find_endpoint (dum, w_index);
-					if (!ep2) {
-						value = -EOPNOTSUPP;
-						break;
-					}
-					if (!ep2->wedged)
-						ep2->halted = 0;
-					value = 0;
-					status = 0;
-				}
-				break;
-			case USB_REQ_GET_STATUS:
-				if (setup.bRequestType == Dev_InRequest
-						|| setup.bRequestType
-							== Intf_InRequest
-						|| setup.bRequestType
-							== Ep_InRequest
-						) {
-					char *buf;
-
-					// device: remote wakeup, selfpowered
-					// interface: nothing
-					// endpoint: halt
-					buf = (char *)urb->transfer_buffer;
-					if (urb->transfer_buffer_length > 0) {
-						if (setup.bRequestType ==
-								Ep_InRequest) {
-	ep2 = find_endpoint (dum, w_index);
-	if (!ep2) {
-		value = -EOPNOTSUPP;
-		break;
-	}
-	buf [0] = ep2->halted;
-						} else if (setup.bRequestType ==
-								Dev_InRequest) {
-							buf [0] = (u8)
-								dum->devstatus;
-						} else
-							buf [0] = 0;
-					}
-					if (urb->transfer_buffer_length > 1)
-						buf [1] = 0;
-					urb->actual_length = min_t(u32, 2,
-						urb->transfer_buffer_length);
-					value = 0;
-					status = 0;
-				}
-				break;
-			}
+			value = handle_control_request(dum, urb, &setup,
+						       &status);
 
 			/* gadget driver handles all other requests.  block
 			 * until setup() returns; no reentrancy issues etc.
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 484c5ba..1499f9e 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1,10 +1,10 @@
 /*
- * f_fs.c -- user mode filesystem api for usb composite funtcion controllers
+ * f_fs.c -- user mode file system API for USB composite function controllers
  *
  * Copyright (C) 2010 Samsung Electronics
  * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
  *
- * Based on inode.c (GadgetFS):
+ * Based on inode.c (GadgetFS) which was:
  * Copyright (C) 2003-2004 David Brownell
  * Copyright (C) 2003 Agilent Technologies
  *
@@ -38,62 +38,56 @@
 #define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */
 
 
-/* Debuging *****************************************************************/
-
-#define ffs_printk(level, fmt, args...) printk(level "f_fs: " fmt "\n", ## args)
-
-#define FERR(...)  ffs_printk(KERN_ERR,  __VA_ARGS__)
-#define FINFO(...) ffs_printk(KERN_INFO, __VA_ARGS__)
-
-#ifdef DEBUG
-#  define FDBG(...) ffs_printk(KERN_DEBUG, __VA_ARGS__)
-#else
-#  define FDBG(...) do { } while (0)
-#endif /* DEBUG */
+/* Debugging ****************************************************************/
 
 #ifdef VERBOSE_DEBUG
-#  define FVDBG FDBG
+#  define pr_vdebug pr_debug
+#  define ffs_dump_mem(prefix, ptr, len) \
+	print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
 #else
-#  define FVDBG(...) do { } while (0)
+#  define pr_vdebug(...)                 do { } while (0)
+#  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
 #endif /* VERBOSE_DEBUG */
 
-#define ENTER()    FVDBG("%s()", __func__)
-
-#ifdef VERBOSE_DEBUG
-#  define ffs_dump_mem(prefix, ptr, len) \
-	print_hex_dump_bytes("f_fs" prefix ": ", DUMP_PREFIX_NONE, ptr, len)
-#else
-#  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
-#endif
+#define ENTER()    pr_vdebug("%s()\n", __func__)
 
 
 /* The data structure and setup file ****************************************/
 
 enum ffs_state {
-	/* Waiting for descriptors and strings. */
-	/* In this state no open(2), read(2) or write(2) on epfiles
+	/*
+	 * Waiting for descriptors and strings.
+	 *
+	 * In this state no open(2), read(2) or write(2) on epfiles
 	 * may succeed (which should not be the problem as there
-	 * should be no such files opened in the firts place). */
+	 * should be no such files opened in the first place).
+	 */
 	FFS_READ_DESCRIPTORS,
 	FFS_READ_STRINGS,
 
-	/* We've got descriptors and strings.  We are or have called
+	/*
+	 * We've got descriptors and strings.  We are or have called
 	 * functionfs_ready_callback().  functionfs_bind() may have
-	 * been called but we don't know. */
-	/* This is the only state in which operations on epfiles may
-	 * succeed. */
+	 * been called but we don't know.
+	 *
+	 * This is the only state in which operations on epfiles may
+	 * succeed.
+	 */
 	FFS_ACTIVE,
 
-	/* All endpoints have been closed.  This state is also set if
+	/*
+	 * All endpoints have been closed.  This state is also set if
 	 * we encounter an unrecoverable error.  The only
 	 * unrecoverable error is situation when after reading strings
-	 * from user space we fail to initialise EP files or
-	 * functionfs_ready_callback() returns with error (<0). */
-	/* In this state no open(2), read(2) or write(2) (both on ep0
+	 * from user space we fail to initialise epfiles or
+	 * functionfs_ready_callback() returns with error (<0).
+	 *
+	 * In this state no open(2), read(2) or write(2) (both on ep0
 	 * as well as epfile) may succeed (at this point epfiles are
 	 * unlinked and all closed so this is not a problem; ep0 is
 	 * also closed but ep0 file exists and so open(2) on ep0 must
-	 * fail). */
+	 * fail).
+	 */
 	FFS_CLOSING
 };
 
@@ -101,14 +95,18 @@
 enum ffs_setup_state {
 	/* There is no setup request pending. */
 	FFS_NO_SETUP,
-	/* User has read events and there was a setup request event
+	/*
+	 * User has read events and there was a setup request event
 	 * there.  The next read/write on ep0 will handle the
-	 * request. */
+	 * request.
+	 */
 	FFS_SETUP_PENDING,
-	/* There was event pending but before user space handled it
+	/*
+	 * There was event pending but before user space handled it
 	 * some other event was introduced which canceled existing
 	 * setup.  If this state is set read/write on ep0 return
-	 * -EIDRM.  This state is only set when adding event. */
+	 * -EIDRM.  This state is only set when adding event.
+	 */
 	FFS_SETUP_CANCELED
 };
 
@@ -120,23 +118,29 @@
 struct ffs_data {
 	struct usb_gadget		*gadget;
 
-	/* Protect access read/write operations, only one read/write
+	/*
+	 * Protect access read/write operations, only one read/write
 	 * at a time.  As a consequence protects ep0req and company.
 	 * While setup request is being processed (queued) this is
-	 * held. */
+	 * held.
+	 */
 	struct mutex			mutex;
 
-	/* Protect access to enpoint related structures (basically
+	/*
+	 * Protect access to endpoint related structures (basically
 	 * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for
-	 * endpint zero. */
+	 * endpoint zero.
+	 */
 	spinlock_t			eps_lock;
 
-	/* XXX REVISIT do we need our own request? Since we are not
-	 * handling setup requests immidiatelly user space may be so
+	/*
+	 * XXX REVISIT do we need our own request? Since we are not
+	 * handling setup requests immediately user space may be so
 	 * slow that another setup will be sent to the gadget but this
 	 * time not to us but another function and then there could be
 	 * a race.  Is that the case? Or maybe we can use cdev->req
-	 * after all, maybe we just need some spinlock for that? */
+	 * after all, maybe we just need some spinlock for that?
+	 */
 	struct usb_request		*ep0req;		/* P: mutex */
 	struct completion		ep0req_completion;	/* P: mutex */
 	int				ep0req_status;		/* P: mutex */
@@ -150,7 +154,7 @@
 	enum ffs_state			state;
 
 	/*
-	 * Possible transations:
+	 * Possible transitions:
 	 * + FFS_NO_SETUP       -> FFS_SETUP_PENDING  -- P: ev.waitq.lock
 	 *               happens only in ep0 read which is P: mutex
 	 * + FFS_SETUP_PENDING  -> FFS_NO_SETUP       -- P: ev.waitq.lock
@@ -183,18 +187,21 @@
 	/* Active function */
 	struct ffs_function		*func;
 
-	/* Device name, write once when file system is mounted.
-	 * Intendet for user to read if she wants. */
+	/*
+	 * Device name, write once when file system is mounted.
+	 * Intended for user to read if she wants.
+	 */
 	const char			*dev_name;
-	/* Private data for our user (ie. gadget).  Managed by
-	 * user. */
+	/* Private data for our user (ie. gadget).  Managed by user. */
 	void				*private_data;
 
 	/* filled by __ffs_data_got_descs() */
-	/* real descriptors are 16 bytes after raw_descs (so you need
+	/*
+	 * Real descriptors are 16 bytes after raw_descs (so you need
 	 * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the
 	 * first full speed descriptor).  raw_descs_length and
-	 * raw_fs_descs_length do not have those 16 bytes added. */
+	 * raw_fs_descs_length do not have those 16 bytes added.
+	 */
 	const void			*raw_descs;
 	unsigned			raw_descs_length;
 	unsigned			raw_fs_descs_length;
@@ -211,18 +218,23 @@
 	const void			*raw_strings;
 	struct usb_gadget_strings	**stringtabs;
 
-	/* File system's super block, write once when file system is mounted. */
+	/*
+	 * File system's super block, write once when file system is
+	 * mounted.
+	 */
 	struct super_block		*sb;
 
-	/* File permissions, written once when fs is mounted*/
+	/* File permissions, written once when fs is mounted */
 	struct ffs_file_perms {
 		umode_t				mode;
 		uid_t				uid;
 		gid_t				gid;
 	}				file_perms;
 
-	/* The endpoint files, filled by ffs_epfiles_create(),
-	 * destroyed by ffs_epfiles_destroy(). */
+	/*
+	 * The endpoint files, filled by ffs_epfiles_create(),
+	 * destroyed by ffs_epfiles_destroy().
+	 */
 	struct ffs_epfile		*epfiles;
 };
 
@@ -236,7 +248,7 @@
 static void ffs_data_opened(struct ffs_data *ffs);
 static void ffs_data_closed(struct ffs_data *ffs);
 
-/* Called with ffs->mutex held; take over ownerrship of data. */
+/* Called with ffs->mutex held; take over ownership of data. */
 static int __must_check
 __ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len);
 static int __must_check
@@ -267,11 +279,9 @@
 
 static void ffs_func_free(struct ffs_function *func);
 
-
 static void ffs_func_eps_disable(struct ffs_function *func);
 static int __must_check ffs_func_eps_enable(struct ffs_function *func);
 
-
 static int ffs_func_bind(struct usb_configuration *,
 			 struct usb_function *);
 static void ffs_func_unbind(struct usb_configuration *,
@@ -288,7 +298,6 @@
 static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf);
 
 
-
 /* The endpoints structures *************************************************/
 
 struct ffs_ep {
@@ -321,7 +330,6 @@
 	unsigned char			_pad;
 };
 
-
 static int  __must_check ffs_epfiles_create(struct ffs_data *ffs);
 static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
 
@@ -348,7 +356,6 @@
 	complete_all(&ffs->ep0req_completion);
 }
 
-
 static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
 {
 	struct usb_request *req = ffs->ep0req;
@@ -380,17 +387,16 @@
 static int __ffs_ep0_stall(struct ffs_data *ffs)
 {
 	if (ffs->ev.can_stall) {
-		FVDBG("ep0 stall\n");
+		pr_vdebug("ep0 stall\n");
 		usb_ep_set_halt(ffs->gadget->ep0);
 		ffs->setup_state = FFS_NO_SETUP;
 		return -EL2HLT;
 	} else {
-		FDBG("bogus ep0 stall!\n");
+		pr_debug("bogus ep0 stall!\n");
 		return -ESRCH;
 	}
 }
 
-
 static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
 			     size_t len, loff_t *ptr)
 {
@@ -409,7 +415,6 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-
 	/* Check state */
 	switch (ffs->state) {
 	case FFS_READ_DESCRIPTORS:
@@ -421,14 +426,14 @@
 		}
 
 		data = ffs_prepare_buffer(buf, len);
-		if (unlikely(IS_ERR(data))) {
+		if (IS_ERR(data)) {
 			ret = PTR_ERR(data);
 			break;
 		}
 
 		/* Handle data */
 		if (ffs->state == FFS_READ_DESCRIPTORS) {
-			FINFO("read descriptors");
+			pr_info("read descriptors\n");
 			ret = __ffs_data_got_descs(ffs, data, len);
 			if (unlikely(ret < 0))
 				break;
@@ -436,7 +441,7 @@
 			ffs->state = FFS_READ_STRINGS;
 			ret = len;
 		} else {
-			FINFO("read strings");
+			pr_info("read strings\n");
 			ret = __ffs_data_got_strings(ffs, data, len);
 			if (unlikely(ret < 0))
 				break;
@@ -461,11 +466,12 @@
 		}
 		break;
 
-
 	case FFS_ACTIVE:
 		data = NULL;
-		/* We're called from user space, we can use _irq
-		 * rather then _irqsave */
+		/*
+		 * We're called from user space, we can use _irq
+		 * rather then _irqsave
+		 */
 		spin_lock_irq(&ffs->ev.waitq.lock);
 		switch (FFS_SETUP_STATE(ffs)) {
 		case FFS_SETUP_CANCELED:
@@ -493,23 +499,25 @@
 		spin_unlock_irq(&ffs->ev.waitq.lock);
 
 		data = ffs_prepare_buffer(buf, len);
-		if (unlikely(IS_ERR(data))) {
+		if (IS_ERR(data)) {
 			ret = PTR_ERR(data);
 			break;
 		}
 
 		spin_lock_irq(&ffs->ev.waitq.lock);
 
-		/* We are guaranteed to be still in FFS_ACTIVE state
+		/*
+		 * We are guaranteed to be still in FFS_ACTIVE state
 		 * but the state of setup could have changed from
 		 * FFS_SETUP_PENDING to FFS_SETUP_CANCELED so we need
 		 * to check for that.  If that happened we copied data
-		 * from user space in vain but it's unlikely. */
-		/* For sure we are not in FFS_NO_SETUP since this is
+		 * from user space in vain but it's unlikely.
+		 *
+		 * For sure we are not in FFS_NO_SETUP since this is
 		 * the only place FFS_SETUP_PENDING -> FFS_NO_SETUP
 		 * transition can be performed and it's protected by
-		 * mutex. */
-
+		 * mutex.
+		 */
 		if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) {
 			ret = -EIDRM;
 done_spin:
@@ -521,25 +529,22 @@
 		kfree(data);
 		break;
 
-
 	default:
 		ret = -EBADFD;
 		break;
 	}
 
-
 	mutex_unlock(&ffs->mutex);
 	return ret;
 }
 
-
-
 static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
 				     size_t n)
 {
-	/* We are holding ffs->ev.waitq.lock and ffs->mutex and we need
-	 * to release them. */
-
+	/*
+	 * We are holding ffs->ev.waitq.lock and ffs->mutex and we need
+	 * to release them.
+	 */
 	struct usb_functionfs_event events[n];
 	unsigned i = 0;
 
@@ -568,7 +573,6 @@
 		? -EFAULT : sizeof events;
 }
 
-
 static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
 			    size_t len, loff_t *ptr)
 {
@@ -588,16 +592,16 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-
 	/* Check state */
 	if (ffs->state != FFS_ACTIVE) {
 		ret = -EBADFD;
 		goto done_mutex;
 	}
 
-
-	/* We're called from user space, we can use _irq rather then
-	 * _irqsave */
+	/*
+	 * We're called from user space, we can use _irq rather then
+	 * _irqsave
+	 */
 	spin_lock_irq(&ffs->ev.waitq.lock);
 
 	switch (FFS_SETUP_STATE(ffs)) {
@@ -617,7 +621,8 @@
 			break;
 		}
 
-		if (unlikely(wait_event_interruptible_exclusive_locked_irq(ffs->ev.waitq, ffs->ev.count))) {
+		if (wait_event_interruptible_exclusive_locked_irq(ffs->ev.waitq,
+							ffs->ev.count)) {
 			ret = -EINTR;
 			break;
 		}
@@ -625,7 +630,6 @@
 		return __ffs_ep0_read_events(ffs, buf,
 					     min(n, (size_t)ffs->ev.count));
 
-
 	case FFS_SETUP_PENDING:
 		if (ffs->ev.setup.bRequestType & USB_DIR_IN) {
 			spin_unlock_irq(&ffs->ev.waitq.lock);
@@ -671,8 +675,6 @@
 	return ret;
 }
 
-
-
 static int ffs_ep0_open(struct inode *inode, struct file *file)
 {
 	struct ffs_data *ffs = inode->i_private;
@@ -688,7 +690,6 @@
 	return 0;
 }
 
-
 static int ffs_ep0_release(struct inode *inode, struct file *file)
 {
 	struct ffs_data *ffs = file->private_data;
@@ -700,7 +701,6 @@
 	return 0;
 }
 
-
 static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
 {
 	struct ffs_data *ffs = file->private_data;
@@ -721,7 +721,6 @@
 	return ret;
 }
 
-
 static const struct file_operations ffs_ep0_operations = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
@@ -736,7 +735,6 @@
 
 /* "Normal" endpoints operations ********************************************/
 
-
 static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
 {
 	ENTER();
@@ -747,7 +745,6 @@
 	}
 }
 
-
 static ssize_t ffs_epfile_io(struct file *file,
 			     char __user *buf, size_t len, int read)
 {
@@ -777,8 +774,8 @@
 				goto error;
 			}
 
-			if (unlikely(wait_event_interruptible
-				     (epfile->wait, (ep = epfile->ep)))) {
+			if (wait_event_interruptible(epfile->wait,
+						     (ep = epfile->ep))) {
 				ret = -EINTR;
 				goto error;
 			}
@@ -810,12 +807,16 @@
 		if (unlikely(ret))
 			goto error;
 
-		/* We're called from user space, we can use _irq rather then
-		 * _irqsave */
+		/*
+		 * We're called from user space, we can use _irq rather then
+		 * _irqsave
+		 */
 		spin_lock_irq(&epfile->ffs->eps_lock);
 
-		/* While we were acquiring mutex endpoint got disabled
-		 * or changed? */
+		/*
+		 * While we were acquiring mutex endpoint got disabled
+		 * or changed?
+		 */
 	} while (unlikely(epfile->ep != ep));
 
 	/* Halt */
@@ -857,7 +858,6 @@
 	return ret;
 }
 
-
 static ssize_t
 ffs_epfile_write(struct file *file, const char __user *buf, size_t len,
 		 loff_t *ptr)
@@ -903,7 +903,6 @@
 	return 0;
 }
 
-
 static long ffs_epfile_ioctl(struct file *file, unsigned code,
 			     unsigned long value)
 {
@@ -942,7 +941,6 @@
 	return ret;
 }
 
-
 static const struct file_operations ffs_epfile_operations = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
@@ -955,15 +953,13 @@
 };
 
 
-
 /* File system and super block operations ***********************************/
 
 /*
- * Mounting the filesystem creates a controller file, used first for
+ * Mounting the file system creates a controller file, used first for
  * function configuration then later for event monitoring.
  */
 
-
 static struct inode *__must_check
 ffs_sb_make_inode(struct super_block *sb, void *data,
 		  const struct file_operations *fops,
@@ -996,9 +992,7 @@
 	return inode;
 }
 
-
 /* Create "regular" file */
-
 static struct inode *ffs_sb_create_file(struct super_block *sb,
 					const char *name, void *data,
 					const struct file_operations *fops,
@@ -1027,9 +1021,7 @@
 	return inode;
 }
 
-
 /* Super block */
-
 static const struct super_operations ffs_sb_operations = {
 	.statfs =	simple_statfs,
 	.drop_inode =	generic_delete_inode,
@@ -1050,7 +1042,7 @@
 
 	ENTER();
 
-	/* Initialize data */
+	/* Initialise data */
 	ffs = ffs_data_new();
 	if (unlikely(!ffs))
 		goto enomem0;
@@ -1096,7 +1088,6 @@
 	return -ENOMEM;
 }
 
-
 static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
 {
 	ENTER();
@@ -1116,7 +1107,7 @@
 		/* Value limit */
 		eq = strchr(opts, '=');
 		if (unlikely(!eq)) {
-			FERR("'=' missing in %s", opts);
+			pr_err("'=' missing in %s\n", opts);
 			return -EINVAL;
 		}
 		*eq = 0;
@@ -1124,7 +1115,7 @@
 		/* Parse value */
 		value = simple_strtoul(eq + 1, &end, 0);
 		if (unlikely(*end != ',' && *end != 0)) {
-			FERR("%s: invalid value: %s", opts, eq + 1);
+			pr_err("%s: invalid value: %s\n", opts, eq + 1);
 			return -EINVAL;
 		}
 
@@ -1159,7 +1150,7 @@
 
 		default:
 invalid:
-			FERR("%s: invalid option", opts);
+			pr_err("%s: invalid option\n", opts);
 			return -EINVAL;
 		}
 
@@ -1172,7 +1163,6 @@
 	return 0;
 }
 
-
 /* "mount -t functionfs dev_name /dev/function" ends up here */
 
 static struct dentry *
@@ -1224,10 +1214,8 @@
 };
 
 
-
 /* Driver's main init/cleanup functions *************************************/
 
-
 static int functionfs_init(void)
 {
 	int ret;
@@ -1236,9 +1224,9 @@
 
 	ret = register_filesystem(&ffs_fs_type);
 	if (likely(!ret))
-		FINFO("file system registered");
+		pr_info("file system registered\n");
 	else
-		FERR("failed registering file system (%d)", ret);
+		pr_err("failed registering file system (%d)\n", ret);
 
 	return ret;
 }
@@ -1247,18 +1235,16 @@
 {
 	ENTER();
 
-	FINFO("unloading");
+	pr_info("unloading\n");
 	unregister_filesystem(&ffs_fs_type);
 }
 
 
-
 /* ffs_data and ffs_function construction and destruction code **************/
 
 static void ffs_data_clear(struct ffs_data *ffs);
 static void ffs_data_reset(struct ffs_data *ffs);
 
-
 static void ffs_data_get(struct ffs_data *ffs)
 {
 	ENTER();
@@ -1279,7 +1265,7 @@
 	ENTER();
 
 	if (unlikely(atomic_dec_and_test(&ffs->ref))) {
-		FINFO("%s(): freeing", __func__);
+		pr_info("%s(): freeing\n", __func__);
 		ffs_data_clear(ffs);
 		BUG_ON(mutex_is_locked(&ffs->mutex) ||
 		       spin_is_locked(&ffs->ev.waitq.lock) ||
@@ -1289,8 +1275,6 @@
 	}
 }
 
-
-
 static void ffs_data_closed(struct ffs_data *ffs)
 {
 	ENTER();
@@ -1303,7 +1287,6 @@
 	ffs_data_put(ffs);
 }
 
-
 static struct ffs_data *ffs_data_new(void)
 {
 	struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
@@ -1326,7 +1309,6 @@
 	return ffs;
 }
 
-
 static void ffs_data_clear(struct ffs_data *ffs)
 {
 	ENTER();
@@ -1344,7 +1326,6 @@
 	kfree(ffs->stringtabs);
 }
 
-
 static void ffs_data_reset(struct ffs_data *ffs)
 {
 	ENTER();
@@ -1407,7 +1388,6 @@
 	return 0;
 }
 
-
 static void functionfs_unbind(struct ffs_data *ffs)
 {
 	ENTER();
@@ -1420,7 +1400,6 @@
 	}
 }
 
-
 static int ffs_epfiles_create(struct ffs_data *ffs)
 {
 	struct ffs_epfile *epfile, *epfiles;
@@ -1451,7 +1430,6 @@
 	return 0;
 }
 
-
 static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
 {
 	struct ffs_epfile *epfile = epfiles;
@@ -1471,7 +1449,6 @@
 	kfree(epfiles);
 }
 
-
 static int functionfs_bind_config(struct usb_composite_dev *cdev,
 				  struct usb_configuration *c,
 				  struct ffs_data *ffs)
@@ -1491,7 +1468,6 @@
 	func->function.bind    = ffs_func_bind;
 	func->function.unbind  = ffs_func_unbind;
 	func->function.set_alt = ffs_func_set_alt;
-	/*func->function.get_alt = ffs_func_get_alt;*/
 	func->function.disable = ffs_func_disable;
 	func->function.setup   = ffs_func_setup;
 	func->function.suspend = ffs_func_suspend;
@@ -1516,14 +1492,15 @@
 	ffs_data_put(func->ffs);
 
 	kfree(func->eps);
-	/* eps and interfaces_nums are allocated in the same chunk so
+	/*
+	 * eps and interfaces_nums are allocated in the same chunk so
 	 * only one free is required.  Descriptors are also allocated
-	 * in the same chunk. */
+	 * in the same chunk.
+	 */
 
 	kfree(func);
 }
 
-
 static void ffs_func_eps_disable(struct ffs_function *func)
 {
 	struct ffs_ep *ep         = func->eps;
@@ -1581,11 +1558,12 @@
 
 /* Parsing and building descriptors and strings *****************************/
 
-
-/* This validates if data pointed by data is a valid USB descriptor as
+/*
+ * This validates if data pointed by data is a valid USB descriptor as
  * well as record how many interfaces, endpoints and strings are
- * required by given configuration.  Returns address afther the
- * descriptor or NULL if data is invalid. */
+ * required by given configuration.  Returns address after the
+ * descriptor or NULL if data is invalid.
+ */
 
 enum ffs_entity_type {
 	FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
@@ -1607,14 +1585,14 @@
 
 	/* At least two bytes are required: length and type */
 	if (len < 2) {
-		FVDBG("descriptor too short");
+		pr_vdebug("descriptor too short\n");
 		return -EINVAL;
 	}
 
 	/* If we have at least as many bytes as the descriptor takes? */
 	length = _ds->bLength;
 	if (len < length) {
-		FVDBG("descriptor longer then available data");
+		pr_vdebug("descriptor longer then available data\n");
 		return -EINVAL;
 	}
 
@@ -1622,15 +1600,15 @@
 #define __entity_check_STRING(val)     (val)
 #define __entity_check_ENDPOINT(val)   ((val) & USB_ENDPOINT_NUMBER_MASK)
 #define __entity(type, val) do {					\
-		FVDBG("entity " #type "(%02x)", (val));			\
+		pr_vdebug("entity " #type "(%02x)\n", (val));		\
 		if (unlikely(!__entity_check_ ##type(val))) {		\
-			FVDBG("invalid entity's value");		\
+			pr_vdebug("invalid entity's value\n");		\
 			return -EINVAL;					\
 		}							\
 		ret = entity(FFS_ ##type, &val, _ds, priv);		\
 		if (unlikely(ret < 0)) {				\
-			FDBG("entity " #type "(%02x); ret = %d",	\
-			     (val), ret);				\
+			pr_debug("entity " #type "(%02x); ret = %d\n",	\
+				 (val), ret);				\
 			return ret;					\
 		}							\
 	} while (0)
@@ -1642,12 +1620,13 @@
 	case USB_DT_STRING:
 	case USB_DT_DEVICE_QUALIFIER:
 		/* function can't have any of those */
-		FVDBG("descriptor reserved for gadget: %d", _ds->bDescriptorType);
+		pr_vdebug("descriptor reserved for gadget: %d\n",
+		      _ds->bDescriptorType);
 		return -EINVAL;
 
 	case USB_DT_INTERFACE: {
 		struct usb_interface_descriptor *ds = (void *)_ds;
-		FVDBG("interface descriptor");
+		pr_vdebug("interface descriptor\n");
 		if (length != sizeof *ds)
 			goto inv_length;
 
@@ -1659,7 +1638,7 @@
 
 	case USB_DT_ENDPOINT: {
 		struct usb_endpoint_descriptor *ds = (void *)_ds;
-		FVDBG("endpoint descriptor");
+		pr_vdebug("endpoint descriptor\n");
 		if (length != USB_DT_ENDPOINT_SIZE &&
 		    length != USB_DT_ENDPOINT_AUDIO_SIZE)
 			goto inv_length;
@@ -1674,7 +1653,7 @@
 
 	case USB_DT_INTERFACE_ASSOCIATION: {
 		struct usb_interface_assoc_descriptor *ds = (void *)_ds;
-		FVDBG("interface association descriptor");
+		pr_vdebug("interface association descriptor\n");
 		if (length != sizeof *ds)
 			goto inv_length;
 		if (ds->iFunction)
@@ -1688,17 +1667,17 @@
 	case USB_DT_SECURITY:
 	case USB_DT_CS_RADIO_CONTROL:
 		/* TODO */
-		FVDBG("unimplemented descriptor: %d", _ds->bDescriptorType);
+		pr_vdebug("unimplemented descriptor: %d\n", _ds->bDescriptorType);
 		return -EINVAL;
 
 	default:
 		/* We should never be here */
-		FVDBG("unknown descriptor: %d", _ds->bDescriptorType);
+		pr_vdebug("unknown descriptor: %d\n", _ds->bDescriptorType);
 		return -EINVAL;
 
-	inv_length:
-		FVDBG("invalid length: %d (descriptor %d)",
-		      _ds->bLength, _ds->bDescriptorType);
+inv_length:
+		pr_vdebug("invalid length: %d (descriptor %d)\n",
+			  _ds->bLength, _ds->bDescriptorType);
 		return -EINVAL;
 	}
 
@@ -1711,7 +1690,6 @@
 	return length;
 }
 
-
 static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
 				     ffs_entity_callback entity, void *priv)
 {
@@ -1726,10 +1704,11 @@
 		if (num == count)
 			data = NULL;
 
-		/* Record "descriptor" entitny */
+		/* Record "descriptor" entity */
 		ret = entity(FFS_DESCRIPTOR, (u8 *)num, (void *)data, priv);
 		if (unlikely(ret < 0)) {
-			FDBG("entity DESCRIPTOR(%02lx); ret = %d", num, ret);
+			pr_debug("entity DESCRIPTOR(%02lx); ret = %d\n",
+				 num, ret);
 			return ret;
 		}
 
@@ -1738,7 +1717,7 @@
 
 		ret = ffs_do_desc(data, len, entity, priv);
 		if (unlikely(ret < 0)) {
-			FDBG("%s returns %d", __func__, ret);
+			pr_debug("%s returns %d\n", __func__, ret);
 			return ret;
 		}
 
@@ -1748,7 +1727,6 @@
 	}
 }
 
-
 static int __ffs_data_do_entity(enum ffs_entity_type type,
 				u8 *valuep, struct usb_descriptor_header *desc,
 				void *priv)
@@ -1762,16 +1740,20 @@
 		break;
 
 	case FFS_INTERFACE:
-		/* Interfaces are indexed from zero so if we
+		/*
+		 * Interfaces are indexed from zero so if we
 		 * encountered interface "n" then there are at least
-		 * "n+1" interfaces. */
+		 * "n+1" interfaces.
+		 */
 		if (*valuep >= ffs->interfaces_count)
 			ffs->interfaces_count = *valuep + 1;
 		break;
 
 	case FFS_STRING:
-		/* Strings are indexed from 1 (0 is magic ;) reserved
-		 * for languages list or some such) */
+		/*
+		 * Strings are indexed from 1 (0 is magic ;) reserved
+		 * for languages list or some such)
+		 */
 		if (*valuep > ffs->strings_count)
 			ffs->strings_count = *valuep;
 		break;
@@ -1786,7 +1768,6 @@
 	return 0;
 }
 
-
 static int __ffs_data_got_descs(struct ffs_data *ffs,
 				char *const _data, size_t len)
 {
@@ -1849,8 +1830,6 @@
 	return ret;
 }
 
-
-
 static int __ffs_data_got_strings(struct ffs_data *ffs,
 				  char *const _data, size_t len)
 {
@@ -1876,17 +1855,17 @@
 	if (unlikely(str_count < needed_count))
 		goto error;
 
-	/* If we don't need any strings just return and free all
-	 * memory */
+	/*
+	 * If we don't need any strings just return and free all
+	 * memory.
+	 */
 	if (!needed_count) {
 		kfree(_data);
 		return 0;
 	}
 
-	/* Allocate */
+	/* Allocate everything in one chunk so there's less maintenance. */
 	{
-		/* Allocate everything in one chunk so there's less
-		 * maintanance. */
 		struct {
 			struct usb_gadget_strings *stringtabs[lang_count + 1];
 			struct usb_gadget_strings stringtab[lang_count];
@@ -1937,13 +1916,17 @@
 			if (unlikely(length == len))
 				goto error_free;
 
-			/* user may provide more strings then we need,
-			 * if that's the case we simply ingore the
-			 * rest */
+			/*
+			 * User may provide more strings then we need,
+			 * if that's the case we simply ignore the
+			 * rest
+			 */
 			if (likely(needed)) {
-				/* s->id will be set while adding
+				/*
+				 * s->id will be set while adding
 				 * function to configuration so for
-				 * now just leave garbage here. */
+				 * now just leave garbage here.
+				 */
 				s->s = data;
 				--needed;
 				++s;
@@ -1977,8 +1960,6 @@
 }
 
 
-
-
 /* Events handling and management *******************************************/
 
 static void __ffs_event_add(struct ffs_data *ffs,
@@ -1987,29 +1968,32 @@
 	enum usb_functionfs_event_type rem_type1, rem_type2 = type;
 	int neg = 0;
 
-	/* Abort any unhandled setup */
-	/* We do not need to worry about some cmpxchg() changing value
+	/*
+	 * Abort any unhandled setup
+	 *
+	 * We do not need to worry about some cmpxchg() changing value
 	 * of ffs->setup_state without holding the lock because when
 	 * state is FFS_SETUP_PENDING cmpxchg() in several places in
-	 * the source does nothing. */
+	 * the source does nothing.
+	 */
 	if (ffs->setup_state == FFS_SETUP_PENDING)
 		ffs->setup_state = FFS_SETUP_CANCELED;
 
 	switch (type) {
 	case FUNCTIONFS_RESUME:
 		rem_type2 = FUNCTIONFS_SUSPEND;
-		/* FALL THGOUTH */
+		/* FALL THROUGH */
 	case FUNCTIONFS_SUSPEND:
 	case FUNCTIONFS_SETUP:
 		rem_type1 = type;
-		/* discard all similar events */
+		/* Discard all similar events */
 		break;
 
 	case FUNCTIONFS_BIND:
 	case FUNCTIONFS_UNBIND:
 	case FUNCTIONFS_DISABLE:
 	case FUNCTIONFS_ENABLE:
-		/* discard everything other then power management. */
+		/* Discard everything other then power management. */
 		rem_type1 = FUNCTIONFS_SUSPEND;
 		rem_type2 = FUNCTIONFS_RESUME;
 		neg = 1;
@@ -2026,11 +2010,11 @@
 			if ((*ev == rem_type1 || *ev == rem_type2) == neg)
 				*out++ = *ev;
 			else
-				FVDBG("purging event %d", *ev);
+				pr_vdebug("purging event %d\n", *ev);
 		ffs->ev.count = out - ffs->ev.types;
 	}
 
-	FVDBG("adding event %d", type);
+	pr_vdebug("adding event %d\n", type);
 	ffs->ev.types[ffs->ev.count++] = type;
 	wake_up_locked(&ffs->ev.waitq);
 }
@@ -2055,8 +2039,10 @@
 	struct ffs_function *func = priv;
 	struct ffs_ep *ffs_ep;
 
-	/* If hs_descriptors is not NULL then we are reading hs
-	 * descriptors now */
+	/*
+	 * If hs_descriptors is not NULL then we are reading hs
+	 * descriptors now
+	 */
 	const int isHS = func->function.hs_descriptors != NULL;
 	unsigned idx;
 
@@ -2075,9 +2061,9 @@
 	ffs_ep = func->eps + idx;
 
 	if (unlikely(ffs_ep->descs[isHS])) {
-		FVDBG("two %sspeed descriptors for EP %d",
-		      isHS ? "high" : "full",
-		      ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+		pr_vdebug("two %sspeed descriptors for EP %d\n",
+			  isHS ? "high" : "full",
+			  ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 		return -EINVAL;
 	}
 	ffs_ep->descs[isHS] = ds;
@@ -2091,11 +2077,11 @@
 		struct usb_request *req;
 		struct usb_ep *ep;
 
-		FVDBG("autoconfig");
+		pr_vdebug("autoconfig\n");
 		ep = usb_ep_autoconfig(func->gadget, ds);
 		if (unlikely(!ep))
 			return -ENOTSUPP;
-		ep->driver_data = func->eps + idx;;
+		ep->driver_data = func->eps + idx;
 
 		req = usb_ep_alloc_request(ep, GFP_KERNEL);
 		if (unlikely(!req))
@@ -2111,7 +2097,6 @@
 	return 0;
 }
 
-
 static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
 				   struct usb_descriptor_header *desc,
 				   void *priv)
@@ -2143,8 +2128,10 @@
 		break;
 
 	case FFS_ENDPOINT:
-		/* USB_DT_ENDPOINT are handled in
-		 * __ffs_func_bind_do_descs(). */
+		/*
+		 * USB_DT_ENDPOINT are handled in
+		 * __ffs_func_bind_do_descs().
+		 */
 		if (desc->bDescriptorType == USB_DT_ENDPOINT)
 			return 0;
 
@@ -2160,7 +2147,7 @@
 		break;
 	}
 
-	FVDBG("%02x -> %02x", *valuep, newValue);
+	pr_vdebug("%02x -> %02x\n", *valuep, newValue);
 	*valuep = newValue;
 	return 0;
 }
@@ -2211,9 +2198,11 @@
 	func->eps             = data->eps;
 	func->interfaces_nums = data->inums;
 
-	/* Go throught all the endpoint descriptors and allocate
+	/*
+	 * Go through all the endpoint descriptors and allocate
 	 * endpoints first, so that later we can rewrite the endpoint
-	 * numbers without worying that it may be described later on. */
+	 * numbers without worrying that it may be described later on.
+	 */
 	if (likely(full)) {
 		func->function.descriptors = data->fs_descs;
 		ret = ffs_do_descs(ffs->fs_descs_count,
@@ -2234,9 +2223,11 @@
 				   __ffs_func_bind_do_descs, func);
 	}
 
-	/* Now handle interface numbers allocation and interface and
-	 * enpoint numbers rewritting.  We can do that in one go
-	 * now. */
+	/*
+	 * Now handle interface numbers allocation and interface and
+	 * endpoint numbers rewriting.  We can do that in one go
+	 * now.
+	 */
 	ret = ffs_do_descs(ffs->fs_descs_count +
 			   (high ? ffs->hs_descs_count : 0),
 			   data->raw_descs, sizeof data->raw_descs,
@@ -2274,7 +2265,6 @@
 	ffs_func_free(func);
 }
 
-
 static int ffs_func_set_alt(struct usb_function *f,
 			    unsigned interface, unsigned alt)
 {
@@ -2322,20 +2312,21 @@
 
 	ENTER();
 
-	FVDBG("creq->bRequestType = %02x", creq->bRequestType);
-	FVDBG("creq->bRequest     = %02x", creq->bRequest);
-	FVDBG("creq->wValue       = %04x", le16_to_cpu(creq->wValue));
-	FVDBG("creq->wIndex       = %04x", le16_to_cpu(creq->wIndex));
-	FVDBG("creq->wLength      = %04x", le16_to_cpu(creq->wLength));
+	pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType);
+	pr_vdebug("creq->bRequest     = %02x\n", creq->bRequest);
+	pr_vdebug("creq->wValue       = %04x\n", le16_to_cpu(creq->wValue));
+	pr_vdebug("creq->wIndex       = %04x\n", le16_to_cpu(creq->wIndex));
+	pr_vdebug("creq->wLength      = %04x\n", le16_to_cpu(creq->wLength));
 
-	/* Most requests directed to interface go throught here
+	/*
+	 * Most requests directed to interface go through here
 	 * (notable exceptions are set/get interface) so we need to
 	 * handle them.  All other either handled by composite or
 	 * passed to usb_configuration->setup() (if one is set).  No
 	 * matter, we will handle requests directed to endpoint here
 	 * as well (as it's straightforward) but what to do with any
-	 * other request? */
-
+	 * other request?
+	 */
 	if (ffs->state != FFS_ACTIVE)
 		return -ENODEV;
 
@@ -2378,8 +2369,7 @@
 }
 
 
-
-/* Enpoint and interface numbers reverse mapping ****************************/
+/* Endpoint and interface numbers reverse mapping ***************************/
 
 static int ffs_func_revmap_ep(struct ffs_function *func, u8 num)
 {
@@ -2410,7 +2400,6 @@
 		: mutex_lock_interruptible(mutex);
 }
 
-
 static char *ffs_prepare_buffer(const char * __user buf, size_t len)
 {
 	char *data;
@@ -2427,7 +2416,7 @@
 		return ERR_PTR(-EFAULT);
 	}
 
-	FVDBG("Buffer from user space:");
+	pr_vdebug("Buffer from user space:\n");
 	ffs_dump_mem("", data, len);
 
 	return data;
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 838286b..b5dbb23 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -37,7 +37,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-
 /*
  * The Mass Storage Function acts as a USB Mass Storage device,
  * appearing to the host as a disk drive or as a CD-ROM drive.  In
@@ -185,7 +184,6 @@
  * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
  */
 
-
 /*
  *				Driver Design
  *
@@ -275,7 +273,6 @@
 /* #define VERBOSE_DEBUG */
 /* #define DUMP_MSGS */
 
-
 #include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/dcache.h>
@@ -300,7 +297,6 @@
 #include "gadget_chips.h"
 
 
-
 /*------------------------------------------------------------------------*/
 
 #define FSG_DRIVER_DESC		"Mass Storage Function"
@@ -308,7 +304,6 @@
 
 static const char fsg_string_interface[] = "Mass Storage";
 
-
 #define FSG_NO_INTR_EP 1
 #define FSG_NO_DEVICE_STRINGS    1
 #define FSG_NO_OTG               1
@@ -324,25 +319,30 @@
 
 /* FSF callback functions */
 struct fsg_operations {
-	/* Callback function to call when thread exits.  If no
+	/*
+	 * Callback function to call when thread exits.  If no
 	 * callback is set or it returns value lower then zero MSF
 	 * will force eject all LUNs it operates on (including those
 	 * marked as non-removable or with prevent_medium_removal flag
-	 * set). */
+	 * set).
+	 */
 	int (*thread_exits)(struct fsg_common *common);
 
-	/* Called prior to ejection.  Negative return means error,
+	/*
+	 * Called prior to ejection.  Negative return means error,
 	 * zero means to continue with ejection, positive means not to
-	 * eject. */
+	 * eject.
+	 */
 	int (*pre_eject)(struct fsg_common *common,
 			 struct fsg_lun *lun, int num);
-	/* Called after ejection.  Negative return means error, zero
-	 * or positive is just a success. */
+	/*
+	 * Called after ejection.  Negative return means error, zero
+	 * or positive is just a success.
+	 */
 	int (*post_eject)(struct fsg_common *common,
 			  struct fsg_lun *lun, int num);
 };
 
-
 /* Data shared by all the FSG instances. */
 struct fsg_common {
 	struct usb_gadget	*gadget;
@@ -398,14 +398,15 @@
 	/* Gadget's private data. */
 	void			*private_data;
 
-	/* Vendor (8 chars), product (16 chars), release (4
-	 * hexadecimal digits) and NUL byte */
+	/*
+	 * Vendor (8 chars), product (16 chars), release (4
+	 * hexadecimal digits) and NUL byte
+	 */
 	char inquiry_string[8 + 16 + 4 + 1];
 
 	struct kref		ref;
 };
 
-
 struct fsg_config {
 	unsigned nluns;
 	struct fsg_lun_config {
@@ -431,7 +432,6 @@
 	char			can_stall;
 };
 
-
 struct fsg_dev {
 	struct usb_function	function;
 	struct usb_gadget	*gadget;	/* Copy of cdev->gadget */
@@ -449,7 +449,6 @@
 	struct usb_ep		*bulk_out;
 };
 
-
 static inline int __fsg_is_set(struct fsg_common *common,
 			       const char *func, unsigned line)
 {
@@ -462,13 +461,11 @@
 
 #define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__))
 
-
 static inline struct fsg_dev *fsg_from_func(struct usb_function *f)
 {
 	return container_of(f, struct fsg_dev, function);
 }
 
-
 typedef void (*fsg_routine_t)(struct fsg_dev *);
 
 static int exception_in_progress(struct fsg_common *common)
@@ -478,7 +475,7 @@
 
 /* Make bulk-out requests be divisible by the maxpacket size */
 static void set_bulk_out_req_length(struct fsg_common *common,
-		struct fsg_buffhd *bh, unsigned int length)
+				    struct fsg_buffhd *bh, unsigned int length)
 {
 	unsigned int	rem;
 
@@ -489,6 +486,7 @@
 	bh->outreq->length = length;
 }
 
+
 /*-------------------------------------------------------------------------*/
 
 static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
@@ -519,14 +517,15 @@
 		wake_up_process(common->thread_task);
 }
 
-
 static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
 {
 	unsigned long		flags;
 
-	/* Do nothing if a higher-priority exception is already in progress.
+	/*
+	 * Do nothing if a higher-priority exception is already in progress.
 	 * If a lower-or-equal priority exception is in progress, preempt it
-	 * and notify the main thread by sending it a signal. */
+	 * and notify the main thread by sending it a signal.
+	 */
 	spin_lock_irqsave(&common->lock, flags);
 	if (common->state <= new_state) {
 		common->exception_req_tag = common->ep0_req_tag;
@@ -555,10 +554,10 @@
 	return rc;
 }
 
+
 /*-------------------------------------------------------------------------*/
 
-/* Bulk and interrupt endpoint completion handlers.
- * These always run in_irq. */
+/* Completion handlers. These always run in_irq. */
 
 static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
 {
@@ -567,7 +566,7 @@
 
 	if (req->status || req->actual != req->length)
 		DBG(common, "%s --> %d, %u/%u\n", __func__,
-				req->status, req->actual, req->length);
+		    req->status, req->actual, req->length);
 	if (req->status == -ECONNRESET)		/* Request was cancelled */
 		usb_ep_fifo_flush(ep);
 
@@ -588,8 +587,7 @@
 	dump_msg(common, "bulk-out", req->buf, req->actual);
 	if (req->status || req->actual != bh->bulk_out_intended_length)
 		DBG(common, "%s --> %d, %u/%u\n", __func__,
-				req->status, req->actual,
-				bh->bulk_out_intended_length);
+		    req->status, req->actual, bh->bulk_out_intended_length);
 	if (req->status == -ECONNRESET)		/* Request was cancelled */
 		usb_ep_fifo_flush(ep);
 
@@ -602,13 +600,8 @@
 	spin_unlock(&common->lock);
 }
 
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 class-specific handlers.  These always run in_irq. */
-
 static int fsg_setup(struct usb_function *f,
-		const struct usb_ctrlrequest *ctrl)
+		     const struct usb_ctrlrequest *ctrl)
 {
 	struct fsg_dev		*fsg = fsg_from_func(f);
 	struct usb_request	*req = fsg->common->ep0req;
@@ -628,8 +621,10 @@
 		if (w_index != fsg->interface_number || w_value != 0)
 			return -EDOM;
 
-		/* Raise an exception to stop the current operation
-		 * and reinitialize our state. */
+		/*
+		 * Raise an exception to stop the current operation
+		 * and reinitialize our state.
+		 */
 		DBG(fsg, "bulk reset request\n");
 		raise_exception(fsg->common, FSG_STATE_RESET);
 		return DELAYED_STATUS;
@@ -641,7 +636,7 @@
 		if (w_index != fsg->interface_number || w_value != 0)
 			return -EDOM;
 		VDBG(fsg, "get max LUN\n");
-		*(u8 *) req->buf = fsg->common->nluns - 1;
+		*(u8 *)req->buf = fsg->common->nluns - 1;
 
 		/* Respond with data/status */
 		req->length = min((u16)1, w_length);
@@ -649,8 +644,7 @@
 	}
 
 	VDBG(fsg,
-	     "unknown class-specific control req "
-	     "%02x.%02x v%04x i%04x l%u\n",
+	     "unknown class-specific control req %02x.%02x v%04x i%04x l%u\n",
 	     ctrl->bRequestType, ctrl->bRequest,
 	     le16_to_cpu(ctrl->wValue), w_index, w_length);
 	return -EOPNOTSUPP;
@@ -661,11 +655,10 @@
 
 /* All the following routines run in process context */
 
-
 /* Use this for bulk or interrupt transfers, not ep0 */
 static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
-		struct usb_request *req, int *pbusy,
-		enum fsg_buffer_state *state)
+			   struct usb_request *req, int *pbusy,
+			   enum fsg_buffer_state *state)
 {
 	int	rc;
 
@@ -683,25 +676,34 @@
 
 		/* We can't do much more than wait for a reset */
 
-		/* Note: currently the net2280 driver fails zero-length
-		 * submissions if DMA is enabled. */
-		if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
-						req->length == 0))
+		/*
+		 * Note: currently the net2280 driver fails zero-length
+		 * submissions if DMA is enabled.
+		 */
+		if (rc != -ESHUTDOWN &&
+		    !(rc == -EOPNOTSUPP && req->length == 0))
 			WARNING(fsg, "error in submission: %s --> %d\n",
-					ep->name, rc);
+				ep->name, rc);
 	}
 }
 
-#define START_TRANSFER_OR(common, ep_name, req, pbusy, state)		\
-	if (fsg_is_set(common))						\
-		start_transfer((common)->fsg, (common)->fsg->ep_name,	\
-			       req, pbusy, state);			\
-	else
+static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
+{
+	if (!fsg_is_set(common))
+		return false;
+	start_transfer(common->fsg, common->fsg->bulk_in,
+		       bh->inreq, &bh->inreq_busy, &bh->state);
+	return true;
+}
 
-#define START_TRANSFER(common, ep_name, req, pbusy, state)		\
-	START_TRANSFER_OR(common, ep_name, req, pbusy, state) (void)0
-
-
+static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
+{
+	if (!fsg_is_set(common))
+		return false;
+	start_transfer(common->fsg, common->fsg->bulk_out,
+		       bh->outreq, &bh->outreq_busy, &bh->state);
+	return true;
+}
 
 static int sleep_thread(struct fsg_common *common)
 {
@@ -739,16 +741,20 @@
 	unsigned int		partial_page;
 	ssize_t			nread;
 
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
+	/*
+	 * Get the starting Logical Block Address and check that it's
+	 * not too big.
+	 */
 	if (common->cmnd[0] == READ_6)
 		lba = get_unaligned_be24(&common->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&common->cmnd[2]);
 
-		/* We allow DPO (Disable Page Out = don't save data in the
+		/*
+		 * We allow DPO (Disable Page Out = don't save data in the
 		 * cache) and FUA (Force Unit Access = don't read from the
-		 * cache), but we don't implement them. */
+		 * cache), but we don't implement them.
+		 */
 		if ((common->cmnd[1] & ~0x18) != 0) {
 			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return -EINVAL;
@@ -766,22 +772,23 @@
 		return -EIO;		/* No default reply */
 
 	for (;;) {
-
-		/* Figure out how much we need to read:
+		/*
+		 * Figure out how much we need to read:
 		 * Try to read the remaining amount.
 		 * But don't read more than the buffer size.
 		 * And don't try to read past the end of the file.
 		 * Finally, if we're not at a page boundary, don't read past
 		 *	the next page.
 		 * If this means reading 0 then we were asked to read past
-		 *	the end of file. */
+		 *	the end of file.
+		 */
 		amount = min(amount_left, FSG_BUFLEN);
-		amount = min((loff_t) amount,
-				curlun->file_length - file_offset);
+		amount = min((loff_t)amount,
+			     curlun->file_length - file_offset);
 		partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
 		if (partial_page > 0)
-			amount = min(amount, (unsigned int) PAGE_CACHE_SIZE -
-					partial_page);
+			amount = min(amount, (unsigned int)PAGE_CACHE_SIZE -
+					     partial_page);
 
 		/* Wait for the next buffer to become available */
 		bh = common->next_buffhd_to_fill;
@@ -791,8 +798,10 @@
 				return rc;
 		}
 
-		/* If we were asked to read past the end of file,
-		 * end with an empty buffer. */
+		/*
+		 * If we were asked to read past the end of file,
+		 * end with an empty buffer.
+		 */
 		if (amount == 0) {
 			curlun->sense_data =
 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
@@ -806,21 +815,19 @@
 		/* Perform the read */
 		file_offset_tmp = file_offset;
 		nread = vfs_read(curlun->filp,
-				(char __user *) bh->buf,
-				amount, &file_offset_tmp);
+				 (char __user *)bh->buf,
+				 amount, &file_offset_tmp);
 		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-				(unsigned long long) file_offset,
-				(int) nread);
+		      (unsigned long long)file_offset, (int)nread);
 		if (signal_pending(current))
 			return -EINTR;
 
 		if (nread < 0) {
-			LDBG(curlun, "error in file read: %d\n",
-					(int) nread);
+			LDBG(curlun, "error in file read: %d\n", (int)nread);
 			nread = 0;
 		} else if (nread < amount) {
 			LDBG(curlun, "partial file read: %d/%u\n",
-					(int) nread, amount);
+			     (int)nread, amount);
 			nread -= (nread & 511);	/* Round down to a block */
 		}
 		file_offset  += nread;
@@ -842,10 +849,8 @@
 
 		/* Send this buffer and go read some more */
 		bh->inreq->zero = 0;
-		START_TRANSFER_OR(common, bulk_in, bh->inreq,
-			       &bh->inreq_busy, &bh->state)
-			/* Don't know what to do if
-			 * common->fsg is NULL */
+		if (!start_in_transfer(common, bh))
+			/* Don't know what to do if common->fsg is NULL */
 			return -EIO;
 		common->next_buffhd_to_fill = bh->next;
 	}
@@ -877,17 +882,21 @@
 	curlun->filp->f_flags &= ~O_SYNC;	/* Default is not to wait */
 	spin_unlock(&curlun->filp->f_lock);
 
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
+	/*
+	 * Get the starting Logical Block Address and check that it's
+	 * not too big
+	 */
 	if (common->cmnd[0] == WRITE_6)
 		lba = get_unaligned_be24(&common->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&common->cmnd[2]);
 
-		/* We allow DPO (Disable Page Out = don't save data in the
+		/*
+		 * We allow DPO (Disable Page Out = don't save data in the
 		 * cache) and FUA (Force Unit Access = write directly to the
 		 * medium).  We don't implement DPO; we implement FUA by
-		 * performing synchronous output. */
+		 * performing synchronous output.
+		 */
 		if (common->cmnd[1] & ~0x18) {
 			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return -EINVAL;
@@ -915,7 +924,8 @@
 		bh = common->next_buffhd_to_fill;
 		if (bh->state == BUF_STATE_EMPTY && get_some_more) {
 
-			/* Figure out how much we want to get:
+			/*
+			 * Figure out how much we want to get:
 			 * Try to get the remaining amount.
 			 * But don't get more than the buffer size.
 			 * And don't try to go past the end of the file.
@@ -923,14 +933,15 @@
 			 *	don't go past the next page.
 			 * If this means getting 0, then we were asked
 			 *	to write past the end of file.
-			 * Finally, round down to a block boundary. */
+			 * Finally, round down to a block boundary.
+			 */
 			amount = min(amount_left_to_req, FSG_BUFLEN);
-			amount = min((loff_t) amount, curlun->file_length -
-					usb_offset);
+			amount = min((loff_t)amount,
+				     curlun->file_length - usb_offset);
 			partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
 			if (partial_page > 0)
 				amount = min(amount,
-	(unsigned int) PAGE_CACHE_SIZE - partial_page);
+	(unsigned int)PAGE_CACHE_SIZE - partial_page);
 
 			if (amount == 0) {
 				get_some_more = 0;
@@ -940,11 +951,13 @@
 				curlun->info_valid = 1;
 				continue;
 			}
-			amount -= (amount & 511);
+			amount -= amount & 511;
 			if (amount == 0) {
 
-				/* Why were we were asked to transfer a
-				 * partial block? */
+				/*
+				 * Why were we were asked to transfer a
+				 * partial block?
+				 */
 				get_some_more = 0;
 				continue;
 			}
@@ -956,15 +969,15 @@
 			if (amount_left_to_req == 0)
 				get_some_more = 0;
 
-			/* amount is always divisible by 512, hence by
-			 * the bulk-out maxpacket size */
+			/*
+			 * amount is always divisible by 512, hence by
+			 * the bulk-out maxpacket size
+			 */
 			bh->outreq->length = amount;
 			bh->bulk_out_intended_length = amount;
 			bh->outreq->short_not_ok = 1;
-			START_TRANSFER_OR(common, bulk_out, bh->outreq,
-					  &bh->outreq_busy, &bh->state)
-				/* Don't know what to do if
-				 * common->fsg is NULL */
+			if (!start_out_transfer(common, bh))
+				/* Dunno what to do if common->fsg is NULL */
 				return -EIO;
 			common->next_buffhd_to_fill = bh->next;
 			continue;
@@ -990,30 +1003,29 @@
 			amount = bh->outreq->actual;
 			if (curlun->file_length - file_offset < amount) {
 				LERROR(curlun,
-	"write %u @ %llu beyond end %llu\n",
-	amount, (unsigned long long) file_offset,
-	(unsigned long long) curlun->file_length);
+				       "write %u @ %llu beyond end %llu\n",
+				       amount, (unsigned long long)file_offset,
+				       (unsigned long long)curlun->file_length);
 				amount = curlun->file_length - file_offset;
 			}
 
 			/* Perform the write */
 			file_offset_tmp = file_offset;
 			nwritten = vfs_write(curlun->filp,
-					(char __user *) bh->buf,
-					amount, &file_offset_tmp);
+					     (char __user *)bh->buf,
+					     amount, &file_offset_tmp);
 			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
-					(unsigned long long) file_offset,
-					(int) nwritten);
+			      (unsigned long long)file_offset, (int)nwritten);
 			if (signal_pending(current))
 				return -EINTR;		/* Interrupted! */
 
 			if (nwritten < 0) {
 				LDBG(curlun, "error in file write: %d\n",
-						(int) nwritten);
+				     (int)nwritten);
 				nwritten = 0;
 			} else if (nwritten < amount) {
 				LDBG(curlun, "partial file write: %d/%u\n",
-						(int) nwritten, amount);
+				     (int)nwritten, amount);
 				nwritten -= (nwritten & 511);
 				/* Round down to a block */
 			}
@@ -1086,16 +1098,20 @@
 	unsigned int		amount;
 	ssize_t			nread;
 
-	/* Get the starting Logical Block Address and check that it's
-	 * not too big */
+	/*
+	 * Get the starting Logical Block Address and check that it's
+	 * not too big.
+	 */
 	lba = get_unaligned_be32(&common->cmnd[2]);
 	if (lba >= curlun->num_sectors) {
 		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
 		return -EINVAL;
 	}
 
-	/* We allow DPO (Disable Page Out = don't save data in the
-	 * cache) but we don't implement it. */
+	/*
+	 * We allow DPO (Disable Page Out = don't save data in the
+	 * cache) but we don't implement it.
+	 */
 	if (common->cmnd[1] & ~0x10) {
 		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return -EINVAL;
@@ -1120,16 +1136,17 @@
 
 	/* Just try to read the requested blocks */
 	while (amount_left > 0) {
-
-		/* Figure out how much we need to read:
+		/*
+		 * Figure out how much we need to read:
 		 * Try to read the remaining amount, but not more than
 		 * the buffer size.
 		 * And don't try to read past the end of the file.
 		 * If this means reading 0 then we were asked to read
-		 * past the end of file. */
+		 * past the end of file.
+		 */
 		amount = min(amount_left, FSG_BUFLEN);
-		amount = min((loff_t) amount,
-				curlun->file_length - file_offset);
+		amount = min((loff_t)amount,
+			     curlun->file_length - file_offset);
 		if (amount == 0) {
 			curlun->sense_data =
 					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
@@ -1150,13 +1167,12 @@
 			return -EINTR;
 
 		if (nread < 0) {
-			LDBG(curlun, "error in file verify: %d\n",
-					(int) nread);
+			LDBG(curlun, "error in file verify: %d\n", (int)nread);
 			nread = 0;
 		} else if (nread < amount) {
 			LDBG(curlun, "partial file verify: %d/%u\n",
-					(int) nread, amount);
-			nread -= (nread & 511);	/* Round down to a sector */
+			     (int)nread, amount);
+			nread -= nread & 511;	/* Round down to a sector */
 		}
 		if (nread == 0) {
 			curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
@@ -1198,7 +1214,6 @@
 	return 36;
 }
 
-
 static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
 {
 	struct fsg_lun	*curlun = common->curlun;
@@ -1252,13 +1267,12 @@
 	return 18;
 }
 
-
 static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh)
 {
 	struct fsg_lun	*curlun = common->curlun;
 	u32		lba = get_unaligned_be32(&common->cmnd[2]);
 	int		pmi = common->cmnd[8];
-	u8		*buf = (u8 *) bh->buf;
+	u8		*buf = (u8 *)bh->buf;
 
 	/* Check the PMI and LBA fields */
 	if (pmi > 1 || (pmi == 0 && lba != 0)) {
@@ -1272,13 +1286,12 @@
 	return 8;
 }
 
-
 static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh)
 {
 	struct fsg_lun	*curlun = common->curlun;
 	int		msf = common->cmnd[1] & 0x02;
 	u32		lba = get_unaligned_be32(&common->cmnd[2]);
-	u8		*buf = (u8 *) bh->buf;
+	u8		*buf = (u8 *)bh->buf;
 
 	if (common->cmnd[1] & ~0x02) {		/* Mask away MSF */
 		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
@@ -1295,13 +1308,12 @@
 	return 8;
 }
 
-
 static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
 {
 	struct fsg_lun	*curlun = common->curlun;
 	int		msf = common->cmnd[1] & 0x02;
 	int		start_track = common->cmnd[6];
-	u8		*buf = (u8 *) bh->buf;
+	u8		*buf = (u8 *)bh->buf;
 
 	if ((common->cmnd[1] & ~0x02) != 0 ||	/* Mask away MSF */
 			start_track > 1) {
@@ -1323,7 +1335,6 @@
 	return 20;
 }
 
-
 static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
 {
 	struct fsg_lun	*curlun = common->curlun;
@@ -1348,10 +1359,12 @@
 	changeable_values = (pc == 1);
 	all_pages = (page_code == 0x3f);
 
-	/* Write the mode parameter header.  Fixed values are: default
+	/*
+	 * Write the mode parameter header.  Fixed values are: default
 	 * medium type, no cache control (DPOFUA), and no block descriptors.
 	 * The only variable value is the WriteProtect bit.  We will fill in
-	 * the mode data length later. */
+	 * the mode data length later.
+	 */
 	memset(buf, 0, 8);
 	if (mscmnd == MODE_SENSE) {
 		buf[2] = (curlun->ro ? 0x80 : 0x00);		/* WP, DPOFUA */
@@ -1365,8 +1378,10 @@
 
 	/* No block descriptors */
 
-	/* The mode pages, in numerical order.  The only page we support
-	 * is the Caching page. */
+	/*
+	 * The mode pages, in numerical order.  The only page we support
+	 * is the Caching page.
+	 */
 	if (page_code == 0x08 || all_pages) {
 		valid_page = 1;
 		buf[0] = 0x08;		/* Page code */
@@ -1388,8 +1403,10 @@
 		buf += 12;
 	}
 
-	/* Check that a valid page was requested and the mode data length
-	 * isn't too long. */
+	/*
+	 * Check that a valid page was requested and the mode data length
+	 * isn't too long.
+	 */
 	len = buf - buf0;
 	if (!valid_page || len > limit) {
 		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
@@ -1404,7 +1421,6 @@
 	return len;
 }
 
-
 static int do_start_stop(struct fsg_common *common)
 {
 	struct fsg_lun	*curlun = common->curlun;
@@ -1424,8 +1440,10 @@
 	loej  = common->cmnd[4] & 0x02;
 	start = common->cmnd[4] & 0x01;
 
-	/* Our emulation doesn't support mounting; the medium is
-	 * available for use as soon as it is loaded. */
+	/*
+	 * Our emulation doesn't support mounting; the medium is
+	 * available for use as soon as it is loaded.
+	 */
 	if (start) {
 		if (!fsg_lun_is_open(curlun)) {
 			curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
@@ -1466,7 +1484,6 @@
 		: 0;
 }
 
-
 static int do_prevent_allow(struct fsg_common *common)
 {
 	struct fsg_lun	*curlun = common->curlun;
@@ -1491,7 +1508,6 @@
 	return 0;
 }
 
-
 static int do_read_format_capacities(struct fsg_common *common,
 			struct fsg_buffhd *bh)
 {
@@ -1509,7 +1525,6 @@
 	return 12;
 }
 
-
 static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh)
 {
 	struct fsg_lun	*curlun = common->curlun;
@@ -1591,7 +1606,7 @@
 		bh->inreq->length = nsend;
 		bh->inreq->zero = 0;
 		start_transfer(fsg, fsg->bulk_in, bh->inreq,
-				&bh->inreq_busy, &bh->state);
+			       &bh->inreq_busy, &bh->state);
 		bh = fsg->common->next_buffhd_to_fill = bh->next;
 		fsg->common->usb_amount_left -= nsend;
 		nkeep = 0;
@@ -1617,7 +1632,7 @@
 
 			/* A short packet or an error ends everything */
 			if (bh->outreq->actual != bh->outreq->length ||
-					bh->outreq->status != 0) {
+			    bh->outreq->status != 0) {
 				raise_exception(common,
 						FSG_STATE_ABORT_BULK_OUT);
 				return -EINTR;
@@ -1631,15 +1646,15 @@
 		 && common->usb_amount_left > 0) {
 			amount = min(common->usb_amount_left, FSG_BUFLEN);
 
-			/* amount is always divisible by 512, hence by
-			 * the bulk-out maxpacket size */
+			/*
+			 * amount is always divisible by 512, hence by
+			 * the bulk-out maxpacket size.
+			 */
 			bh->outreq->length = amount;
 			bh->bulk_out_intended_length = amount;
 			bh->outreq->short_not_ok = 1;
-			START_TRANSFER_OR(common, bulk_out, bh->outreq,
-					  &bh->outreq_busy, &bh->state)
-				/* Don't know what to do if
-				 * common->fsg is NULL */
+			if (!start_out_transfer(common, bh))
+				/* Dunno what to do if common->fsg is NULL */
 				return -EIO;
 			common->next_buffhd_to_fill = bh->next;
 			common->usb_amount_left -= amount;
@@ -1654,7 +1669,6 @@
 	return 0;
 }
 
-
 static int finish_reply(struct fsg_common *common)
 {
 	struct fsg_buffhd	*bh = common->next_buffhd_to_fill;
@@ -1664,10 +1678,12 @@
 	case DATA_DIR_NONE:
 		break;			/* Nothing to send */
 
-	/* If we don't know whether the host wants to read or write,
+	/*
+	 * If we don't know whether the host wants to read or write,
 	 * this must be CB or CBI with an unknown command.  We mustn't
 	 * try to send or receive any data.  So stall both bulk pipes
-	 * if we can and wait for a reset. */
+	 * if we can and wait for a reset.
+	 */
 	case DATA_DIR_UNKNOWN:
 		if (!common->can_stall) {
 			/* Nothing */
@@ -1688,18 +1704,18 @@
 		/* If there's no residue, simply send the last buffer */
 		} else if (common->residue == 0) {
 			bh->inreq->zero = 0;
-			START_TRANSFER_OR(common, bulk_in, bh->inreq,
-					  &bh->inreq_busy, &bh->state)
+			if (!start_in_transfer(common, bh))
 				return -EIO;
 			common->next_buffhd_to_fill = bh->next;
 
-		/* For Bulk-only, if we're allowed to stall then send the
+		/*
+		 * For Bulk-only, if we're allowed to stall then send the
 		 * short packet and halt the bulk-in endpoint.  If we can't
-		 * stall, pad out the remaining data with 0's. */
+		 * stall, pad out the remaining data with 0's.
+		 */
 		} else if (common->can_stall) {
 			bh->inreq->zero = 1;
-			START_TRANSFER_OR(common, bulk_in, bh->inreq,
-					  &bh->inreq_busy, &bh->state)
+			if (!start_in_transfer(common, bh))
 				/* Don't know what to do if
 				 * common->fsg is NULL */
 				rc = -EIO;
@@ -1714,8 +1730,10 @@
 		}
 		break;
 
-	/* We have processed all we want from the data the host has sent.
-	 * There may still be outstanding bulk-out requests. */
+	/*
+	 * We have processed all we want from the data the host has sent.
+	 * There may still be outstanding bulk-out requests.
+	 */
 	case DATA_DIR_FROM_HOST:
 		if (common->residue == 0) {
 			/* Nothing to receive */
@@ -1725,12 +1743,14 @@
 			raise_exception(common, FSG_STATE_ABORT_BULK_OUT);
 			rc = -EINTR;
 
-		/* We haven't processed all the incoming data.  Even though
+		/*
+		 * We haven't processed all the incoming data.  Even though
 		 * we may be allowed to stall, doing so would cause a race.
 		 * The controller may already have ACK'ed all the remaining
 		 * bulk-out packets, in which case the host wouldn't see a
 		 * STALL.  Not realizing the endpoint was halted, it wouldn't
-		 * clear the halt -- leading to problems later on. */
+		 * clear the halt -- leading to problems later on.
+		 */
 #if 0
 		} else if (common->can_stall) {
 			if (fsg_is_set(common))
@@ -1740,8 +1760,10 @@
 			rc = -EINTR;
 #endif
 
-		/* We can't stall.  Read in the excess data and throw it
-		 * all away. */
+		/*
+		 * We can't stall.  Read in the excess data and throw it
+		 * all away.
+		 */
 		} else {
 			rc = throw_away_data(common);
 		}
@@ -1750,7 +1772,6 @@
 	return rc;
 }
 
-
 static int send_status(struct fsg_common *common)
 {
 	struct fsg_lun		*curlun = common->curlun;
@@ -1798,8 +1819,7 @@
 
 	bh->inreq->length = USB_BULK_CS_WRAP_LEN;
 	bh->inreq->zero = 0;
-	START_TRANSFER_OR(common, bulk_in, bh->inreq,
-			  &bh->inreq_busy, &bh->state)
+	if (!start_in_transfer(common, bh))
 		/* Don't know what to do if common->fsg is NULL */
 		return -EIO;
 
@@ -1810,11 +1830,13 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* Check whether the command is properly formed and whether its data size
- * and direction agree with the values we already have. */
+/*
+ * Check whether the command is properly formed and whether its data size
+ * and direction agree with the values we already have.
+ */
 static int check_command(struct fsg_common *common, int cmnd_size,
-		enum data_direction data_dir, unsigned int mask,
-		int needs_medium, const char *name)
+			 enum data_direction data_dir, unsigned int mask,
+			 int needs_medium, const char *name)
 {
 	int			i;
 	int			lun = common->cmnd[1] >> 5;
@@ -1825,19 +1847,23 @@
 	hdlen[0] = 0;
 	if (common->data_dir != DATA_DIR_UNKNOWN)
 		sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir],
-				common->data_size);
+			common->data_size);
 	VDBG(common, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
 	     name, cmnd_size, dirletter[(int) data_dir],
 	     common->data_size_from_cmnd, common->cmnd_size, hdlen);
 
-	/* We can't reply at all until we know the correct data direction
-	 * and size. */
+	/*
+	 * We can't reply at all until we know the correct data direction
+	 * and size.
+	 */
 	if (common->data_size_from_cmnd == 0)
 		data_dir = DATA_DIR_NONE;
 	if (common->data_size < common->data_size_from_cmnd) {
-		/* Host data size < Device data size is a phase error.
+		/*
+		 * Host data size < Device data size is a phase error.
 		 * Carry out the command, but only transfer as much as
-		 * we are allowed. */
+		 * we are allowed.
+		 */
 		common->data_size_from_cmnd = common->data_size;
 		common->phase_error = 1;
 	}
@@ -1845,8 +1871,7 @@
 	common->usb_amount_left = common->data_size;
 
 	/* Conflicting data directions is a phase error */
-	if (common->data_dir != data_dir
-	 && common->data_size_from_cmnd > 0) {
+	if (common->data_dir != data_dir && common->data_size_from_cmnd > 0) {
 		common->phase_error = 1;
 		return -EINVAL;
 	}
@@ -1854,7 +1879,8 @@
 	/* Verify the length of the command itself */
 	if (cmnd_size != common->cmnd_size) {
 
-		/* Special case workaround: There are plenty of buggy SCSI
+		/*
+		 * Special case workaround: There are plenty of buggy SCSI
 		 * implementations. Many have issues with cbw->Length
 		 * field passing a wrong command size. For those cases we
 		 * always try to work around the problem by using the length
@@ -1896,8 +1922,10 @@
 		curlun = NULL;
 		common->bad_lun_okay = 0;
 
-		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
-		 * to use unsupported LUNs; all others may not. */
+		/*
+		 * INQUIRY and REQUEST SENSE commands are explicitly allowed
+		 * to use unsupported LUNs; all others may not.
+		 */
 		if (common->cmnd[0] != INQUIRY &&
 		    common->cmnd[0] != REQUEST_SENSE) {
 			DBG(common, "unsupported LUN %d\n", common->lun);
@@ -1905,11 +1933,13 @@
 		}
 	}
 
-	/* If a unit attention condition exists, only INQUIRY and
-	 * REQUEST SENSE commands are allowed; anything else must fail. */
+	/*
+	 * If a unit attention condition exists, only INQUIRY and
+	 * REQUEST SENSE commands are allowed; anything else must fail.
+	 */
 	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-			common->cmnd[0] != INQUIRY &&
-			common->cmnd[0] != REQUEST_SENSE) {
+	    common->cmnd[0] != INQUIRY &&
+	    common->cmnd[0] != REQUEST_SENSE) {
 		curlun->sense_data = curlun->unit_attention_data;
 		curlun->unit_attention_data = SS_NO_SENSE;
 		return -EINVAL;
@@ -1935,7 +1965,6 @@
 	return 0;
 }
 
-
 static int do_scsi_command(struct fsg_common *common)
 {
 	struct fsg_buffhd	*bh;
@@ -2123,8 +2152,10 @@
 				"TEST UNIT READY");
 		break;
 
-	/* Although optional, this command is used by MS-Windows.  We
-	 * support a minimal version: BytChk must be 0. */
+	/*
+	 * Although optional, this command is used by MS-Windows.  We
+	 * support a minimal version: BytChk must be 0.
+	 */
 	case VERIFY:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 10, DATA_DIR_NONE,
@@ -2164,10 +2195,12 @@
 			reply = do_write(common);
 		break;
 
-	/* Some mandatory commands that we recognize but don't implement.
+	/*
+	 * Some mandatory commands that we recognize but don't implement.
 	 * They don't mean much in this setting.  It's left as an exercise
 	 * for anyone interested to implement RESERVE and RELEASE in terms
-	 * of Posix locks. */
+	 * of Posix locks.
+	 */
 	case FORMAT_UNIT:
 	case RELEASE:
 	case RESERVE:
@@ -2195,7 +2228,7 @@
 	if (reply == -EINVAL)
 		reply = 0;		/* Error reply length */
 	if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) {
-		reply = min((u32) reply, common->data_size_from_cmnd);
+		reply = min((u32)reply, common->data_size_from_cmnd);
 		bh->inreq->length = reply;
 		bh->state = BUF_STATE_FULL;
 		common->residue -= reply;
@@ -2225,7 +2258,8 @@
 				req->actual,
 				le32_to_cpu(cbw->Signature));
 
-		/* The Bulk-only spec says we MUST stall the IN endpoint
+		/*
+		 * The Bulk-only spec says we MUST stall the IN endpoint
 		 * (6.6.1), so it's unavoidable.  It also says we must
 		 * retain this state until the next reset, but there's
 		 * no way to tell the controller driver it should ignore
@@ -2233,7 +2267,8 @@
 		 *
 		 * We aren't required to halt the OUT endpoint; instead
 		 * we can simply accept and discard any data received
-		 * until the next reset. */
+		 * until the next reset.
+		 */
 		wedge_bulk_in_endpoint(fsg);
 		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 		return -EINVAL;
@@ -2246,8 +2281,10 @@
 				"cmdlen %u\n",
 				cbw->Lun, cbw->Flags, cbw->Length);
 
-		/* We can do anything we want here, so let's stall the
-		 * bulk pipes if we are allowed to. */
+		/*
+		 * We can do anything we want here, so let's stall the
+		 * bulk pipes if we are allowed to.
+		 */
 		if (common->can_stall) {
 			fsg_set_halt(fsg, fsg->bulk_out);
 			halt_bulk_in_endpoint(fsg);
@@ -2270,7 +2307,6 @@
 	return 0;
 }
 
-
 static int get_next_command(struct fsg_common *common)
 {
 	struct fsg_buffhd	*bh;
@@ -2287,14 +2323,15 @@
 	/* Queue a request to read a Bulk-only CBW */
 	set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN);
 	bh->outreq->short_not_ok = 1;
-	START_TRANSFER_OR(common, bulk_out, bh->outreq,
-			  &bh->outreq_busy, &bh->state)
+	if (!start_out_transfer(common, bh))
 		/* Don't know what to do if common->fsg is NULL */
 		return -EIO;
 
-	/* We will drain the buffer in software, which means we
+	/*
+	 * We will drain the buffer in software, which means we
 	 * can reuse it for the next filling.  No need to advance
-	 * next_buffhd_to_fill. */
+	 * next_buffhd_to_fill.
+	 */
 
 	/* Wait for the CBW to arrive */
 	while (bh->state != BUF_STATE_FULL) {
@@ -2425,7 +2462,6 @@
 
 /****************************** ALT CONFIGS ******************************/
 
-
 static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
 	struct fsg_dev *fsg = fsg_from_func(f);
@@ -2453,8 +2489,10 @@
 	struct fsg_lun		*curlun;
 	unsigned int		exception_req_tag;
 
-	/* Clear the existing signals.  Anything but SIGUSR1 is converted
-	 * into a high-priority EXIT exception. */
+	/*
+	 * Clear the existing signals.  Anything but SIGUSR1 is converted
+	 * into a high-priority EXIT exception.
+	 */
 	for (;;) {
 		int sig =
 			dequeue_signal_lock(current, &current->blocked, &info);
@@ -2498,8 +2536,10 @@
 			usb_ep_fifo_flush(common->fsg->bulk_out);
 	}
 
-	/* Reset the I/O buffer states and pointers, the SCSI
-	 * state, and the exception.  Then invoke the handler. */
+	/*
+	 * Reset the I/O buffer states and pointers, the SCSI
+	 * state, and the exception.  Then invoke the handler.
+	 */
 	spin_lock_irq(&common->lock);
 
 	for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
@@ -2537,9 +2577,11 @@
 		break;
 
 	case FSG_STATE_RESET:
-		/* In case we were forced against our will to halt a
+		/*
+		 * In case we were forced against our will to halt a
 		 * bulk endpoint, clear the halt now.  (The SuperH UDC
-		 * requires this.) */
+		 * requires this.)
+		 */
 		if (!fsg_is_set(common))
 			break;
 		if (test_and_clear_bit(IGNORE_BULK_OUT,
@@ -2549,9 +2591,11 @@
 		if (common->ep0_req_tag == exception_req_tag)
 			ep0_queue(common);	/* Complete the status stage */
 
-		/* Technically this should go here, but it would only be
+		/*
+		 * Technically this should go here, but it would only be
 		 * a waste of time.  Ditto for the INTERFACE_CHANGE and
-		 * CONFIG_CHANGE cases. */
+		 * CONFIG_CHANGE cases.
+		 */
 		/* for (i = 0; i < common->nluns; ++i) */
 		/*	common->luns[i].unit_attention_data = */
 		/*		SS_RESET_OCCURRED;  */
@@ -2586,8 +2630,10 @@
 {
 	struct fsg_common	*common = common_;
 
-	/* Allow the thread to be killed by a signal, but set the signal mask
-	 * to block everything but INT, TERM, KILL, and USR1. */
+	/*
+	 * Allow the thread to be killed by a signal, but set the signal mask
+	 * to block everything but INT, TERM, KILL, and USR1.
+	 */
 	allow_signal(SIGINT);
 	allow_signal(SIGTERM);
 	allow_signal(SIGKILL);
@@ -2596,9 +2642,11 @@
 	/* Allow the thread to be frozen */
 	set_freezable();
 
-	/* Arrange for userspace references to be interpreted as kernel
+	/*
+	 * Arrange for userspace references to be interpreted as kernel
 	 * pointers.  That way we can pass a kernel pointer to a routine
-	 * that expects a __user pointer and it will work okay. */
+	 * that expects a __user pointer and it will work okay.
+	 */
 	set_fs(get_ds());
 
 	/* The main loop */
@@ -2658,7 +2706,7 @@
 		up_write(&common->filesem);
 	}
 
-	/* Let the unbind and cleanup routines know the thread has exited */
+	/* Let fsg_unbind() know the thread has exited */
 	complete_and_exit(&common->thread_notifier, 0);
 }
 
@@ -2690,7 +2738,6 @@
 	kref_put(&common->ref, fsg_common_release);
 }
 
-
 static struct fsg_common *fsg_common_init(struct fsg_common *common,
 					  struct usb_composite_dev *cdev,
 					  struct fsg_config *cfg)
@@ -2736,8 +2783,10 @@
 		fsg_intf_desc.iInterface = rc;
 	}
 
-	/* Create the LUNs, open their backing files, and register the
-	 * LUN devices in sysfs. */
+	/*
+	 * Create the LUNs, open their backing files, and register the
+	 * LUN devices in sysfs.
+	 */
 	curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL);
 	if (unlikely(!curlun)) {
 		rc = -ENOMEM;
@@ -2765,6 +2814,7 @@
 		if (rc) {
 			INFO(common, "failed to register LUN%d: %d\n", i, rc);
 			common->nluns = i;
+			put_device(&curlun->dev);
 			goto error_release;
 		}
 
@@ -2790,7 +2840,6 @@
 	}
 	common->nluns = nluns;
 
-
 	/* Data buffers cyclic list */
 	bh = common->buffhds;
 	i = FSG_NUM_BUFFERS;
@@ -2807,7 +2856,6 @@
 	} while (--i);
 	bh->next = common->buffhds;
 
-
 	/* Prepare inquiryString */
 	if (cfg->release != 0xffff) {
 		i = cfg->release;
@@ -2821,41 +2869,35 @@
 			i = 0x0399;
 		}
 	}
-#define OR(x, y) ((x) ? (x) : (y))
 	snprintf(common->inquiry_string, sizeof common->inquiry_string,
-		 "%-8s%-16s%04x",
-		 OR(cfg->vendor_name, "Linux   "),
+		 "%-8s%-16s%04x", cfg->vendor_name ?: "Linux",
 		 /* Assume product name dependent on the first LUN */
-		 OR(cfg->product_name, common->luns->cdrom
+		 cfg->product_name ?: (common->luns->cdrom
 				     ? "File-Stor Gadget"
-				     : "File-CD Gadget  "),
+				     : "File-CD Gadget"),
 		 i);
 
-
-	/* Some peripheral controllers are known not to be able to
+	/*
+	 * Some peripheral controllers are known not to be able to
 	 * halt bulk endpoints correctly.  If one of them is present,
 	 * disable stalls.
 	 */
 	common->can_stall = cfg->can_stall &&
 		!(gadget_is_at91(common->gadget));
 
-
 	spin_lock_init(&common->lock);
 	kref_init(&common->ref);
 
-
 	/* Tell the thread to start working */
 	common->thread_task =
 		kthread_create(fsg_main_thread, common,
-			       OR(cfg->thread_name, "file-storage"));
+			       cfg->thread_name ?: "file-storage");
 	if (IS_ERR(common->thread_task)) {
 		rc = PTR_ERR(common->thread_task);
 		goto error_release;
 	}
 	init_completion(&common->thread_notifier);
 	init_waitqueue_head(&common->fsg_wait);
-#undef OR
-
 
 	/* Information */
 	INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
@@ -2889,18 +2931,15 @@
 
 	return common;
 
-
 error_luns:
 	common->nluns = i + 1;
 error_release:
 	common->state = FSG_STATE_TERMINATED;	/* The thread is dead */
-	/* Call fsg_common_release() directly, ref might be not
-	 * initialised */
+	/* Call fsg_common_release() directly, ref might be not initialised. */
 	fsg_common_release(&common->ref);
 	return ERR_PTR(rc);
 }
 
-
 static void fsg_common_release(struct kref *ref)
 {
 	struct fsg_common *common = container_of(ref, struct fsg_common, ref);
@@ -2909,9 +2948,6 @@
 	if (common->state != FSG_STATE_TERMINATED) {
 		raise_exception(common, FSG_STATE_EXIT);
 		wait_for_completion(&common->thread_notifier);
-
-		/* The cleanup routine waits for this completion also */
-		complete(&common->thread_notifier);
 	}
 
 	if (likely(common->luns)) {
@@ -2945,7 +2981,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-
 static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct fsg_dev		*fsg = fsg_from_func(f);
@@ -2965,7 +3000,6 @@
 	kfree(fsg);
 }
 
-
 static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct fsg_dev		*fsg = fsg_from_func(f);
@@ -3048,11 +3082,13 @@
 	fsg->function.disable     = fsg_disable;
 
 	fsg->common               = common;
-	/* Our caller holds a reference to common structure so we
+	/*
+	 * Our caller holds a reference to common structure so we
 	 * don't have to be worry about it being freed until we return
 	 * from this function.  So instead of incrementing counter now
 	 * and decrement in error recovery we increment it only when
-	 * call to usb_add_function() was successful. */
+	 * call to usb_add_function() was successful.
+	 */
 
 	rc = usb_add_function(c, &fsg->function);
 	if (unlikely(rc))
@@ -3063,8 +3099,7 @@
 }
 
 static inline int __deprecated __maybe_unused
-fsg_add(struct usb_composite_dev *cdev,
-	struct usb_configuration *c,
+fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c,
 	struct fsg_common *common)
 {
 	return fsg_bind_config(cdev, c, common);
@@ -3073,7 +3108,6 @@
 
 /************************* Module parameters *************************/
 
-
 struct fsg_module_parameters {
 	char		*file[FSG_MAX_LUNS];
 	int		ro[FSG_MAX_LUNS];
@@ -3087,7 +3121,6 @@
 	int		stall;	/* can_stall */
 };
 
-
 #define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc)	\
 	module_param_array_named(prefix ## name, params.name, type,	\
 				 &prefix ## params.name ## _count,	\
@@ -3115,7 +3148,6 @@
 	_FSG_MODULE_PARAM(prefix, params, stall, bool,			\
 			  "false to prevent bulk stalls")
 
-
 static void
 fsg_config_from_params(struct fsg_config *cfg,
 		       const struct fsg_module_parameters *params)
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
new file mode 100644
index 0000000..130eee6
--- /dev/null
+++ b/drivers/usb/gadget/f_ncm.c
@@ -0,0 +1,1407 @@
+/*
+ * f_ncm.c -- USB CDC Network (NCM) link function driver
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Contact: Yauheni Kaliuta <yauheni.kaliuta@nokia.com>
+ *
+ * The driver borrows from f_ecm.c which is:
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2008 Nokia 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 <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+
+#include <linux/usb/cdc.h>
+
+#include "u_ether.h"
+
+/*
+ * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link.
+ * NCM is intended to be used with high-speed network attachments.
+ *
+ * Note that NCM requires the use of "alternate settings" for its data
+ * interface.  This means that the set_alt() method has real work to do,
+ * and also means that a get_alt() method is required.
+ */
+
+/* to trigger crc/non-crc ndp signature */
+
+#define NCM_NDP_HDR_CRC_MASK	0x01000000
+#define NCM_NDP_HDR_CRC		0x01000000
+#define NCM_NDP_HDR_NOCRC	0x00000000
+
+struct ncm_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+enum ncm_notify_state {
+	NCM_NOTIFY_NONE,		/* don't notify */
+	NCM_NOTIFY_CONNECT,		/* issue CONNECT next */
+	NCM_NOTIFY_SPEED,		/* issue SPEED_CHANGE next */
+};
+
+struct f_ncm {
+	struct gether			port;
+	u8				ctrl_id, data_id;
+
+	char				ethaddr[14];
+
+	struct ncm_ep_descs		fs;
+	struct ncm_ep_descs		hs;
+
+	struct usb_ep			*notify;
+	struct usb_endpoint_descriptor	*notify_desc;
+	struct usb_request		*notify_req;
+	u8				notify_state;
+	bool				is_open;
+
+	struct ndp_parser_opts		*parser_opts;
+	bool				is_crc;
+
+	/*
+	 * for notification, it is accessed from both
+	 * callback and ethernet open/close
+	 */
+	spinlock_t			lock;
+};
+
+static inline struct f_ncm *func_to_ncm(struct usb_function *f)
+{
+	return container_of(f, struct f_ncm, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static inline unsigned ncm_bitrate(struct usb_gadget *g)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return 13 * 512 * 8 * 1000 * 8;
+	else
+		return 19 *  64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * We cannot group frames so use just the minimal size which ok to put
+ * one max-size ethernet frame.
+ * If the host can group frames, allow it to do that, 16K is selected,
+ * because it's used by default by the current linux host driver
+ */
+#define NTB_DEFAULT_IN_SIZE	USB_CDC_NCM_NTB_MIN_IN_SIZE
+#define NTB_OUT_SIZE		16384
+
+/*
+ * skbs of size less than that will not be alligned
+ * to NCM's dwNtbInMaxSize to save bus bandwidth
+ */
+
+#define	MAX_TX_NONFIXED		(512 * 3)
+
+#define FORMATS_SUPPORTED	(USB_CDC_NCM_NTB16_SUPPORTED |	\
+				 USB_CDC_NCM_NTB32_SUPPORTED)
+
+static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
+	.wLength = sizeof ntb_parameters,
+	.bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
+	.dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
+	.wNdpInDivisor = cpu_to_le16(4),
+	.wNdpInPayloadRemainder = cpu_to_le16(0),
+	.wNdpInAlignment = cpu_to_le16(4),
+
+	.dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE),
+	.wNdpOutDivisor = cpu_to_le16(4),
+	.wNdpOutPayloadRemainder = cpu_to_le16(0),
+	.wNdpOutAlignment = cpu_to_le16(4),
+};
+
+/*
+ * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancellation; and a big transfer interval, to
+ * waste less bandwidth.
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define NCM_STATUS_BYTECOUNT		16	/* 8 byte header + data */
+
+static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = {
+	.bLength =		sizeof ncm_iad_desc,
+	.bDescriptorType =	USB_DT_INTERFACE_ASSOCIATION,
+
+	/* .bFirstInterface =	DYNAMIC, */
+	.bInterfaceCount =	2,	/* control + data */
+	.bFunctionClass =	USB_CLASS_COMM,
+	.bFunctionSubClass =	USB_CDC_SUBCLASS_NCM,
+	.bFunctionProtocol =	USB_CDC_PROTO_NONE,
+	/* .iFunction =		DYNAMIC */
+};
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor ncm_control_intf __initdata = {
+	.bLength =		sizeof ncm_control_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_COMM,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_NCM,
+	.bInterfaceProtocol =	USB_CDC_PROTO_NONE,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc ncm_header_desc __initdata = {
+	.bLength =		sizeof ncm_header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_union_desc ncm_union_desc __initdata = {
+	.bLength =		sizeof(ncm_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+static struct usb_cdc_ether_desc ecm_desc __initdata = {
+	.bLength =		sizeof ecm_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
+
+	/* this descriptor actually adds value, surprise! */
+	/* .iMACAddress = DYNAMIC */
+	.bmEthernetStatistics =	cpu_to_le32(0), /* no statistics */
+	.wMaxSegmentSize =	cpu_to_le16(ETH_FRAME_LEN),
+	.wNumberMCFilters =	cpu_to_le16(0),
+	.bNumberPowerFilters =	0,
+};
+
+#define NCAPS	(USB_CDC_NCM_NCAP_ETH_FILTER | USB_CDC_NCM_NCAP_CRC_MODE)
+
+static struct usb_cdc_ncm_desc ncm_desc __initdata = {
+	.bLength =		sizeof ncm_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_NCM_TYPE,
+
+	.bcdNcmVersion =	cpu_to_le16(0x0100),
+	/* can process SetEthernetPacketFilter */
+	.bmNetworkCapabilities = NCAPS,
+};
+
+/* the default data interface has no endpoints ... */
+
+static struct usb_interface_descriptor ncm_data_nop_intf __initdata = {
+	.bLength =		sizeof ncm_data_nop_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	1,
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	USB_CDC_NCM_PROTO_NTB,
+	/* .iInterface = DYNAMIC */
+};
+
+/* ... but the "real" data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor ncm_data_intf __initdata = {
+	.bLength =		sizeof ncm_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	1,
+	.bAlternateSetting =	1,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	USB_CDC_NCM_PROTO_NTB,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(NCM_STATUS_BYTECOUNT),
+	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_ncm_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *ncm_fs_function[] __initdata = {
+	(struct usb_descriptor_header *) &ncm_iad_desc,
+	/* CDC NCM control descriptors */
+	(struct usb_descriptor_header *) &ncm_control_intf,
+	(struct usb_descriptor_header *) &ncm_header_desc,
+	(struct usb_descriptor_header *) &ncm_union_desc,
+	(struct usb_descriptor_header *) &ecm_desc,
+	(struct usb_descriptor_header *) &ncm_desc,
+	(struct usb_descriptor_header *) &fs_ncm_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &ncm_data_nop_intf,
+	(struct usb_descriptor_header *) &ncm_data_intf,
+	(struct usb_descriptor_header *) &fs_ncm_in_desc,
+	(struct usb_descriptor_header *) &fs_ncm_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(NCM_STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_ncm_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *ncm_hs_function[] __initdata = {
+	(struct usb_descriptor_header *) &ncm_iad_desc,
+	/* CDC NCM control descriptors */
+	(struct usb_descriptor_header *) &ncm_control_intf,
+	(struct usb_descriptor_header *) &ncm_header_desc,
+	(struct usb_descriptor_header *) &ncm_union_desc,
+	(struct usb_descriptor_header *) &ecm_desc,
+	(struct usb_descriptor_header *) &ncm_desc,
+	(struct usb_descriptor_header *) &hs_ncm_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &ncm_data_nop_intf,
+	(struct usb_descriptor_header *) &ncm_data_intf,
+	(struct usb_descriptor_header *) &hs_ncm_in_desc,
+	(struct usb_descriptor_header *) &hs_ncm_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+#define STRING_CTRL_IDX	0
+#define STRING_MAC_IDX	1
+#define STRING_DATA_IDX	2
+#define STRING_IAD_IDX	3
+
+static struct usb_string ncm_string_defs[] = {
+	[STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)",
+	[STRING_MAC_IDX].s = NULL /* DYNAMIC */,
+	[STRING_DATA_IDX].s = "CDC Network Data",
+	[STRING_IAD_IDX].s = "CDC NCM",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings ncm_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		ncm_string_defs,
+};
+
+static struct usb_gadget_strings *ncm_strings[] = {
+	&ncm_string_table,
+	NULL,
+};
+
+/*
+ * Here are options for NCM Datagram Pointer table (NDP) parser.
+ * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
+ * in NDP16 offsets and sizes fields are 1 16bit word wide,
+ * in NDP32 -- 2 16bit words wide. Also signatures are different.
+ * To make the parser code the same, put the differences in the structure,
+ * and switch pointers to the structures when the format is changed.
+ */
+
+struct ndp_parser_opts {
+	u32		nth_sign;
+	u32		ndp_sign;
+	unsigned	nth_size;
+	unsigned	ndp_size;
+	unsigned	ndplen_align;
+	/* sizes in u16 units */
+	unsigned	dgram_item_len; /* index or length */
+	unsigned	block_length;
+	unsigned	fp_index;
+	unsigned	reserved1;
+	unsigned	reserved2;
+	unsigned	next_fp_index;
+};
+
+#define INIT_NDP16_OPTS {					\
+		.nth_sign = USB_CDC_NCM_NTH16_SIGN,		\
+		.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN,	\
+		.nth_size = sizeof(struct usb_cdc_ncm_nth16),	\
+		.ndp_size = sizeof(struct usb_cdc_ncm_ndp16),	\
+		.ndplen_align = 4,				\
+		.dgram_item_len = 1,				\
+		.block_length = 1,				\
+		.fp_index = 1,					\
+		.reserved1 = 0,					\
+		.reserved2 = 0,					\
+		.next_fp_index = 1,				\
+	}
+
+
+#define INIT_NDP32_OPTS {					\
+		.nth_sign = USB_CDC_NCM_NTH32_SIGN,		\
+		.ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN,	\
+		.nth_size = sizeof(struct usb_cdc_ncm_nth32),	\
+		.ndp_size = sizeof(struct usb_cdc_ncm_ndp32),	\
+		.ndplen_align = 8,				\
+		.dgram_item_len = 2,				\
+		.block_length = 2,				\
+		.fp_index = 2,					\
+		.reserved1 = 1,					\
+		.reserved2 = 2,					\
+		.next_fp_index = 2,				\
+	}
+
+static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
+static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
+
+static inline void put_ncm(__le16 **p, unsigned size, unsigned val)
+{
+	switch (size) {
+	case 1:
+		put_unaligned_le16((u16)val, *p);
+		break;
+	case 2:
+		put_unaligned_le32((u32)val, *p);
+
+		break;
+	default:
+		BUG();
+	}
+
+	*p += size;
+}
+
+static inline unsigned get_ncm(__le16 **p, unsigned size)
+{
+	unsigned tmp;
+
+	switch (size) {
+	case 1:
+		tmp = get_unaligned_le16(*p);
+		break;
+	case 2:
+		tmp = get_unaligned_le32(*p);
+		break;
+	default:
+		BUG();
+	}
+
+	*p += size;
+	return tmp;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline void ncm_reset_values(struct f_ncm *ncm)
+{
+	ncm->parser_opts = &ndp16_opts;
+	ncm->is_crc = false;
+	ncm->port.cdc_filter = DEFAULT_FILTER;
+
+	/* doesn't make sense for ncm, fixed size used */
+	ncm->port.header_len = 0;
+
+	ncm->port.fixed_out_len = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
+	ncm->port.fixed_in_len = NTB_DEFAULT_IN_SIZE;
+}
+
+/*
+ * Context: ncm->lock held
+ */
+static void ncm_do_notify(struct f_ncm *ncm)
+{
+	struct usb_request		*req = ncm->notify_req;
+	struct usb_cdc_notification	*event;
+	struct usb_composite_dev	*cdev = ncm->port.func.config->cdev;
+	__le32				*data;
+	int				status;
+
+	/* notification already in flight? */
+	if (!req)
+		return;
+
+	event = req->buf;
+	switch (ncm->notify_state) {
+	case NCM_NOTIFY_NONE:
+		return;
+
+	case NCM_NOTIFY_CONNECT:
+		event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+		if (ncm->is_open)
+			event->wValue = cpu_to_le16(1);
+		else
+			event->wValue = cpu_to_le16(0);
+		event->wLength = 0;
+		req->length = sizeof *event;
+
+		DBG(cdev, "notify connect %s\n",
+				ncm->is_open ? "true" : "false");
+		ncm->notify_state = NCM_NOTIFY_NONE;
+		break;
+
+	case NCM_NOTIFY_SPEED:
+		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
+		event->wValue = cpu_to_le16(0);
+		event->wLength = cpu_to_le16(8);
+		req->length = NCM_STATUS_BYTECOUNT;
+
+		/* SPEED_CHANGE data is up/down speeds in bits/sec */
+		data = req->buf + sizeof *event;
+		data[0] = cpu_to_le32(ncm_bitrate(cdev->gadget));
+		data[1] = data[0];
+
+		DBG(cdev, "notify speed %d\n", ncm_bitrate(cdev->gadget));
+		ncm->notify_state = NCM_NOTIFY_CONNECT;
+		break;
+	}
+	event->bmRequestType = 0xA1;
+	event->wIndex = cpu_to_le16(ncm->ctrl_id);
+
+	ncm->notify_req = NULL;
+	/*
+	 * In double buffering if there is a space in FIFO,
+	 * completion callback can be called right after the call,
+	 * so unlocking
+	 */
+	spin_unlock(&ncm->lock);
+	status = usb_ep_queue(ncm->notify, req, GFP_ATOMIC);
+	spin_lock(&ncm->lock);
+	if (status < 0) {
+		ncm->notify_req = req;
+		DBG(cdev, "notify --> %d\n", status);
+	}
+}
+
+/*
+ * Context: ncm->lock held
+ */
+static void ncm_notify(struct f_ncm *ncm)
+{
+	/*
+	 * NOTE on most versions of Linux, host side cdc-ethernet
+	 * won't listen for notifications until its netdevice opens.
+	 * The first notification then sits in the FIFO for a long
+	 * time, and the second one is queued.
+	 *
+	 * If ncm_notify() is called before the second (CONNECT)
+	 * notification is sent, then it will reset to send the SPEED
+	 * notificaion again (and again, and again), but it's not a problem
+	 */
+	ncm->notify_state = NCM_NOTIFY_SPEED;
+	ncm_do_notify(ncm);
+}
+
+static void ncm_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_ncm			*ncm = req->context;
+	struct usb_composite_dev	*cdev = ncm->port.func.config->cdev;
+	struct usb_cdc_notification	*event = req->buf;
+
+	spin_lock(&ncm->lock);
+	switch (req->status) {
+	case 0:
+		VDBG(cdev, "Notification %02x sent\n",
+		     event->bNotificationType);
+		break;
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		ncm->notify_state = NCM_NOTIFY_NONE;
+		break;
+	default:
+		DBG(cdev, "event %02x --> %d\n",
+			event->bNotificationType, req->status);
+		break;
+	}
+	ncm->notify_req = req;
+	ncm_do_notify(ncm);
+	spin_unlock(&ncm->lock);
+}
+
+static void ncm_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	/* now for SET_NTB_INPUT_SIZE only */
+	unsigned		in_size;
+	struct usb_function	*f = req->context;
+	struct f_ncm		*ncm = func_to_ncm(f);
+	struct usb_composite_dev *cdev = ep->driver_data;
+
+	req->context = NULL;
+	if (req->status || req->actual != req->length) {
+		DBG(cdev, "Bad control-OUT transfer\n");
+		goto invalid;
+	}
+
+	in_size = get_unaligned_le32(req->buf);
+	if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
+	    in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
+		DBG(cdev, "Got wrong INPUT SIZE (%d) from host\n", in_size);
+		goto invalid;
+	}
+
+	ncm->port.fixed_in_len = in_size;
+	VDBG(cdev, "Set NTB INPUT SIZE %d\n", in_size);
+	return;
+
+invalid:
+	usb_ep_set_halt(ep);
+	return;
+}
+
+static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_ncm		*ncm = func_to_ncm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->req;
+	int			value = -EOPNOTSUPP;
+	u16			w_index = le16_to_cpu(ctrl->wIndex);
+	u16			w_value = le16_to_cpu(ctrl->wValue);
+	u16			w_length = le16_to_cpu(ctrl->wLength);
+
+	/*
+	 * composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 */
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_SET_ETHERNET_PACKET_FILTER:
+		/*
+		 * see 6.2.30: no data, wIndex = interface,
+		 * wValue = packet filter bitmap
+		 */
+		if (w_length != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		DBG(cdev, "packet filter %02x\n", w_value);
+		/*
+		 * REVISIT locking of cdc_filter.  This assumes the UDC
+		 * driver won't have a concurrent packet TX irq running on
+		 * another CPU; or that if it does, this write is atomic...
+		 */
+		ncm->port.cdc_filter = w_value;
+		value = 0;
+		break;
+	/*
+	 * and optionally:
+	 * case USB_CDC_SEND_ENCAPSULATED_COMMAND:
+	 * case USB_CDC_GET_ENCAPSULATED_RESPONSE:
+	 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
+	 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_STATISTIC:
+	 */
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_NTB_PARAMETERS:
+
+		if (w_length == 0 || w_value != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		value = w_length > sizeof ntb_parameters ?
+			sizeof ntb_parameters : w_length;
+		memcpy(req->buf, &ntb_parameters, value);
+		VDBG(cdev, "Host asked NTB parameters\n");
+		break;
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_NTB_INPUT_SIZE:
+
+		if (w_length < 4 || w_value != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		put_unaligned_le32(ncm->port.fixed_in_len, req->buf);
+		value = 4;
+		VDBG(cdev, "Host asked INPUT SIZE, sending %d\n",
+		     ncm->port.fixed_in_len);
+		break;
+
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_SET_NTB_INPUT_SIZE:
+	{
+		if (w_length != 4 || w_value != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		req->complete = ncm_ep0out_complete;
+		req->length = w_length;
+		req->context = f;
+
+		value = req->length;
+		break;
+	}
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_NTB_FORMAT:
+	{
+		uint16_t format;
+
+		if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		format = (ncm->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001;
+		put_unaligned_le16(format, req->buf);
+		value = 2;
+		VDBG(cdev, "Host asked NTB FORMAT, sending %d\n", format);
+		break;
+	}
+
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_SET_NTB_FORMAT:
+	{
+		if (w_length != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		switch (w_value) {
+		case 0x0000:
+			ncm->parser_opts = &ndp16_opts;
+			DBG(cdev, "NCM16 selected\n");
+			break;
+		case 0x0001:
+			ncm->parser_opts = &ndp32_opts;
+			DBG(cdev, "NCM32 selected\n");
+			break;
+		default:
+			goto invalid;
+		}
+		value = 0;
+		break;
+	}
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_CRC_MODE:
+	{
+		uint16_t is_crc;
+
+		if (w_length < 2 || w_value != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		is_crc = ncm->is_crc ? 0x0001 : 0x0000;
+		put_unaligned_le16(is_crc, req->buf);
+		value = 2;
+		VDBG(cdev, "Host asked CRC MODE, sending %d\n", is_crc);
+		break;
+	}
+
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_SET_CRC_MODE:
+	{
+		int ndp_hdr_crc = 0;
+
+		if (w_length != 0 || w_index != ncm->ctrl_id)
+			goto invalid;
+		switch (w_value) {
+		case 0x0000:
+			ncm->is_crc = false;
+			ndp_hdr_crc = NCM_NDP_HDR_NOCRC;
+			DBG(cdev, "non-CRC mode selected\n");
+			break;
+		case 0x0001:
+			ncm->is_crc = true;
+			ndp_hdr_crc = NCM_NDP_HDR_CRC;
+			DBG(cdev, "CRC mode selected\n");
+			break;
+		default:
+			goto invalid;
+		}
+		ncm->parser_opts->ndp_sign &= ~NCM_NDP_HDR_CRC_MASK;
+		ncm->parser_opts->ndp_sign |= ndp_hdr_crc;
+		value = 0;
+		break;
+	}
+
+	/* and disabled in ncm descriptor: */
+	/* case USB_CDC_GET_NET_ADDRESS: */
+	/* case USB_CDC_SET_NET_ADDRESS: */
+	/* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */
+	/* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */
+
+	default:
+invalid:
+		DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* respond with data transfer or status phase? */
+	if (value >= 0) {
+		DBG(cdev, "ncm req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "ncm req %02x.%02x response err %d\n",
+					ctrl->bRequestType, ctrl->bRequest,
+					value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+
+static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_ncm		*ncm = func_to_ncm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* Control interface has only altsetting 0 */
+	if (intf == ncm->ctrl_id) {
+		if (alt != 0)
+			goto fail;
+
+		if (ncm->notify->driver_data) {
+			DBG(cdev, "reset ncm control %d\n", intf);
+			usb_ep_disable(ncm->notify);
+		} else {
+			DBG(cdev, "init ncm ctrl %d\n", intf);
+			ncm->notify_desc = ep_choose(cdev->gadget,
+					ncm->hs.notify,
+					ncm->fs.notify);
+		}
+		usb_ep_enable(ncm->notify, ncm->notify_desc);
+		ncm->notify->driver_data = ncm;
+
+	/* Data interface has two altsettings, 0 and 1 */
+	} else if (intf == ncm->data_id) {
+		if (alt > 1)
+			goto fail;
+
+		if (ncm->port.in_ep->driver_data) {
+			DBG(cdev, "reset ncm\n");
+			gether_disconnect(&ncm->port);
+			ncm_reset_values(ncm);
+		}
+
+		/*
+		 * CDC Network only sends data in non-default altsettings.
+		 * Changing altsettings resets filters, statistics, etc.
+		 */
+		if (alt == 1) {
+			struct net_device	*net;
+
+			if (!ncm->port.in) {
+				DBG(cdev, "init ncm\n");
+				ncm->port.in = ep_choose(cdev->gadget,
+							 ncm->hs.in,
+							 ncm->fs.in);
+				ncm->port.out = ep_choose(cdev->gadget,
+							  ncm->hs.out,
+							  ncm->fs.out);
+			}
+
+			/* TODO */
+			/* Enable zlps by default for NCM conformance;
+			 * override for musb_hdrc (avoids txdma ovhead)
+			 */
+			ncm->port.is_zlp_ok = !(
+				gadget_is_musbhdrc(cdev->gadget)
+				);
+			ncm->port.cdc_filter = DEFAULT_FILTER;
+			DBG(cdev, "activate ncm\n");
+			net = gether_connect(&ncm->port);
+			if (IS_ERR(net))
+				return PTR_ERR(net);
+		}
+
+		spin_lock(&ncm->lock);
+		ncm_notify(ncm);
+		spin_unlock(&ncm->lock);
+	} else
+		goto fail;
+
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/*
+ * Because the data interface supports multiple altsettings,
+ * this NCM function *MUST* implement a get_alt() method.
+ */
+static int ncm_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_ncm		*ncm = func_to_ncm(f);
+
+	if (intf == ncm->ctrl_id)
+		return 0;
+	return ncm->port.in_ep->driver_data ? 1 : 0;
+}
+
+static struct sk_buff *ncm_wrap_ntb(struct gether *port,
+				    struct sk_buff *skb)
+{
+	struct f_ncm	*ncm = func_to_ncm(&port->func);
+	struct sk_buff	*skb2;
+	int		ncb_len = 0;
+	__le16		*tmp;
+	int		div = ntb_parameters.wNdpInDivisor;
+	int		rem = ntb_parameters.wNdpInPayloadRemainder;
+	int		pad;
+	int		ndp_align = ntb_parameters.wNdpInAlignment;
+	int		ndp_pad;
+	unsigned	max_size = ncm->port.fixed_in_len;
+	struct ndp_parser_opts *opts = ncm->parser_opts;
+	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
+
+	ncb_len += opts->nth_size;
+	ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
+	ncb_len += ndp_pad;
+	ncb_len += opts->ndp_size;
+	ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */
+	ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */
+	pad = ALIGN(ncb_len, div) + rem - ncb_len;
+	ncb_len += pad;
+
+	if (ncb_len + skb->len + crc_len > max_size) {
+		dev_kfree_skb_any(skb);
+		return NULL;
+	}
+
+	skb2 = skb_copy_expand(skb, ncb_len,
+			       max_size - skb->len - ncb_len - crc_len,
+			       GFP_ATOMIC);
+	dev_kfree_skb_any(skb);
+	if (!skb2)
+		return NULL;
+
+	skb = skb2;
+
+	tmp = (void *) skb_push(skb, ncb_len);
+	memset(tmp, 0, ncb_len);
+
+	put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */
+	tmp += 2;
+	/* wHeaderLength */
+	put_unaligned_le16(opts->nth_size, tmp++);
+	tmp++; /* skip wSequence */
+	put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */
+	/* (d)wFpIndex */
+	/* the first pointer is right after the NTH + align */
+	put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad);
+
+	tmp = (void *)tmp + ndp_pad;
+
+	/* NDP */
+	put_unaligned_le32(opts->ndp_sign, tmp); /* dwSignature */
+	tmp += 2;
+	/* wLength */
+	put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
+
+	tmp += opts->reserved1;
+	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
+	tmp += opts->reserved2;
+
+	if (ncm->is_crc) {
+		uint32_t crc;
+
+		crc = ~crc32_le(~0,
+				skb->data + ncb_len,
+				skb->len - ncb_len);
+		put_unaligned_le32(crc, skb->data + skb->len);
+		skb_put(skb, crc_len);
+	}
+
+	/* (d)wDatagramIndex[0] */
+	put_ncm(&tmp, opts->dgram_item_len, ncb_len);
+	/* (d)wDatagramLength[0] */
+	put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len);
+	/* (d)wDatagramIndex[1] and  (d)wDatagramLength[1] already zeroed */
+
+	if (skb->len > MAX_TX_NONFIXED)
+		memset(skb_put(skb, max_size - skb->len),
+		       0, max_size - skb->len);
+
+	return skb;
+}
+
+static int ncm_unwrap_ntb(struct gether *port,
+			  struct sk_buff *skb,
+			  struct sk_buff_head *list)
+{
+	struct f_ncm	*ncm = func_to_ncm(&port->func);
+	__le16		*tmp = (void *) skb->data;
+	unsigned	index, index2;
+	unsigned	dg_len, dg_len2;
+	unsigned	ndp_len;
+	struct sk_buff	*skb2;
+	int		ret = -EINVAL;
+	unsigned	max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
+	struct ndp_parser_opts *opts = ncm->parser_opts;
+	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
+	int		dgram_counter;
+
+	/* dwSignature */
+	if (get_unaligned_le32(tmp) != opts->nth_sign) {
+		INFO(port->func.config->cdev, "Wrong NTH SIGN, skblen %d\n",
+			skb->len);
+		print_hex_dump(KERN_INFO, "HEAD:", DUMP_PREFIX_ADDRESS, 32, 1,
+			       skb->data, 32, false);
+
+		goto err;
+	}
+	tmp += 2;
+	/* wHeaderLength */
+	if (get_unaligned_le16(tmp++) != opts->nth_size) {
+		INFO(port->func.config->cdev, "Wrong NTB headersize\n");
+		goto err;
+	}
+	tmp++; /* skip wSequence */
+
+	/* (d)wBlockLength */
+	if (get_ncm(&tmp, opts->block_length) > max_size) {
+		INFO(port->func.config->cdev, "OUT size exceeded\n");
+		goto err;
+	}
+
+	index = get_ncm(&tmp, opts->fp_index);
+	/* NCM 3.2 */
+	if (((index % 4) != 0) && (index < opts->nth_size)) {
+		INFO(port->func.config->cdev, "Bad index: %x\n",
+			index);
+		goto err;
+	}
+
+	/* walk through NDP */
+	tmp = ((void *)skb->data) + index;
+	if (get_unaligned_le32(tmp) != opts->ndp_sign) {
+		INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
+		goto err;
+	}
+	tmp += 2;
+
+	ndp_len = get_unaligned_le16(tmp++);
+	/*
+	 * NCM 3.3.1
+	 * entry is 2 items
+	 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
+	 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
+	 */
+	if ((ndp_len < opts->ndp_size + 2 * 2 * (opts->dgram_item_len * 2))
+	    || (ndp_len % opts->ndplen_align != 0)) {
+		INFO(port->func.config->cdev, "Bad NDP length: %x\n", ndp_len);
+		goto err;
+	}
+	tmp += opts->reserved1;
+	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
+	tmp += opts->reserved2;
+
+	ndp_len -= opts->ndp_size;
+	index2 = get_ncm(&tmp, opts->dgram_item_len);
+	dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
+	dgram_counter = 0;
+
+	do {
+		index = index2;
+		dg_len = dg_len2;
+		if (dg_len < 14 + crc_len) { /* ethernet header + crc */
+			INFO(port->func.config->cdev, "Bad dgram length: %x\n",
+			     dg_len);
+			goto err;
+		}
+		if (ncm->is_crc) {
+			uint32_t crc, crc2;
+
+			crc = get_unaligned_le32(skb->data +
+						 index + dg_len - crc_len);
+			crc2 = ~crc32_le(~0,
+					 skb->data + index,
+					 dg_len - crc_len);
+			if (crc != crc2) {
+				INFO(port->func.config->cdev, "Bad CRC\n");
+				goto err;
+			}
+		}
+
+		index2 = get_ncm(&tmp, opts->dgram_item_len);
+		dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
+
+		if (index2 == 0 || dg_len2 == 0) {
+			skb2 = skb;
+		} else {
+			skb2 = skb_clone(skb, GFP_ATOMIC);
+			if (skb2 == NULL)
+				goto err;
+		}
+
+		if (!skb_pull(skb2, index)) {
+			ret = -EOVERFLOW;
+			goto err;
+		}
+
+		skb_trim(skb2, dg_len - crc_len);
+		skb_queue_tail(list, skb2);
+
+		ndp_len -= 2 * (opts->dgram_item_len * 2);
+
+		dgram_counter++;
+
+		if (index2 == 0 || dg_len2 == 0)
+			break;
+	} while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */
+
+	VDBG(port->func.config->cdev,
+	     "Parsed NTB with %d frames\n", dgram_counter);
+	return 0;
+err:
+	skb_queue_purge(list);
+	dev_kfree_skb_any(skb);
+	return ret;
+}
+
+static void ncm_disable(struct usb_function *f)
+{
+	struct f_ncm		*ncm = func_to_ncm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "ncm deactivated\n");
+
+	if (ncm->port.in_ep->driver_data)
+		gether_disconnect(&ncm->port);
+
+	if (ncm->notify->driver_data) {
+		usb_ep_disable(ncm->notify);
+		ncm->notify->driver_data = NULL;
+		ncm->notify_desc = NULL;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Callbacks let us notify the host about connect/disconnect when the
+ * net device is opened or closed.
+ *
+ * For testing, note that link states on this side include both opened
+ * and closed variants of:
+ *
+ *   - disconnected/unconfigured
+ *   - configured but inactive (data alt 0)
+ *   - configured and active (data alt 1)
+ *
+ * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and
+ * SET_INTERFACE (altsetting).  Remember also that "configured" doesn't
+ * imply the host is actually polling the notification endpoint, and
+ * likewise that "active" doesn't imply it's actually using the data
+ * endpoints for traffic.
+ */
+
+static void ncm_open(struct gether *geth)
+{
+	struct f_ncm		*ncm = func_to_ncm(&geth->func);
+
+	DBG(ncm->port.func.config->cdev, "%s\n", __func__);
+
+	spin_lock(&ncm->lock);
+	ncm->is_open = true;
+	ncm_notify(ncm);
+	spin_unlock(&ncm->lock);
+}
+
+static void ncm_close(struct gether *geth)
+{
+	struct f_ncm		*ncm = func_to_ncm(&geth->func);
+
+	DBG(ncm->port.func.config->cdev, "%s\n", __func__);
+
+	spin_lock(&ncm->lock);
+	ncm->is_open = false;
+	ncm_notify(ncm);
+	spin_unlock(&ncm->lock);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int __init
+ncm_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_ncm		*ncm = func_to_ncm(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	ncm->ctrl_id = status;
+	ncm_iad_desc.bFirstInterface = status;
+
+	ncm_control_intf.bInterfaceNumber = status;
+	ncm_union_desc.bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	ncm->data_id = status;
+
+	ncm_data_nop_intf.bInterfaceNumber = status;
+	ncm_data_intf.bInterfaceNumber = status;
+	ncm_union_desc.bSlaveInterface0 = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_in_desc);
+	if (!ep)
+		goto fail;
+	ncm->port.in_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc);
+	if (!ep)
+		goto fail;
+	ncm->port.out_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc);
+	if (!ep)
+		goto fail;
+	ncm->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	status = -ENOMEM;
+
+	/* allocate notification request and buffer */
+	ncm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+	if (!ncm->notify_req)
+		goto fail;
+	ncm->notify_req->buf = kmalloc(NCM_STATUS_BYTECOUNT, GFP_KERNEL);
+	if (!ncm->notify_req->buf)
+		goto fail;
+	ncm->notify_req->context = ncm;
+	ncm->notify_req->complete = ncm_notify_complete;
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(ncm_fs_function);
+	if (!f->descriptors)
+		goto fail;
+
+	ncm->fs.in = usb_find_endpoint(ncm_fs_function,
+			f->descriptors, &fs_ncm_in_desc);
+	ncm->fs.out = usb_find_endpoint(ncm_fs_function,
+			f->descriptors, &fs_ncm_out_desc);
+	ncm->fs.notify = usb_find_endpoint(ncm_fs_function,
+			f->descriptors, &fs_ncm_notify_desc);
+
+	/*
+	 * support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_ncm_in_desc.bEndpointAddress =
+				fs_ncm_in_desc.bEndpointAddress;
+		hs_ncm_out_desc.bEndpointAddress =
+				fs_ncm_out_desc.bEndpointAddress;
+		hs_ncm_notify_desc.bEndpointAddress =
+				fs_ncm_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(ncm_hs_function);
+		if (!f->hs_descriptors)
+			goto fail;
+
+		ncm->hs.in = usb_find_endpoint(ncm_hs_function,
+				f->hs_descriptors, &hs_ncm_in_desc);
+		ncm->hs.out = usb_find_endpoint(ncm_hs_function,
+				f->hs_descriptors, &hs_ncm_out_desc);
+		ncm->hs.notify = usb_find_endpoint(ncm_hs_function,
+				f->hs_descriptors, &hs_ncm_notify_desc);
+	}
+
+	/*
+	 * NOTE:  all that is done without knowing or caring about
+	 * the network link ... which is unavailable to this code
+	 * until we're activated via set_alt().
+	 */
+
+	ncm->port.open = ncm_open;
+	ncm->port.close = ncm_close;
+
+	DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			ncm->port.in_ep->name, ncm->port.out_ep->name,
+			ncm->notify->name);
+	return 0;
+
+fail:
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
+	if (ncm->notify_req) {
+		kfree(ncm->notify_req->buf);
+		usb_ep_free_request(ncm->notify, ncm->notify_req);
+	}
+
+	/* we might as well release our claims on endpoints */
+	if (ncm->notify)
+		ncm->notify->driver_data = NULL;
+	if (ncm->port.out)
+		ncm->port.out_ep->driver_data = NULL;
+	if (ncm->port.in)
+		ncm->port.in_ep->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+ncm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_ncm		*ncm = func_to_ncm(f);
+
+	DBG(c->cdev, "ncm unbind\n");
+
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+
+	kfree(ncm->notify_req->buf);
+	usb_ep_free_request(ncm->notify, ncm->notify_req);
+
+	ncm_string_defs[1].s = NULL;
+	kfree(ncm);
+}
+
+/**
+ * ncm_bind_config - add CDC Network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ *	side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup().  Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	struct f_ncm	*ncm;
+	int		status;
+
+	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
+		return -EINVAL;
+
+	/* maybe allocate device-global string IDs */
+	if (ncm_string_defs[0].id == 0) {
+
+		/* control interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ncm_string_defs[STRING_CTRL_IDX].id = status;
+		ncm_control_intf.iInterface = status;
+
+		/* data interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ncm_string_defs[STRING_DATA_IDX].id = status;
+		ncm_data_nop_intf.iInterface = status;
+		ncm_data_intf.iInterface = status;
+
+		/* MAC address */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ncm_string_defs[STRING_MAC_IDX].id = status;
+		ecm_desc.iMACAddress = status;
+
+		/* IAD */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ncm_string_defs[STRING_IAD_IDX].id = status;
+		ncm_iad_desc.iFunction = status;
+	}
+
+	/* allocate and initialize one new instance */
+	ncm = kzalloc(sizeof *ncm, GFP_KERNEL);
+	if (!ncm)
+		return -ENOMEM;
+
+	/* export host's Ethernet address in CDC format */
+	snprintf(ncm->ethaddr, sizeof ncm->ethaddr,
+		"%02X%02X%02X%02X%02X%02X",
+		ethaddr[0], ethaddr[1], ethaddr[2],
+		ethaddr[3], ethaddr[4], ethaddr[5]);
+	ncm_string_defs[1].s = ncm->ethaddr;
+
+	spin_lock_init(&ncm->lock);
+	ncm_reset_values(ncm);
+	ncm->port.is_fixed = true;
+
+	ncm->port.func.name = "cdc_network";
+	ncm->port.func.strings = ncm_strings;
+	/* descriptors are per-instance copies */
+	ncm->port.func.bind = ncm_bind;
+	ncm->port.func.unbind = ncm_unbind;
+	ncm->port.func.set_alt = ncm_set_alt;
+	ncm->port.func.get_alt = ncm_get_alt;
+	ncm->port.func.setup = ncm_setup;
+	ncm->port.func.disable = ncm_disable;
+
+	ncm->port.wrap = ncm_wrap_ntb;
+	ncm->port.unwrap = ncm_unwrap_ntb;
+
+	status = usb_add_function(c, &ncm->port.func);
+	if (status) {
+		ncm_string_defs[1].s = NULL;
+		kfree(ncm);
+	}
+	return status;
+}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index d4fdf65..a6eacb5 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3392,25 +3392,28 @@
 		dev_set_name(&curlun->dev,"%s-lun%d",
 			     dev_name(&gadget->dev), i);
 
-		if ((rc = device_register(&curlun->dev)) != 0) {
+		kref_get(&fsg->ref);
+		rc = device_register(&curlun->dev);
+		if (rc) {
 			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-			goto out;
-		}
-		if ((rc = device_create_file(&curlun->dev,
-					&dev_attr_ro)) != 0 ||
-				(rc = device_create_file(&curlun->dev,
-					&dev_attr_nofua)) != 0 ||
-				(rc = device_create_file(&curlun->dev,
-					&dev_attr_file)) != 0) {
-			device_unregister(&curlun->dev);
+			put_device(&curlun->dev);
 			goto out;
 		}
 		curlun->registered = 1;
-		kref_get(&fsg->ref);
+
+		rc = device_create_file(&curlun->dev, &dev_attr_ro);
+		if (rc)
+			goto out;
+		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
+		if (rc)
+			goto out;
+		rc = device_create_file(&curlun->dev, &dev_attr_file);
+		if (rc)
+			goto out;
 
 		if (mod_data.file[i] && *mod_data.file[i]) {
-			if ((rc = fsg_lun_open(curlun,
-					mod_data.file[i])) != 0)
+			rc = fsg_lun_open(curlun, mod_data.file[i]);
+			if (rc)
 				goto out;
 		} else if (!mod_data.removable) {
 			ERROR(fsg, "no file given for LUN%d\n", i);
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index 5bdbfe6..77b1eb5 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -93,9 +93,9 @@
 
 	/* workaround ENGcm09152 for i.MX35 */
 	if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
-		v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+		v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
 				USBPHYCTRL_OTGBASE_OFFSET));
-		writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+		writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
 				USBPHYCTRL_OTGBASE_OFFSET));
 	}
 #endif
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index af75e36..ebf6970 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -1,7 +1,29 @@
+/*
+ * g_ffs.c -- user mode file system API for USB composite function controllers
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ * Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define pr_fmt(fmt) "g_ffs: " fmt
+
 #include <linux/module.h>
 #include <linux/utsname.h>
 
-
 /*
  * kbuild is not very cooperative with respect to linking separately
  * compiled library objects into one module.  So for now we won't use
@@ -43,7 +65,6 @@
 
 #include "f_fs.c"
 
-
 #define DRIVER_NAME	"g_ffs"
 #define DRIVER_DESC	"USB Function Filesystem"
 #define DRIVER_VERSION	"24 Aug 2004"
@@ -73,8 +94,6 @@
 module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte,   0644);
 MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
 
-
-
 static const struct usb_descriptor_header *gfs_otg_desc[] = {
 	(const struct usb_descriptor_header *)
 	&(const struct usb_otg_descriptor) {
@@ -91,8 +110,7 @@
 	NULL
 };
 
-/* string IDs are assigned dynamically */
-
+/* String IDs are assigned dynamically */
 static struct usb_string gfs_strings[] = {
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 	{ .s = "FunctionFS + RNDIS" },
@@ -114,8 +132,6 @@
 	NULL,
 };
 
-
-
 struct gfs_configuration {
 	struct usb_configuration c;
 	int (*eth)(struct usb_configuration *c, u8 *ethaddr);
@@ -138,7 +154,6 @@
 #endif
 };
 
-
 static int gfs_bind(struct usb_composite_dev *cdev);
 static int gfs_unbind(struct usb_composite_dev *cdev);
 static int gfs_do_config(struct usb_configuration *c);
@@ -151,11 +166,9 @@
 	.iProduct	= DRIVER_DESC,
 };
 
-
 static struct ffs_data *gfs_ffs_data;
 static unsigned long gfs_registered;
 
-
 static int  gfs_init(void)
 {
 	ENTER();
@@ -175,7 +188,6 @@
 }
 module_exit(gfs_exit);
 
-
 static int functionfs_ready_callback(struct ffs_data *ffs)
 {
 	int ret;
@@ -200,14 +212,11 @@
 		usb_composite_unregister(&gfs_driver);
 }
 
-
 static int functionfs_check_dev_callback(const char *dev_name)
 {
 	return 0;
 }
 
-
-
 static int gfs_bind(struct usb_composite_dev *cdev)
 {
 	int ret, i;
@@ -274,7 +283,6 @@
 	return 0;
 }
 
-
 static int gfs_do_config(struct usb_configuration *c)
 {
 	struct gfs_configuration *gc =
@@ -315,7 +323,6 @@
 	return 0;
 }
 
-
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
 
 static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index e511fec..5c2720d 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -96,7 +96,7 @@
 
 /* Mentor high speed "dual role" controller, in peripheral role */
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
-#define gadget_is_musbhdrc(g)	!strcmp("musb_hdrc", (g)->name)
+#define gadget_is_musbhdrc(g)	!strcmp("musb-hdrc", (g)->name)
 #else
 #define gadget_is_musbhdrc(g)	0
 #endif
@@ -120,10 +120,10 @@
 #define gadget_is_fsl_qe(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_CI13XXX
-#define gadget_is_ci13xxx(g)	(!strcmp("ci13xxx_udc", (g)->name))
+#ifdef CONFIG_USB_GADGET_CI13XXX_PCI
+#define gadget_is_ci13xxx_pci(g)	(!strcmp("ci13xxx_pci", (g)->name))
 #else
-#define gadget_is_ci13xxx(g)	0
+#define gadget_is_ci13xxx_pci(g)	0
 #endif
 
 // CONFIG_USB_GADGET_SX2
@@ -142,6 +142,17 @@
 #define gadget_is_s3c_hsotg(g)    0
 #endif
 
+#ifdef CONFIG_USB_GADGET_EG20T
+#define	gadget_is_pch(g)	(!strcmp("pch_udc", (g)->name))
+#else
+#define	gadget_is_pch(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_CI13XXX_MSM
+#define gadget_is_ci13xxx_msm(g)	(!strcmp("ci13xxx_msm", (g)->name))
+#else
+#define gadget_is_ci13xxx_msm(g)	0
+#endif
 
 /**
  * usb_gadget_controller_number - support bcdDevice id convention
@@ -192,7 +203,7 @@
 		return 0x21;
 	else if (gadget_is_fsl_qe(gadget))
 		return 0x22;
-	else if (gadget_is_ci13xxx(gadget))
+	else if (gadget_is_ci13xxx_pci(gadget))
 		return 0x23;
 	else if (gadget_is_langwell(gadget))
 		return 0x24;
@@ -200,6 +211,10 @@
 		return 0x25;
 	else if (gadget_is_s3c_hsotg(gadget))
 		return 0x26;
+	else if (gadget_is_pch(gadget))
+		return 0x27;
+	else if (gadget_is_ci13xxx_msm(gadget))
+		return 0x28;
 	return -ENOENT;
 }
 
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index ed02664..1210534 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1191,13 +1191,17 @@
 	return IRQ_HANDLED;
 }
 
+#ifndef MX1_INT_USBD0
+#define MX1_INT_USBD0 MX1_USBD_INT0
+#endif
+
 static irqreturn_t imx_udc_bulk_irq(int irq, void *dev)
 {
 	struct imx_udc_struct *imx_usb = dev;
-	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - USBD_INT0];
+	struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - MX1_INT_USBD0];
 	int intr = __raw_readl(imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
 
-	dump_ep_intr(__func__, irq - USBD_INT0, intr, imx_usb->dev);
+	dump_ep_intr(__func__, irq - MX1_INT_USBD0, intr, imx_usb->dev);
 
 	if (!imx_usb->driver) {
 		__raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h
index b48ad59..7136c24 100644
--- a/drivers/usb/gadget/imx_udc.h
+++ b/drivers/usb/gadget/imx_udc.h
@@ -23,9 +23,6 @@
 /* Helper macros */
 #define EP_NO(ep)	((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
 #define EP_DIR(ep)	((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
-#define irq_to_ep(irq)	(((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) \
-		? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
-#define ep_to_irq(ep)	(EP_NO((ep)) + USBD_INT0)
 #define IMX_USB_NB_EP	6
 
 /* Driver structures */
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index b8ec954..7779724 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -2225,6 +2225,7 @@
 	u16	wValue = le16_to_cpu(setup->wValue);
 	u16	wIndex = le16_to_cpu(setup->wIndex);
 	u16	wLength = le16_to_cpu(setup->wLength);
+	u32	portsc1;
 
 	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
@@ -2313,6 +2314,28 @@
 					dev->dev_status &= ~(1 << wValue);
 				}
 				break;
+			case USB_DEVICE_TEST_MODE:
+				dev_dbg(&dev->pdev->dev, "SETUP: TEST MODE\n");
+				if ((wIndex & 0xff) ||
+					(dev->gadget.speed != USB_SPEED_HIGH))
+					ep0_stall(dev);
+
+				switch (wIndex >> 8) {
+				case TEST_J:
+				case TEST_K:
+				case TEST_SE0_NAK:
+				case TEST_PACKET:
+				case TEST_FORCE_EN:
+					if (prime_status_phase(dev, EP_DIR_IN))
+						ep0_stall(dev);
+					portsc1 = readl(&dev->op_regs->portsc1);
+					portsc1 |= (wIndex & 0xf00) << 8;
+					writel(portsc1, &dev->op_regs->portsc1);
+					goto end;
+				default:
+					rc = -EOPNOTSUPP;
+				}
+				break;
 			default:
 				rc = -EOPNOTSUPP;
 				break;
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 0769179..0182242 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -102,7 +102,7 @@
 };
 FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
 
-static unsigned long msg_registered = 0;
+static unsigned long msg_registered;
 static void msg_cleanup(void);
 
 static int msg_thread_exits(struct fsg_common *common)
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
new file mode 100644
index 0000000..65f1f7c
--- /dev/null
+++ b/drivers/usb/gadget/mv_udc.h
@@ -0,0 +1,294 @@
+
+#ifndef __MV_UDC_H
+#define __MV_UDC_H
+
+#define VUSBHS_MAX_PORTS	8
+
+#define DQH_ALIGNMENT		2048
+#define DTD_ALIGNMENT		64
+#define DMA_BOUNDARY		4096
+
+#define EP_DIR_IN	1
+#define EP_DIR_OUT	0
+
+#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+#define EP0_MAX_PKT_SIZE	64
+/* ep0 transfer state */
+#define WAIT_FOR_SETUP		0
+#define DATA_STATE_XMIT		1
+#define DATA_STATE_NEED_ZLP	2
+#define WAIT_FOR_OUT_STATUS	3
+#define DATA_STATE_RECV		4
+
+#define CAPLENGTH_MASK		(0xff)
+#define DCCPARAMS_DEN_MASK	(0x1f)
+
+#define HCSPARAMS_PPC		(0x10)
+
+/* Frame Index Register Bit Masks */
+#define USB_FRINDEX_MASKS	0x3fff
+
+/* Command Register Bit Masks */
+#define USBCMD_RUN_STOP				(0x00000001)
+#define USBCMD_CTRL_RESET			(0x00000002)
+#define USBCMD_SETUP_TRIPWIRE_SET		(0x00002000)
+#define USBCMD_SETUP_TRIPWIRE_CLEAR		(~USBCMD_SETUP_TRIPWIRE_SET)
+
+#define USBCMD_ATDTW_TRIPWIRE_SET		(0x00004000)
+#define USBCMD_ATDTW_TRIPWIRE_CLEAR		(~USBCMD_ATDTW_TRIPWIRE_SET)
+
+/* bit 15,3,2 are for frame list size */
+#define USBCMD_FRAME_SIZE_1024			(0x00000000) /* 000 */
+#define USBCMD_FRAME_SIZE_512			(0x00000004) /* 001 */
+#define USBCMD_FRAME_SIZE_256			(0x00000008) /* 010 */
+#define USBCMD_FRAME_SIZE_128			(0x0000000C) /* 011 */
+#define USBCMD_FRAME_SIZE_64			(0x00008000) /* 100 */
+#define USBCMD_FRAME_SIZE_32			(0x00008004) /* 101 */
+#define USBCMD_FRAME_SIZE_16			(0x00008008) /* 110 */
+#define USBCMD_FRAME_SIZE_8			(0x0000800C) /* 111 */
+
+#define EPCTRL_TX_ALL_MASK			(0xFFFF0000)
+#define EPCTRL_RX_ALL_MASK			(0x0000FFFF)
+
+#define EPCTRL_TX_DATA_TOGGLE_RST		(0x00400000)
+#define EPCTRL_TX_EP_STALL			(0x00010000)
+#define EPCTRL_RX_EP_STALL			(0x00000001)
+#define EPCTRL_RX_DATA_TOGGLE_RST		(0x00000040)
+#define EPCTRL_RX_ENABLE			(0x00000080)
+#define EPCTRL_TX_ENABLE			(0x00800000)
+#define EPCTRL_CONTROL				(0x00000000)
+#define EPCTRL_ISOCHRONOUS			(0x00040000)
+#define EPCTRL_BULK				(0x00080000)
+#define EPCTRL_INT				(0x000C0000)
+#define EPCTRL_TX_TYPE				(0x000C0000)
+#define EPCTRL_RX_TYPE				(0x0000000C)
+#define EPCTRL_DATA_TOGGLE_INHIBIT		(0x00000020)
+#define EPCTRL_TX_EP_TYPE_SHIFT			(18)
+#define EPCTRL_RX_EP_TYPE_SHIFT			(2)
+
+#define EPCOMPLETE_MAX_ENDPOINTS		(16)
+
+/* endpoint list address bit masks */
+#define USB_EP_LIST_ADDRESS_MASK              0xfffff800
+
+#define PORTSCX_W1C_BITS			0x2a
+#define PORTSCX_PORT_RESET			0x00000100
+#define PORTSCX_PORT_POWER			0x00001000
+#define PORTSCX_FORCE_FULL_SPEED_CONNECT	0x01000000
+#define PORTSCX_PAR_XCVR_SELECT			0xC0000000
+#define PORTSCX_PORT_FORCE_RESUME		0x00000040
+#define PORTSCX_PORT_SUSPEND			0x00000080
+#define PORTSCX_PORT_SPEED_FULL			0x00000000
+#define PORTSCX_PORT_SPEED_LOW			0x04000000
+#define PORTSCX_PORT_SPEED_HIGH			0x08000000
+#define PORTSCX_PORT_SPEED_MASK			0x0C000000
+
+/* USB MODE Register Bit Masks */
+#define USBMODE_CTRL_MODE_IDLE			0x00000000
+#define USBMODE_CTRL_MODE_DEVICE		0x00000002
+#define USBMODE_CTRL_MODE_HOST			0x00000003
+#define USBMODE_CTRL_MODE_RSV			0x00000001
+#define USBMODE_SETUP_LOCK_OFF			0x00000008
+#define USBMODE_STREAM_DISABLE			0x00000010
+
+/* USB STS Register Bit Masks */
+#define USBSTS_INT			0x00000001
+#define USBSTS_ERR			0x00000002
+#define USBSTS_PORT_CHANGE		0x00000004
+#define USBSTS_FRM_LST_ROLL		0x00000008
+#define USBSTS_SYS_ERR			0x00000010
+#define USBSTS_IAA			0x00000020
+#define USBSTS_RESET			0x00000040
+#define USBSTS_SOF			0x00000080
+#define USBSTS_SUSPEND			0x00000100
+#define USBSTS_HC_HALTED		0x00001000
+#define USBSTS_RCL			0x00002000
+#define USBSTS_PERIODIC_SCHEDULE	0x00004000
+#define USBSTS_ASYNC_SCHEDULE		0x00008000
+
+
+/* Interrupt Enable Register Bit Masks */
+#define USBINTR_INT_EN                          (0x00000001)
+#define USBINTR_ERR_INT_EN                      (0x00000002)
+#define USBINTR_PORT_CHANGE_DETECT_EN           (0x00000004)
+
+#define USBINTR_ASYNC_ADV_AAE                   (0x00000020)
+#define USBINTR_ASYNC_ADV_AAE_ENABLE            (0x00000020)
+#define USBINTR_ASYNC_ADV_AAE_DISABLE           (0xFFFFFFDF)
+
+#define USBINTR_RESET_EN                        (0x00000040)
+#define USBINTR_SOF_UFRAME_EN                   (0x00000080)
+#define USBINTR_DEVICE_SUSPEND                  (0x00000100)
+
+#define USB_DEVICE_ADDRESS_MASK			(0xfe000000)
+#define USB_DEVICE_ADDRESS_BIT_SHIFT		(25)
+
+struct mv_cap_regs {
+	u32	caplength_hciversion;
+	u32	hcsparams;	/* HC structural parameters */
+	u32	hccparams;	/* HC Capability Parameters*/
+	u32	reserved[5];
+	u32	dciversion;	/* DC version number and reserved 16 bits */
+	u32	dccparams;	/* DC Capability Parameters */
+};
+
+struct mv_op_regs {
+	u32	usbcmd;		/* Command register */
+	u32	usbsts;		/* Status register */
+	u32	usbintr;	/* Interrupt enable */
+	u32	frindex;	/* Frame index */
+	u32	reserved1[1];
+	u32	deviceaddr;	/* Device Address */
+	u32	eplistaddr;	/* Endpoint List Address */
+	u32	ttctrl;		/* HOST TT status and control */
+	u32	burstsize;	/* Programmable Burst Size */
+	u32	txfilltuning;	/* Host Transmit Pre-Buffer Packet Tuning */
+	u32	reserved[4];
+	u32	epnak;		/* Endpoint NAK */
+	u32	epnaken;	/* Endpoint NAK Enable */
+	u32	configflag;	/* Configured Flag register */
+	u32	portsc[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */
+	u32	otgsc;
+	u32	usbmode;	/* USB Host/Device mode */
+	u32	epsetupstat;	/* Endpoint Setup Status */
+	u32	epprime;	/* Endpoint Initialize */
+	u32	epflush;	/* Endpoint De-initialize */
+	u32	epstatus;	/* Endpoint Status */
+	u32	epcomplete;	/* Endpoint Interrupt On Complete */
+	u32	epctrlx[16];	/* Endpoint Control, where x = 0.. 15 */
+	u32	mcr;		/* Mux Control */
+	u32	isr;		/* Interrupt Status */
+	u32	ier;		/* Interrupt Enable */
+};
+
+struct mv_udc {
+	struct usb_gadget		gadget;
+	struct usb_gadget_driver	*driver;
+	spinlock_t			lock;
+	struct completion		*done;
+	struct platform_device		*dev;
+	int				irq;
+
+	struct mv_cap_regs __iomem	*cap_regs;
+	struct mv_op_regs __iomem	*op_regs;
+	unsigned int			phy_regs;
+	unsigned int			max_eps;
+	struct mv_dqh			*ep_dqh;
+	size_t				ep_dqh_size;
+	dma_addr_t			ep_dqh_dma;
+
+	struct dma_pool			*dtd_pool;
+	struct mv_ep			*eps;
+
+	struct mv_dtd			*dtd_head;
+	struct mv_dtd			*dtd_tail;
+	unsigned int			dtd_entries;
+
+	struct mv_req			*status_req;
+	struct usb_ctrlrequest		local_setup_buff;
+
+	unsigned int		resume_state;	/* USB state to resume */
+	unsigned int		usb_state;	/* USB current state */
+	unsigned int		ep0_state;	/* Endpoint zero state */
+	unsigned int		ep0_dir;
+
+	unsigned int		dev_addr;
+
+	int			errors;
+	unsigned		softconnect:1,
+				vbus_active:1,
+				remote_wakeup:1,
+				softconnected:1,
+				force_fs:1;
+	struct clk		*clk;
+};
+
+/* endpoint data structure */
+struct mv_ep {
+	struct usb_ep		ep;
+	struct mv_udc		*udc;
+	struct list_head	queue;
+	struct mv_dqh		*dqh;
+	const struct usb_endpoint_descriptor	*desc;
+	u32			direction;
+	char			name[14];
+	unsigned		stopped:1,
+				wedge:1,
+				ep_type:2,
+				ep_num:8;
+};
+
+/* request data structure */
+struct mv_req {
+	struct usb_request	req;
+	struct mv_dtd		*dtd, *head, *tail;
+	struct mv_ep		*ep;
+	struct list_head	queue;
+	unsigned		dtd_count;
+	unsigned		mapped:1;
+};
+
+#define EP_QUEUE_HEAD_MULT_POS			30
+#define EP_QUEUE_HEAD_ZLT_SEL			0x20000000
+#define EP_QUEUE_HEAD_MAX_PKT_LEN_POS		16
+#define EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info)	(((ep_info)>>16)&0x07ff)
+#define EP_QUEUE_HEAD_IOS			0x00008000
+#define EP_QUEUE_HEAD_NEXT_TERMINATE		0x00000001
+#define EP_QUEUE_HEAD_IOC			0x00008000
+#define EP_QUEUE_HEAD_MULTO			0x00000C00
+#define EP_QUEUE_HEAD_STATUS_HALT		0x00000040
+#define EP_QUEUE_HEAD_STATUS_ACTIVE		0x00000080
+#define EP_QUEUE_CURRENT_OFFSET_MASK		0x00000FFF
+#define EP_QUEUE_HEAD_NEXT_POINTER_MASK		0xFFFFFFE0
+#define EP_QUEUE_FRINDEX_MASK			0x000007FF
+#define EP_MAX_LENGTH_TRANSFER			0x4000
+
+struct mv_dqh {
+	/* Bits 16..26 Bit 15 is Interrupt On Setup */
+	u32	max_packet_length;
+	u32	curr_dtd_ptr;		/* Current dTD Pointer */
+	u32	next_dtd_ptr;		/* Next dTD Pointer */
+	/* Total bytes (16..30), IOC (15), INT (8), STS (0-7) */
+	u32	size_ioc_int_sts;
+	u32	buff_ptr0;		/* Buffer pointer Page 0 (12-31) */
+	u32	buff_ptr1;		/* Buffer pointer Page 1 (12-31) */
+	u32	buff_ptr2;		/* Buffer pointer Page 2 (12-31) */
+	u32	buff_ptr3;		/* Buffer pointer Page 3 (12-31) */
+	u32	buff_ptr4;		/* Buffer pointer Page 4 (12-31) */
+	u32	reserved1;
+	/* 8 bytes of setup data that follows the Setup PID */
+	u8	setup_buffer[8];
+	u32	reserved2[4];
+};
+
+
+#define DTD_NEXT_TERMINATE		(0x00000001)
+#define DTD_IOC				(0x00008000)
+#define DTD_STATUS_ACTIVE		(0x00000080)
+#define DTD_STATUS_HALTED		(0x00000040)
+#define DTD_STATUS_DATA_BUFF_ERR	(0x00000020)
+#define DTD_STATUS_TRANSACTION_ERR	(0x00000008)
+#define DTD_RESERVED_FIELDS		(0x00007F00)
+#define DTD_ERROR_MASK			(0x68)
+#define DTD_ADDR_MASK			(0xFFFFFFE0)
+#define DTD_PACKET_SIZE			0x7FFF0000
+#define DTD_LENGTH_BIT_POS		(16)
+
+struct mv_dtd {
+	u32	dtd_next;
+	u32	size_ioc_sts;
+	u32	buff_ptr0;		/* Buffer pointer Page 0 */
+	u32	buff_ptr1;		/* Buffer pointer Page 1 */
+	u32	buff_ptr2;		/* Buffer pointer Page 2 */
+	u32	buff_ptr3;		/* Buffer pointer Page 3 */
+	u32	buff_ptr4;		/* Buffer pointer Page 4 */
+	u32	scratch_ptr;
+	/* 32 bytes */
+	dma_addr_t td_dma;		/* dma address for this td */
+	struct mv_dtd *next_dtd_virt;
+};
+
+extern int mv_udc_phy_init(unsigned int base);
+
+#endif
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
new file mode 100644
index 0000000..d5468a7
--- /dev/null
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -0,0 +1,2149 @@
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+#include "mv_udc.h"
+
+#define DRIVER_DESC		"Marvell PXA USB Device Controller driver"
+#define DRIVER_VERSION		"8 Nov 2010"
+
+#define ep_dir(ep)	(((ep)->ep_num == 0) ? \
+				((ep)->udc->ep0_dir) : ((ep)->direction))
+
+/* timeout value -- usec */
+#define RESET_TIMEOUT		10000
+#define FLUSH_TIMEOUT		10000
+#define EPSTATUS_TIMEOUT	10000
+#define PRIME_TIMEOUT		10000
+#define READSAFE_TIMEOUT	1000
+#define DTD_TIMEOUT		1000
+
+#define LOOPS_USEC_SHIFT	4
+#define LOOPS_USEC		(1 << LOOPS_USEC_SHIFT)
+#define LOOPS(timeout)		((timeout) >> LOOPS_USEC_SHIFT)
+
+static const char driver_name[] = "mv_udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+/* controller device global variable */
+static struct mv_udc	*the_controller;
+int mv_usb_otgsc;
+
+static void nuke(struct mv_ep *ep, int status);
+
+/* for endpoint 0 operations */
+static const struct usb_endpoint_descriptor mv_ep0_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	0,
+	.bmAttributes =		USB_ENDPOINT_XFER_CONTROL,
+	.wMaxPacketSize =	EP0_MAX_PKT_SIZE,
+};
+
+static void ep0_reset(struct mv_udc *udc)
+{
+	struct mv_ep *ep;
+	u32 epctrlx;
+	int i = 0;
+
+	/* ep0 in and out */
+	for (i = 0; i < 2; i++) {
+		ep = &udc->eps[i];
+		ep->udc = udc;
+
+		/* ep0 dQH */
+		ep->dqh = &udc->ep_dqh[i];
+
+		/* configure ep0 endpoint capabilities in dQH */
+		ep->dqh->max_packet_length =
+			(EP0_MAX_PKT_SIZE << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+			| EP_QUEUE_HEAD_IOS;
+
+		epctrlx = readl(&udc->op_regs->epctrlx[0]);
+		if (i) {	/* TX */
+			epctrlx |= EPCTRL_TX_ENABLE | EPCTRL_TX_DATA_TOGGLE_RST
+				| (USB_ENDPOINT_XFER_CONTROL
+					<< EPCTRL_TX_EP_TYPE_SHIFT);
+
+		} else {	/* RX */
+			epctrlx |= EPCTRL_RX_ENABLE | EPCTRL_RX_DATA_TOGGLE_RST
+				| (USB_ENDPOINT_XFER_CONTROL
+					<< EPCTRL_RX_EP_TYPE_SHIFT);
+		}
+
+		writel(epctrlx, &udc->op_regs->epctrlx[0]);
+	}
+}
+
+/* protocol ep0 stall, will automatically be cleared on new transaction */
+static void ep0_stall(struct mv_udc *udc)
+{
+	u32	epctrlx;
+
+	/* set TX and RX to stall */
+	epctrlx = readl(&udc->op_regs->epctrlx[0]);
+	epctrlx |= EPCTRL_RX_EP_STALL | EPCTRL_TX_EP_STALL;
+	writel(epctrlx, &udc->op_regs->epctrlx[0]);
+
+	/* update ep0 state */
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->ep0_dir = EP_DIR_OUT;
+}
+
+static int process_ep_req(struct mv_udc *udc, int index,
+	struct mv_req *curr_req)
+{
+	struct mv_dtd	*curr_dtd;
+	struct mv_dqh	*curr_dqh;
+	int td_complete, actual, remaining_length;
+	int i, direction;
+	int retval = 0;
+	u32 errors;
+
+	curr_dqh = &udc->ep_dqh[index];
+	direction = index % 2;
+
+	curr_dtd = curr_req->head;
+	td_complete = 0;
+	actual = curr_req->req.length;
+
+	for (i = 0; i < curr_req->dtd_count; i++) {
+		if (curr_dtd->size_ioc_sts & DTD_STATUS_ACTIVE) {
+			dev_dbg(&udc->dev->dev, "%s, dTD not completed\n",
+				udc->eps[index].name);
+			return 1;
+		}
+
+		errors = curr_dtd->size_ioc_sts & DTD_ERROR_MASK;
+		if (!errors) {
+			remaining_length +=
+				(curr_dtd->size_ioc_sts	& DTD_PACKET_SIZE)
+					>> DTD_LENGTH_BIT_POS;
+			actual -= remaining_length;
+		} else {
+			dev_info(&udc->dev->dev,
+				"complete_tr error: ep=%d %s: error = 0x%x\n",
+				index >> 1, direction ? "SEND" : "RECV",
+				errors);
+			if (errors & DTD_STATUS_HALTED) {
+				/* Clear the errors and Halt condition */
+				curr_dqh->size_ioc_int_sts &= ~errors;
+				retval = -EPIPE;
+			} else if (errors & DTD_STATUS_DATA_BUFF_ERR) {
+				retval = -EPROTO;
+			} else if (errors & DTD_STATUS_TRANSACTION_ERR) {
+				retval = -EILSEQ;
+			}
+		}
+		if (i != curr_req->dtd_count - 1)
+			curr_dtd = (struct mv_dtd *)curr_dtd->next_dtd_virt;
+	}
+	if (retval)
+		return retval;
+
+	curr_req->req.actual = actual;
+
+	return 0;
+}
+
+/*
+ * done() - retire a request; caller blocked irqs
+ * @status : request status to be set, only works when
+ * request is still in progress.
+ */
+static void done(struct mv_ep *ep, struct mv_req *req, int status)
+{
+	struct mv_udc *udc = NULL;
+	unsigned char stopped = ep->stopped;
+	struct mv_dtd *curr_td, *next_td;
+	int j;
+
+	udc = (struct mv_udc *)ep->udc;
+	/* Removed the req from fsl_ep->queue */
+	list_del_init(&req->queue);
+
+	/* req.status should be set as -EINPROGRESS in ep_queue() */
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	/* Free dtd for the request */
+	next_td = req->head;
+	for (j = 0; j < req->dtd_count; j++) {
+		curr_td = next_td;
+		if (j != req->dtd_count - 1)
+			next_td = curr_td->next_dtd_virt;
+		dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
+	}
+
+	if (req->mapped) {
+		dma_unmap_single(ep->udc->gadget.dev.parent,
+			req->req.dma, req->req.length,
+			((ep_dir(ep) == EP_DIR_IN) ?
+				DMA_TO_DEVICE : DMA_FROM_DEVICE));
+		req->req.dma = DMA_ADDR_INVALID;
+		req->mapped = 0;
+	} else
+		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
+			req->req.dma, req->req.length,
+			((ep_dir(ep) == EP_DIR_IN) ?
+				DMA_TO_DEVICE : DMA_FROM_DEVICE));
+
+	if (status && (status != -ESHUTDOWN))
+		dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
+			ep->ep.name, &req->req, status,
+			req->req.actual, req->req.length);
+
+	ep->stopped = 1;
+
+	spin_unlock(&ep->udc->lock);
+	/*
+	 * complete() is from gadget layer,
+	 * eg fsg->bulk_in_complete()
+	 */
+	if (req->req.complete)
+		req->req.complete(&ep->ep, &req->req);
+
+	spin_lock(&ep->udc->lock);
+	ep->stopped = stopped;
+}
+
+static int queue_dtd(struct mv_ep *ep, struct mv_req *req)
+{
+	u32 tmp, epstatus, bit_pos, direction;
+	struct mv_udc *udc;
+	struct mv_dqh *dqh;
+	unsigned int loops;
+	int readsafe, retval = 0;
+
+	udc = ep->udc;
+	direction = ep_dir(ep);
+	dqh = &(udc->ep_dqh[ep->ep_num * 2 + direction]);
+	bit_pos = 1 << (((direction == EP_DIR_OUT) ? 0 : 16) + ep->ep_num);
+
+	/* check if the pipe is empty */
+	if (!(list_empty(&ep->queue))) {
+		struct mv_req *lastreq;
+		lastreq = list_entry(ep->queue.prev, struct mv_req, queue);
+		lastreq->tail->dtd_next =
+			req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
+		if (readl(&udc->op_regs->epprime) & bit_pos) {
+			loops = LOOPS(PRIME_TIMEOUT);
+			while (readl(&udc->op_regs->epprime) & bit_pos) {
+				if (loops == 0) {
+					retval = -ETIME;
+					goto done;
+				}
+				udelay(LOOPS_USEC);
+				loops--;
+			}
+			if (readl(&udc->op_regs->epstatus) & bit_pos)
+				goto done;
+		}
+		readsafe = 0;
+		loops = LOOPS(READSAFE_TIMEOUT);
+		while (readsafe == 0) {
+			if (loops == 0) {
+				retval = -ETIME;
+				goto done;
+			}
+			/* start with setting the semaphores */
+			tmp = readl(&udc->op_regs->usbcmd);
+			tmp |= USBCMD_ATDTW_TRIPWIRE_SET;
+			writel(tmp, &udc->op_regs->usbcmd);
+
+			/* read the endpoint status */
+			epstatus = readl(&udc->op_regs->epstatus) & bit_pos;
+
+			/*
+			 * Reread the ATDTW semaphore bit to check if it is
+			 * cleared. When hardware see a hazard, it will clear
+			 * the bit or else we remain set to 1 and we can
+			 * proceed with priming of endpoint if not already
+			 * primed.
+			 */
+			if (readl(&udc->op_regs->usbcmd)
+				& USBCMD_ATDTW_TRIPWIRE_SET) {
+				readsafe = 1;
+			}
+			loops--;
+			udelay(LOOPS_USEC);
+		}
+
+		/* Clear the semaphore */
+		tmp = readl(&udc->op_regs->usbcmd);
+		tmp &= USBCMD_ATDTW_TRIPWIRE_CLEAR;
+		writel(tmp, &udc->op_regs->usbcmd);
+
+		/* If endpoint is not active, we activate it now. */
+		if (!epstatus) {
+			if (direction == EP_DIR_IN) {
+				struct mv_dtd *curr_dtd = dma_to_virt(
+					&udc->dev->dev, dqh->curr_dtd_ptr);
+
+				loops = LOOPS(DTD_TIMEOUT);
+				while (curr_dtd->size_ioc_sts
+					& DTD_STATUS_ACTIVE) {
+					if (loops == 0) {
+						retval = -ETIME;
+						goto done;
+					}
+					loops--;
+					udelay(LOOPS_USEC);
+				}
+			}
+			/* No other transfers on the queue */
+
+			/* Write dQH next pointer and terminate bit to 0 */
+			dqh->next_dtd_ptr = req->head->td_dma
+				& EP_QUEUE_HEAD_NEXT_POINTER_MASK;
+			dqh->size_ioc_int_sts = 0;
+
+			/*
+			 * Ensure that updates to the QH will
+			 * occure before priming.
+			 */
+			wmb();
+
+			/* Prime the Endpoint */
+			writel(bit_pos, &udc->op_regs->epprime);
+		}
+	} else {
+		/* Write dQH next pointer and terminate bit to 0 */
+		dqh->next_dtd_ptr = req->head->td_dma
+			& EP_QUEUE_HEAD_NEXT_POINTER_MASK;;
+		dqh->size_ioc_int_sts = 0;
+
+		/* Ensure that updates to the QH will occure before priming. */
+		wmb();
+
+		/* Prime the Endpoint */
+		writel(bit_pos, &udc->op_regs->epprime);
+
+		if (direction == EP_DIR_IN) {
+			/* FIXME add status check after prime the IN ep */
+			int prime_again;
+			u32 curr_dtd_ptr = dqh->curr_dtd_ptr;
+
+			loops = LOOPS(DTD_TIMEOUT);
+			prime_again = 0;
+			while ((curr_dtd_ptr != req->head->td_dma)) {
+				curr_dtd_ptr = dqh->curr_dtd_ptr;
+				if (loops == 0) {
+					dev_err(&udc->dev->dev,
+						"failed to prime %s\n",
+						ep->name);
+					retval = -ETIME;
+					goto done;
+				}
+				loops--;
+				udelay(LOOPS_USEC);
+
+				if (loops == (LOOPS(DTD_TIMEOUT) >> 2)) {
+					if (prime_again)
+						goto done;
+					dev_info(&udc->dev->dev,
+						"prime again\n");
+					writel(bit_pos,
+						&udc->op_regs->epprime);
+					prime_again = 1;
+				}
+			}
+		}
+	}
+done:
+	return retval;;
+}
+
+static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length,
+		dma_addr_t *dma, int *is_last)
+{
+	u32 temp;
+	struct mv_dtd *dtd;
+	struct mv_udc *udc;
+
+	/* how big will this transfer be? */
+	*length = min(req->req.length - req->req.actual,
+			(unsigned)EP_MAX_LENGTH_TRANSFER);
+
+	udc = req->ep->udc;
+
+	/*
+	 * Be careful that no _GFP_HIGHMEM is set,
+	 * or we can not use dma_to_virt
+	 */
+	dtd = dma_pool_alloc(udc->dtd_pool, GFP_KERNEL, dma);
+	if (dtd == NULL)
+		return dtd;
+
+	dtd->td_dma = *dma;
+	/* initialize buffer page pointers */
+	temp = (u32)(req->req.dma + req->req.actual);
+	dtd->buff_ptr0 = cpu_to_le32(temp);
+	temp &= ~0xFFF;
+	dtd->buff_ptr1 = cpu_to_le32(temp + 0x1000);
+	dtd->buff_ptr2 = cpu_to_le32(temp + 0x2000);
+	dtd->buff_ptr3 = cpu_to_le32(temp + 0x3000);
+	dtd->buff_ptr4 = cpu_to_le32(temp + 0x4000);
+
+	req->req.actual += *length;
+
+	/* zlp is needed if req->req.zero is set */
+	if (req->req.zero) {
+		if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
+			*is_last = 1;
+		else
+			*is_last = 0;
+	} else if (req->req.length == req->req.actual)
+		*is_last = 1;
+	else
+		*is_last = 0;
+
+	/* Fill in the transfer size; set active bit */
+	temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
+
+	/* Enable interrupt for the last dtd of a request */
+	if (*is_last && !req->req.no_interrupt)
+		temp |= DTD_IOC;
+
+	dtd->size_ioc_sts = temp;
+
+	mb();
+
+	return dtd;
+}
+
+/* generate dTD linked list for a request */
+static int req_to_dtd(struct mv_req *req)
+{
+	unsigned count;
+	int is_last, is_first = 1;
+	struct mv_dtd *dtd, *last_dtd = NULL;
+	struct mv_udc *udc;
+	dma_addr_t dma;
+
+	udc = req->ep->udc;
+
+	do {
+		dtd = build_dtd(req, &count, &dma, &is_last);
+		if (dtd == NULL)
+			return -ENOMEM;
+
+		if (is_first) {
+			is_first = 0;
+			req->head = dtd;
+		} else {
+			last_dtd->dtd_next = dma;
+			last_dtd->next_dtd_virt = dtd;
+		}
+		last_dtd = dtd;
+		req->dtd_count++;
+	} while (!is_last);
+
+	/* set terminate bit to 1 for the last dTD */
+	dtd->dtd_next = DTD_NEXT_TERMINATE;
+
+	req->tail = dtd;
+
+	return 0;
+}
+
+static int mv_ep_enable(struct usb_ep *_ep,
+		const struct usb_endpoint_descriptor *desc)
+{
+	struct mv_udc *udc;
+	struct mv_ep *ep;
+	struct mv_dqh *dqh;
+	u16 max = 0;
+	u32 bit_pos, epctrlx, direction;
+	unsigned char zlt = 0, ios = 0, mult = 0;
+
+	ep = container_of(_ep, struct mv_ep, ep);
+	udc = ep->udc;
+
+	if (!_ep || !desc || ep->desc
+			|| desc->bDescriptorType != USB_DT_ENDPOINT)
+		return -EINVAL;
+
+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	direction = ep_dir(ep);
+	max = le16_to_cpu(desc->wMaxPacketSize);
+
+	/*
+	 * disable HW zero length termination select
+	 * driver handles zero length packet through req->req.zero
+	 */
+	zlt = 1;
+
+	/* Get the endpoint queue head address */
+	dqh = (struct mv_dqh *)ep->dqh;
+
+	bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
+
+	/* Check if the Endpoint is Primed */
+	if ((readl(&udc->op_regs->epprime) & bit_pos)
+		|| (readl(&udc->op_regs->epstatus) & bit_pos)) {
+		dev_info(&udc->dev->dev,
+			"ep=%d %s: Init ERROR: ENDPTPRIME=0x%x,"
+			" ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
+			(unsigned)ep->ep_num, direction ? "SEND" : "RECV",
+			(unsigned)readl(&udc->op_regs->epprime),
+			(unsigned)readl(&udc->op_regs->epstatus),
+			(unsigned)bit_pos);
+		goto en_done;
+	}
+	/* Set the max packet length, interrupt on Setup and Mult fields */
+	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_BULK:
+		zlt = 1;
+		mult = 0;
+		break;
+	case USB_ENDPOINT_XFER_CONTROL:
+		ios = 1;
+	case USB_ENDPOINT_XFER_INT:
+		mult = 0;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		/* Calculate transactions needed for high bandwidth iso */
+		mult = (unsigned char)(1 + ((max >> 11) & 0x03));
+		max = max & 0x8ff;	/* bit 0~10 */
+		/* 3 transactions at most */
+		if (mult > 3)
+			goto en_done;
+		break;
+	default:
+		goto en_done;
+	}
+	dqh->max_packet_length = (max << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
+		| (mult << EP_QUEUE_HEAD_MULT_POS)
+		| (zlt ? EP_QUEUE_HEAD_ZLT_SEL : 0)
+		| (ios ? EP_QUEUE_HEAD_IOS : 0);
+	dqh->next_dtd_ptr = 1;
+	dqh->size_ioc_int_sts = 0;
+
+	ep->ep.maxpacket = max;
+	ep->desc = desc;
+	ep->stopped = 0;
+
+	/* Enable the endpoint for Rx or Tx and set the endpoint type */
+	epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+	if (direction == EP_DIR_IN) {
+		epctrlx &= ~EPCTRL_TX_ALL_MASK;
+		epctrlx |= EPCTRL_TX_ENABLE | EPCTRL_TX_DATA_TOGGLE_RST
+			| ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+				<< EPCTRL_TX_EP_TYPE_SHIFT);
+	} else {
+		epctrlx &= ~EPCTRL_RX_ALL_MASK;
+		epctrlx |= EPCTRL_RX_ENABLE | EPCTRL_RX_DATA_TOGGLE_RST
+			| ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+				<< EPCTRL_RX_EP_TYPE_SHIFT);
+	}
+	writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+
+	/*
+	 * Implement Guideline (GL# USB-7) The unused endpoint type must
+	 * be programmed to bulk.
+	 */
+	epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+	if ((epctrlx & EPCTRL_RX_ENABLE) == 0) {
+		epctrlx |= ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+				<< EPCTRL_RX_EP_TYPE_SHIFT);
+		writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+	}
+
+	epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+	if ((epctrlx & EPCTRL_TX_ENABLE) == 0) {
+		epctrlx |= ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+				<< EPCTRL_TX_EP_TYPE_SHIFT);
+		writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+	}
+
+	return 0;
+en_done:
+	return -EINVAL;
+}
+
+static int  mv_ep_disable(struct usb_ep *_ep)
+{
+	struct mv_udc *udc;
+	struct mv_ep *ep;
+	struct mv_dqh *dqh;
+	u32 bit_pos, epctrlx, direction;
+
+	ep = container_of(_ep, struct mv_ep, ep);
+	if ((_ep == NULL) || !ep->desc)
+		return -EINVAL;
+
+	udc = ep->udc;
+
+	/* Get the endpoint queue head address */
+	dqh = ep->dqh;
+
+	direction = ep_dir(ep);
+	bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
+
+	/* Reset the max packet length and the interrupt on Setup */
+	dqh->max_packet_length = 0;
+
+	/* Disable the endpoint for Rx or Tx and reset the endpoint type */
+	epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+	epctrlx &= ~((direction == EP_DIR_IN)
+			? (EPCTRL_TX_ENABLE | EPCTRL_TX_TYPE)
+			: (EPCTRL_RX_ENABLE | EPCTRL_RX_TYPE));
+	writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+
+	/* nuke all pending requests (does flush) */
+	nuke(ep, -ESHUTDOWN);
+
+	ep->desc = NULL;
+	ep->stopped = 1;
+	return 0;
+}
+
+static struct usb_request *
+mv_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+	struct mv_req *req = NULL;
+
+	req = kzalloc(sizeof *req, gfp_flags);
+	if (!req)
+		return NULL;
+
+	req->req.dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+static void mv_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct mv_req *req = NULL;
+
+	req = container_of(_req, struct mv_req, req);
+
+	if (_req)
+		kfree(req);
+}
+
+static void mv_ep_fifo_flush(struct usb_ep *_ep)
+{
+	struct mv_udc *udc;
+	u32 bit_pos, direction;
+	struct mv_ep *ep = container_of(_ep, struct mv_ep, ep);
+	unsigned int loops;
+
+	udc = ep->udc;
+	direction = ep_dir(ep);
+	bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
+	/*
+	 * Flushing will halt the pipe
+	 * Write 1 to the Flush register
+	 */
+	writel(bit_pos, &udc->op_regs->epflush);
+
+	/* Wait until flushing completed */
+	loops = LOOPS(FLUSH_TIMEOUT);
+	while (readl(&udc->op_regs->epflush) & bit_pos) {
+		/*
+		 * ENDPTFLUSH bit should be cleared to indicate this
+		 * operation is complete
+		 */
+		if (loops == 0) {
+			dev_err(&udc->dev->dev,
+				"TIMEOUT for ENDPTFLUSH=0x%x, bit_pos=0x%x\n",
+				(unsigned)readl(&udc->op_regs->epflush),
+				(unsigned)bit_pos);
+			return;
+		}
+		loops--;
+		udelay(LOOPS_USEC);
+	}
+	loops = LOOPS(EPSTATUS_TIMEOUT);
+	while (readl(&udc->op_regs->epstatus) & bit_pos) {
+		unsigned int inter_loops;
+
+		if (loops == 0) {
+			dev_err(&udc->dev->dev,
+				"TIMEOUT for ENDPTSTATUS=0x%x, bit_pos=0x%x\n",
+				(unsigned)readl(&udc->op_regs->epstatus),
+				(unsigned)bit_pos);
+			return;
+		}
+		/* Write 1 to the Flush register */
+		writel(bit_pos, &udc->op_regs->epflush);
+
+		/* Wait until flushing completed */
+		inter_loops = LOOPS(FLUSH_TIMEOUT);
+		while (readl(&udc->op_regs->epflush) & bit_pos) {
+			/*
+			 * ENDPTFLUSH bit should be cleared to indicate this
+			 * operation is complete
+			 */
+			if (inter_loops == 0) {
+				dev_err(&udc->dev->dev,
+					"TIMEOUT for ENDPTFLUSH=0x%x,"
+					"bit_pos=0x%x\n",
+					(unsigned)readl(&udc->op_regs->epflush),
+					(unsigned)bit_pos);
+				return;
+			}
+			inter_loops--;
+			udelay(LOOPS_USEC);
+		}
+		loops--;
+	}
+}
+
+/* queues (submits) an I/O request to an endpoint */
+static int
+mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+	struct mv_ep *ep = container_of(_ep, struct mv_ep, ep);
+	struct mv_req *req = container_of(_req, struct mv_req, req);
+	struct mv_udc *udc = ep->udc;
+	unsigned long flags;
+
+	/* catch various bogus parameters */
+	if (!_req || !req->req.complete || !req->req.buf
+			|| !list_empty(&req->queue)) {
+		dev_err(&udc->dev->dev, "%s, bad params", __func__);
+		return -EINVAL;
+	}
+	if (unlikely(!_ep || !ep->desc)) {
+		dev_err(&udc->dev->dev, "%s, bad ep", __func__);
+		return -EINVAL;
+	}
+	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		if (req->req.length > ep->ep.maxpacket)
+			return -EMSGSIZE;
+	}
+
+	udc = ep->udc;
+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	req->ep = ep;
+
+	/* map virtual address to hardware */
+	if (req->req.dma == DMA_ADDR_INVALID) {
+		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
+					req->req.buf,
+					req->req.length, ep_dir(ep)
+						? DMA_TO_DEVICE
+						: DMA_FROM_DEVICE);
+		req->mapped = 1;
+	} else {
+		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
+					req->req.dma, req->req.length,
+					ep_dir(ep)
+						? DMA_TO_DEVICE
+						: DMA_FROM_DEVICE);
+		req->mapped = 0;
+	}
+
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+	req->dtd_count = 0;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* build dtds and push them to device queue */
+	if (!req_to_dtd(req)) {
+		int retval;
+		retval = queue_dtd(ep, req);
+		if (retval) {
+			spin_unlock_irqrestore(&udc->lock, flags);
+			return retval;
+		}
+	} else {
+		spin_unlock_irqrestore(&udc->lock, flags);
+		return -ENOMEM;
+	}
+
+	/* Update ep0 state */
+	if (ep->ep_num == 0)
+		udc->ep0_state = DATA_STATE_XMIT;
+
+	/* irq handler advances the queue */
+	if (req != NULL)
+		list_add_tail(&req->queue, &ep->queue);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+/* dequeues (cancels, unlinks) an I/O request from an endpoint */
+static int mv_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct mv_ep *ep = container_of(_ep, struct mv_ep, ep);
+	struct mv_req *req;
+	struct mv_udc *udc = ep->udc;
+	unsigned long flags;
+	int stopped, ret = 0;
+	u32 epctrlx;
+
+	if (!_ep || !_req)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->udc->lock, flags);
+	stopped = ep->stopped;
+
+	/* Stop the ep before we deal with the queue */
+	ep->stopped = 1;
+	epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+	if (ep_dir(ep) == EP_DIR_IN)
+		epctrlx &= ~EPCTRL_TX_ENABLE;
+	else
+		epctrlx &= ~EPCTRL_RX_ENABLE;
+	writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* The request is in progress, or completed but not dequeued */
+	if (ep->queue.next == &req->queue) {
+		_req->status = -ECONNRESET;
+		mv_ep_fifo_flush(_ep);	/* flush current transfer */
+
+		/* The request isn't the last request in this ep queue */
+		if (req->queue.next != &ep->queue) {
+			struct mv_dqh *qh;
+			struct mv_req *next_req;
+
+			qh = ep->dqh;
+			next_req = list_entry(req->queue.next, struct mv_req,
+					queue);
+
+			/* Point the QH to the first TD of next request */
+			writel((u32) next_req->head, &qh->curr_dtd_ptr);
+		} else {
+			struct mv_dqh *qh;
+
+			qh = ep->dqh;
+			qh->next_dtd_ptr = 1;
+			qh->size_ioc_int_sts = 0;
+		}
+
+		/* The request hasn't been processed, patch up the TD chain */
+	} else {
+		struct mv_req *prev_req;
+
+		prev_req = list_entry(req->queue.prev, struct mv_req, queue);
+		writel(readl(&req->tail->dtd_next),
+				&prev_req->tail->dtd_next);
+
+	}
+
+	done(ep, req, -ECONNRESET);
+
+	/* Enable EP */
+out:
+	epctrlx = readl(&udc->op_regs->epctrlx[ep->ep_num]);
+	if (ep_dir(ep) == EP_DIR_IN)
+		epctrlx |= EPCTRL_TX_ENABLE;
+	else
+		epctrlx |= EPCTRL_RX_ENABLE;
+	writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
+	ep->stopped = stopped;
+
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+	return ret;
+}
+
+static void ep_set_stall(struct mv_udc *udc, u8 ep_num, u8 direction, int stall)
+{
+	u32 epctrlx;
+
+	epctrlx = readl(&udc->op_regs->epctrlx[ep_num]);
+
+	if (stall) {
+		if (direction == EP_DIR_IN)
+			epctrlx |= EPCTRL_TX_EP_STALL;
+		else
+			epctrlx |= EPCTRL_RX_EP_STALL;
+	} else {
+		if (direction == EP_DIR_IN) {
+			epctrlx &= ~EPCTRL_TX_EP_STALL;
+			epctrlx |= EPCTRL_TX_DATA_TOGGLE_RST;
+		} else {
+			epctrlx &= ~EPCTRL_RX_EP_STALL;
+			epctrlx |= EPCTRL_RX_DATA_TOGGLE_RST;
+		}
+	}
+	writel(epctrlx, &udc->op_regs->epctrlx[ep_num]);
+}
+
+static int ep_is_stall(struct mv_udc *udc, u8 ep_num, u8 direction)
+{
+	u32 epctrlx;
+
+	epctrlx = readl(&udc->op_regs->epctrlx[ep_num]);
+
+	if (direction == EP_DIR_OUT)
+		return (epctrlx & EPCTRL_RX_EP_STALL) ? 1 : 0;
+	else
+		return (epctrlx & EPCTRL_TX_EP_STALL) ? 1 : 0;
+}
+
+static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge)
+{
+	struct mv_ep *ep;
+	unsigned long flags = 0;
+	int status = 0;
+	struct mv_udc *udc;
+
+	ep = container_of(_ep, struct mv_ep, ep);
+	udc = ep->udc;
+	if (!_ep || !ep->desc) {
+		status = -EINVAL;
+		goto out;
+	}
+
+	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		status = -EOPNOTSUPP;
+		goto out;
+	}
+
+	/*
+	 * Attempt to halt IN ep will fail if any transfer requests
+	 * are still queue
+	 */
+	if (halt && (ep_dir(ep) == EP_DIR_IN) && !list_empty(&ep->queue)) {
+		status = -EAGAIN;
+		goto out;
+	}
+
+	spin_lock_irqsave(&ep->udc->lock, flags);
+	ep_set_stall(udc, ep->ep_num, ep_dir(ep), halt);
+	if (halt && wedge)
+		ep->wedge = 1;
+	else if (!halt)
+		ep->wedge = 0;
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+	if (ep->ep_num == 0) {
+		udc->ep0_state = WAIT_FOR_SETUP;
+		udc->ep0_dir = EP_DIR_OUT;
+	}
+out:
+	return status;
+}
+
+static int mv_ep_set_halt(struct usb_ep *_ep, int halt)
+{
+	return mv_ep_set_halt_wedge(_ep, halt, 0);
+}
+
+static int mv_ep_set_wedge(struct usb_ep *_ep)
+{
+	return mv_ep_set_halt_wedge(_ep, 1, 1);
+}
+
+static struct usb_ep_ops mv_ep_ops = {
+	.enable		= mv_ep_enable,
+	.disable	= mv_ep_disable,
+
+	.alloc_request	= mv_alloc_request,
+	.free_request	= mv_free_request,
+
+	.queue		= mv_ep_queue,
+	.dequeue	= mv_ep_dequeue,
+
+	.set_wedge	= mv_ep_set_wedge,
+	.set_halt	= mv_ep_set_halt,
+	.fifo_flush	= mv_ep_fifo_flush,	/* flush fifo */
+};
+
+static void udc_stop(struct mv_udc *udc)
+{
+	u32 tmp;
+
+	/* Disable interrupts */
+	tmp = readl(&udc->op_regs->usbintr);
+	tmp &= ~(USBINTR_INT_EN | USBINTR_ERR_INT_EN |
+		USBINTR_PORT_CHANGE_DETECT_EN | USBINTR_RESET_EN);
+	writel(tmp, &udc->op_regs->usbintr);
+
+	/* Reset the Run the bit in the command register to stop VUSB */
+	tmp = readl(&udc->op_regs->usbcmd);
+	tmp &= ~USBCMD_RUN_STOP;
+	writel(tmp, &udc->op_regs->usbcmd);
+}
+
+static void udc_start(struct mv_udc *udc)
+{
+	u32 usbintr;
+
+	usbintr = USBINTR_INT_EN | USBINTR_ERR_INT_EN
+		| USBINTR_PORT_CHANGE_DETECT_EN
+		| USBINTR_RESET_EN | USBINTR_DEVICE_SUSPEND;
+	/* Enable interrupts */
+	writel(usbintr, &udc->op_regs->usbintr);
+
+	/* Set the Run bit in the command register */
+	writel(USBCMD_RUN_STOP, &udc->op_regs->usbcmd);
+}
+
+static int udc_reset(struct mv_udc *udc)
+{
+	unsigned int loops;
+	u32 tmp, portsc;
+
+	/* Stop the controller */
+	tmp = readl(&udc->op_regs->usbcmd);
+	tmp &= ~USBCMD_RUN_STOP;
+	writel(tmp, &udc->op_regs->usbcmd);
+
+	/* Reset the controller to get default values */
+	writel(USBCMD_CTRL_RESET, &udc->op_regs->usbcmd);
+
+	/* wait for reset to complete */
+	loops = LOOPS(RESET_TIMEOUT);
+	while (readl(&udc->op_regs->usbcmd) & USBCMD_CTRL_RESET) {
+		if (loops == 0) {
+			dev_err(&udc->dev->dev,
+				"Wait for RESET completed TIMEOUT\n");
+			return -ETIMEDOUT;
+		}
+		loops--;
+		udelay(LOOPS_USEC);
+	}
+
+	/* set controller to device mode */
+	tmp = readl(&udc->op_regs->usbmode);
+	tmp |= USBMODE_CTRL_MODE_DEVICE;
+
+	/* turn setup lockout off, require setup tripwire in usbcmd */
+	tmp |= USBMODE_SETUP_LOCK_OFF | USBMODE_STREAM_DISABLE;
+
+	writel(tmp, &udc->op_regs->usbmode);
+
+	writel(0x0, &udc->op_regs->epsetupstat);
+
+	/* Configure the Endpoint List Address */
+	writel(udc->ep_dqh_dma & USB_EP_LIST_ADDRESS_MASK,
+		&udc->op_regs->eplistaddr);
+
+	portsc = readl(&udc->op_regs->portsc[0]);
+	if (readl(&udc->cap_regs->hcsparams) & HCSPARAMS_PPC)
+		portsc &= (~PORTSCX_W1C_BITS | ~PORTSCX_PORT_POWER);
+
+	if (udc->force_fs)
+		portsc |= PORTSCX_FORCE_FULL_SPEED_CONNECT;
+	else
+		portsc &= (~PORTSCX_FORCE_FULL_SPEED_CONNECT);
+
+	writel(portsc, &udc->op_regs->portsc[0]);
+
+	tmp = readl(&udc->op_regs->epctrlx[0]);
+	tmp &= ~(EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL);
+	writel(tmp, &udc->op_regs->epctrlx[0]);
+
+	return 0;
+}
+
+static int mv_udc_get_frame(struct usb_gadget *gadget)
+{
+	struct mv_udc *udc;
+	u16	retval;
+
+	if (!gadget)
+		return -ENODEV;
+
+	udc = container_of(gadget, struct mv_udc, gadget);
+
+	retval = readl(udc->op_regs->frindex) & USB_FRINDEX_MASKS;
+
+	return retval;
+}
+
+/* Tries to wake up the host connected to this gadget */
+static int mv_udc_wakeup(struct usb_gadget *gadget)
+{
+	struct mv_udc *udc = container_of(gadget, struct mv_udc, gadget);
+	u32 portsc;
+
+	/* Remote wakeup feature not enabled by host */
+	if (!udc->remote_wakeup)
+		return -ENOTSUPP;
+
+	portsc = readl(&udc->op_regs->portsc);
+	/* not suspended? */
+	if (!(portsc & PORTSCX_PORT_SUSPEND))
+		return 0;
+	/* trigger force resume */
+	portsc |= PORTSCX_PORT_FORCE_RESUME;
+	writel(portsc, &udc->op_regs->portsc[0]);
+	return 0;
+}
+
+static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct mv_udc *udc;
+	unsigned long flags;
+
+	udc = container_of(gadget, struct mv_udc, gadget);
+	spin_lock_irqsave(&udc->lock, flags);
+
+	udc->softconnect = (is_on != 0);
+	if (udc->driver && udc->softconnect)
+		udc_start(udc);
+	else
+		udc_stop(udc);
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return 0;
+}
+
+/* device controller usb_gadget_ops structure */
+static const struct usb_gadget_ops mv_ops = {
+
+	/* returns the current frame number */
+	.get_frame	= mv_udc_get_frame,
+
+	/* tries to wake up the host connected to this gadget */
+	.wakeup		= mv_udc_wakeup,
+
+	/* D+ pullup, software-controlled connect/disconnect to USB host */
+	.pullup		= mv_udc_pullup,
+};
+
+static void mv_udc_testmode(struct mv_udc *udc, u16 index, bool enter)
+{
+	dev_info(&udc->dev->dev, "Test Mode is not support yet\n");
+}
+
+static int eps_init(struct mv_udc *udc)
+{
+	struct mv_ep	*ep;
+	char name[14];
+	int i;
+
+	/* initialize ep0 */
+	ep = &udc->eps[0];
+	ep->udc = udc;
+	strncpy(ep->name, "ep0", sizeof(ep->name));
+	ep->ep.name = ep->name;
+	ep->ep.ops = &mv_ep_ops;
+	ep->wedge = 0;
+	ep->stopped = 0;
+	ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
+	ep->ep_num = 0;
+	ep->desc = &mv_ep0_desc;
+	INIT_LIST_HEAD(&ep->queue);
+
+	ep->ep_type = USB_ENDPOINT_XFER_CONTROL;
+
+	/* initialize other endpoints */
+	for (i = 2; i < udc->max_eps * 2; i++) {
+		ep = &udc->eps[i];
+		if (i % 2) {
+			snprintf(name, sizeof(name), "ep%din", i / 2);
+			ep->direction = EP_DIR_IN;
+		} else {
+			snprintf(name, sizeof(name), "ep%dout", i / 2);
+			ep->direction = EP_DIR_OUT;
+		}
+		ep->udc = udc;
+		strncpy(ep->name, name, sizeof(ep->name));
+		ep->ep.name = ep->name;
+
+		ep->ep.ops = &mv_ep_ops;
+		ep->stopped = 0;
+		ep->ep.maxpacket = (unsigned short) ~0;
+		ep->ep_num = i / 2;
+
+		INIT_LIST_HEAD(&ep->queue);
+		list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+
+		ep->dqh = &udc->ep_dqh[i];
+	}
+
+	return 0;
+}
+
+/* delete all endpoint requests, called with spinlock held */
+static void nuke(struct mv_ep *ep, int status)
+{
+	/* called with spinlock held */
+	ep->stopped = 1;
+
+	/* endpoint fifo flush */
+	mv_ep_fifo_flush(&ep->ep);
+
+	while (!list_empty(&ep->queue)) {
+		struct mv_req *req = NULL;
+		req = list_entry(ep->queue.next, struct mv_req, queue);
+		done(ep, req, status);
+	}
+}
+
+/* stop all USB activities */
+static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
+{
+	struct mv_ep	*ep;
+
+	nuke(&udc->eps[0], -ESHUTDOWN);
+
+	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+		nuke(ep, -ESHUTDOWN);
+	}
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver) {
+		spin_unlock(&udc->lock);
+		driver->disconnect(&udc->gadget);
+		spin_lock(&udc->lock);
+	}
+}
+
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
+{
+	struct mv_udc *udc = the_controller;
+	int retval = 0;
+	unsigned long flags;
+
+	if (!udc)
+		return -ENODEV;
+
+	if (udc->driver)
+		return -EBUSY;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* hook up the driver ... */
+	driver->driver.bus = NULL;
+	udc->driver = driver;
+	udc->gadget.dev.driver = &driver->driver;
+
+	udc->usb_state = USB_STATE_ATTACHED;
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->ep0_dir = USB_DIR_OUT;
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	retval = bind(&udc->gadget);
+	if (retval) {
+		dev_err(&udc->dev->dev, "bind to driver %s --> %d\n",
+				driver->driver.name, retval);
+		udc->driver = NULL;
+		udc->gadget.dev.driver = NULL;
+		return retval;
+	}
+	udc_reset(udc);
+	ep0_reset(udc);
+	udc_start(udc);
+
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct mv_udc *udc = the_controller;
+	unsigned long flags;
+
+	if (!udc)
+		return -ENODEV;
+
+	udc_stop(udc);
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* stop all usb activities */
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	stop_activity(udc, driver);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	/* unbind gadget driver */
+	driver->unbind(&udc->gadget);
+	udc->gadget.dev.driver = NULL;
+	udc->driver = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+static int
+udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
+{
+	int retval = 0;
+	struct mv_req *req;
+	struct mv_ep *ep;
+
+	ep = &udc->eps[0];
+	udc->ep0_dir = direction;
+
+	req = udc->status_req;
+
+	/* fill in the reqest structure */
+	if (empty == false) {
+		*((u16 *) req->req.buf) = cpu_to_le16(status);
+		req->req.length = 2;
+	} else
+		req->req.length = 0;
+
+	req->ep = ep;
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+	req->req.complete = NULL;
+	req->dtd_count = 0;
+
+	/* prime the data phase */
+	if (!req_to_dtd(req))
+		retval = queue_dtd(ep, req);
+	else{	/* no mem */
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	if (retval) {
+		dev_err(&udc->dev->dev, "response error on GET_STATUS request\n");
+		goto out;
+	}
+
+	list_add_tail(&req->queue, &ep->queue);
+
+	return 0;
+out:
+	return retval;
+}
+
+static void ch9setaddress(struct mv_udc *udc, struct usb_ctrlrequest *setup)
+{
+	udc->dev_addr = (u8)setup->wValue;
+
+	/* update usb state */
+	udc->usb_state = USB_STATE_ADDRESS;
+
+	if (udc_prime_status(udc, EP_DIR_IN, 0, true))
+		ep0_stall(udc);
+}
+
+static void ch9getstatus(struct mv_udc *udc, u8 ep_num,
+	struct usb_ctrlrequest *setup)
+{
+	u16 status;
+	int retval;
+
+	if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
+		!= (USB_DIR_IN | USB_TYPE_STANDARD))
+		return;
+
+	if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
+		status = 1 << USB_DEVICE_SELF_POWERED;
+		status |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+	} else if ((setup->bRequestType & USB_RECIP_MASK)
+			== USB_RECIP_INTERFACE) {
+		/* get interface status */
+		status = 0;
+	} else if ((setup->bRequestType & USB_RECIP_MASK)
+			== USB_RECIP_ENDPOINT) {
+		u8 ep_num, direction;
+
+		ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
+		direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
+				? EP_DIR_IN : EP_DIR_OUT;
+		status = ep_is_stall(udc, ep_num, direction)
+				<< USB_ENDPOINT_HALT;
+	}
+
+	retval = udc_prime_status(udc, EP_DIR_IN, status, false);
+	if (retval)
+		ep0_stall(udc);
+}
+
+static void ch9clearfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
+{
+	u8 ep_num;
+	u8 direction;
+	struct mv_ep *ep;
+
+	if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+		== ((USB_TYPE_STANDARD | USB_RECIP_DEVICE))) {
+		switch (setup->wValue) {
+		case USB_DEVICE_REMOTE_WAKEUP:
+			udc->remote_wakeup = 0;
+			break;
+		case USB_DEVICE_TEST_MODE:
+			mv_udc_testmode(udc, 0, false);
+			break;
+		default:
+			goto out;
+		}
+	} else if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+		== ((USB_TYPE_STANDARD | USB_RECIP_ENDPOINT))) {
+		switch (setup->wValue) {
+		case USB_ENDPOINT_HALT:
+			ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
+			direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
+				? EP_DIR_IN : EP_DIR_OUT;
+			if (setup->wValue != 0 || setup->wLength != 0
+				|| ep_num > udc->max_eps)
+				goto out;
+			ep = &udc->eps[ep_num * 2 + direction];
+			if (ep->wedge == 1)
+				break;
+			spin_unlock(&udc->lock);
+			ep_set_stall(udc, ep_num, direction, 0);
+			spin_lock(&udc->lock);
+			break;
+		default:
+			goto out;
+		}
+	} else
+		goto out;
+
+	if (udc_prime_status(udc, EP_DIR_IN, 0, true))
+		ep0_stall(udc);
+	else
+		udc->ep0_state = DATA_STATE_XMIT;
+out:
+	return;
+}
+
+static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
+{
+	u8 ep_num;
+	u8 direction;
+
+	if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+		== ((USB_TYPE_STANDARD | USB_RECIP_DEVICE))) {
+		switch (setup->wValue) {
+		case USB_DEVICE_REMOTE_WAKEUP:
+			udc->remote_wakeup = 1;
+			break;
+		case USB_DEVICE_TEST_MODE:
+			if (setup->wIndex & 0xFF
+				&& udc->gadget.speed != USB_SPEED_HIGH)
+				goto out;
+			if (udc->usb_state == USB_STATE_CONFIGURED
+				|| udc->usb_state == USB_STATE_ADDRESS
+				|| udc->usb_state == USB_STATE_DEFAULT)
+				mv_udc_testmode(udc,
+					setup->wIndex & 0xFF00, true);
+			else
+				goto out;
+			break;
+		default:
+			goto out;
+		}
+	} else if ((setup->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK))
+		== ((USB_TYPE_STANDARD | USB_RECIP_ENDPOINT))) {
+		switch (setup->wValue) {
+		case USB_ENDPOINT_HALT:
+			ep_num = setup->wIndex & USB_ENDPOINT_NUMBER_MASK;
+			direction = (setup->wIndex & USB_ENDPOINT_DIR_MASK)
+				? EP_DIR_IN : EP_DIR_OUT;
+			if (setup->wValue != 0 || setup->wLength != 0
+				|| ep_num > udc->max_eps)
+				goto out;
+			spin_unlock(&udc->lock);
+			ep_set_stall(udc, ep_num, direction, 1);
+			spin_lock(&udc->lock);
+			break;
+		default:
+			goto out;
+		}
+	} else
+		goto out;
+
+	if (udc_prime_status(udc, EP_DIR_IN, 0, true))
+		ep0_stall(udc);
+out:
+	return;
+}
+
+static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
+	struct usb_ctrlrequest *setup)
+{
+	bool delegate = false;
+
+	nuke(&udc->eps[ep_num * 2 + EP_DIR_OUT], -ESHUTDOWN);
+
+	dev_dbg(&udc->dev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+			setup->bRequestType, setup->bRequest,
+			setup->wValue, setup->wIndex, setup->wLength);
+	/* We process some stardard setup requests here */
+	if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+		switch (setup->bRequest) {
+		case USB_REQ_GET_STATUS:
+			ch9getstatus(udc, ep_num, setup);
+			break;
+
+		case USB_REQ_SET_ADDRESS:
+			ch9setaddress(udc, setup);
+			break;
+
+		case USB_REQ_CLEAR_FEATURE:
+			ch9clearfeature(udc, setup);
+			break;
+
+		case USB_REQ_SET_FEATURE:
+			ch9setfeature(udc, setup);
+			break;
+
+		default:
+			delegate = true;
+		}
+	} else
+		delegate = true;
+
+	/* delegate USB standard requests to the gadget driver */
+	if (delegate == true) {
+		/* USB requests handled by gadget */
+		if (setup->wLength) {
+			/* DATA phase from gadget, STATUS phase from udc */
+			udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
+					?  EP_DIR_IN : EP_DIR_OUT;
+			spin_unlock(&udc->lock);
+			if (udc->driver->setup(&udc->gadget,
+				&udc->local_setup_buff) < 0)
+				ep0_stall(udc);
+			spin_lock(&udc->lock);
+			udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
+					?  DATA_STATE_XMIT : DATA_STATE_RECV;
+		} else {
+			/* no DATA phase, IN STATUS phase from gadget */
+			udc->ep0_dir = EP_DIR_IN;
+			spin_unlock(&udc->lock);
+			if (udc->driver->setup(&udc->gadget,
+				&udc->local_setup_buff) < 0)
+				ep0_stall(udc);
+			spin_lock(&udc->lock);
+			udc->ep0_state = WAIT_FOR_OUT_STATUS;
+		}
+	}
+}
+
+/* complete DATA or STATUS phase of ep0 prime status phase if needed */
+static void ep0_req_complete(struct mv_udc *udc,
+	struct mv_ep *ep0, struct mv_req *req)
+{
+	u32 new_addr;
+
+	if (udc->usb_state == USB_STATE_ADDRESS) {
+		/* set the new address */
+		new_addr = (u32)udc->dev_addr;
+		writel(new_addr << USB_DEVICE_ADDRESS_BIT_SHIFT,
+			&udc->op_regs->deviceaddr);
+	}
+
+	done(ep0, req, 0);
+
+	switch (udc->ep0_state) {
+	case DATA_STATE_XMIT:
+		/* receive status phase */
+		if (udc_prime_status(udc, EP_DIR_OUT, 0, true))
+			ep0_stall(udc);
+		break;
+	case DATA_STATE_RECV:
+		/* send status phase */
+		if (udc_prime_status(udc, EP_DIR_IN, 0 , true))
+			ep0_stall(udc);
+		break;
+	case WAIT_FOR_OUT_STATUS:
+		udc->ep0_state = WAIT_FOR_SETUP;
+		break;
+	case WAIT_FOR_SETUP:
+		dev_err(&udc->dev->dev, "unexpect ep0 packets\n");
+		break;
+	default:
+		ep0_stall(udc);
+		break;
+	}
+}
+
+static void get_setup_data(struct mv_udc *udc, u8 ep_num, u8 *buffer_ptr)
+{
+	u32 temp;
+	struct mv_dqh *dqh;
+
+	dqh = &udc->ep_dqh[ep_num * 2 + EP_DIR_OUT];
+
+	/* Clear bit in ENDPTSETUPSTAT */
+	temp = readl(&udc->op_regs->epsetupstat);
+	writel(temp | (1 << ep_num), &udc->op_regs->epsetupstat);
+
+	/* while a hazard exists when setup package arrives */
+	do {
+		/* Set Setup Tripwire */
+		temp = readl(&udc->op_regs->usbcmd);
+		writel(temp | USBCMD_SETUP_TRIPWIRE_SET, &udc->op_regs->usbcmd);
+
+		/* Copy the setup packet to local buffer */
+		memcpy(buffer_ptr, (u8 *) dqh->setup_buffer, 8);
+	} while (!(readl(&udc->op_regs->usbcmd) & USBCMD_SETUP_TRIPWIRE_SET));
+
+	/* Clear Setup Tripwire */
+	temp = readl(&udc->op_regs->usbcmd);
+	writel(temp & ~USBCMD_SETUP_TRIPWIRE_SET, &udc->op_regs->usbcmd);
+}
+
+static void irq_process_tr_complete(struct mv_udc *udc)
+{
+	u32 tmp, bit_pos;
+	int i, ep_num = 0, direction = 0;
+	struct mv_ep	*curr_ep;
+	struct mv_req *curr_req, *temp_req;
+	int status;
+
+	/*
+	 * We use separate loops for ENDPTSETUPSTAT and ENDPTCOMPLETE
+	 * because the setup packets are to be read ASAP
+	 */
+
+	/* Process all Setup packet received interrupts */
+	tmp = readl(&udc->op_regs->epsetupstat);
+
+	if (tmp) {
+		for (i = 0; i < udc->max_eps; i++) {
+			if (tmp & (1 << i)) {
+				get_setup_data(udc, i,
+					(u8 *)(&udc->local_setup_buff));
+				handle_setup_packet(udc, i,
+					&udc->local_setup_buff);
+			}
+		}
+	}
+
+	/* Don't clear the endpoint setup status register here.
+	 * It is cleared as a setup packet is read out of the buffer
+	 */
+
+	/* Process non-setup transaction complete interrupts */
+	tmp = readl(&udc->op_regs->epcomplete);
+
+	if (!tmp)
+		return;
+
+	writel(tmp, &udc->op_regs->epcomplete);
+
+	for (i = 0; i < udc->max_eps * 2; i++) {
+		ep_num = i >> 1;
+		direction = i % 2;
+
+		bit_pos = 1 << (ep_num + 16 * direction);
+
+		if (!(bit_pos & tmp))
+			continue;
+
+		if (i == 1)
+			curr_ep = &udc->eps[0];
+		else
+			curr_ep = &udc->eps[i];
+		/* process the req queue until an uncomplete request */
+		list_for_each_entry_safe(curr_req, temp_req,
+			&curr_ep->queue, queue) {
+			status = process_ep_req(udc, i, curr_req);
+			if (status)
+				break;
+
+			/* write back status to req */
+			curr_req->req.status = status;
+
+			/* ep0 request completion */
+			if (ep_num == 0) {
+				ep0_req_complete(udc, curr_ep, curr_req);
+				break;
+			} else {
+				done(curr_ep, curr_req, status);
+			}
+		}
+	}
+}
+
+void irq_process_reset(struct mv_udc *udc)
+{
+	u32 tmp;
+	unsigned int loops;
+
+	udc->ep0_dir = EP_DIR_OUT;
+	udc->ep0_state = WAIT_FOR_SETUP;
+	udc->remote_wakeup = 0;		/* default to 0 on reset */
+
+	/* The address bits are past bit 25-31. Set the address */
+	tmp = readl(&udc->op_regs->deviceaddr);
+	tmp &= ~(USB_DEVICE_ADDRESS_MASK);
+	writel(tmp, &udc->op_regs->deviceaddr);
+
+	/* Clear all the setup token semaphores */
+	tmp = readl(&udc->op_regs->epsetupstat);
+	writel(tmp, &udc->op_regs->epsetupstat);
+
+	/* Clear all the endpoint complete status bits */
+	tmp = readl(&udc->op_regs->epcomplete);
+	writel(tmp, &udc->op_regs->epcomplete);
+
+	/* wait until all endptprime bits cleared */
+	loops = LOOPS(PRIME_TIMEOUT);
+	while (readl(&udc->op_regs->epprime) & 0xFFFFFFFF) {
+		if (loops == 0) {
+			dev_err(&udc->dev->dev,
+				"Timeout for ENDPTPRIME = 0x%x\n",
+				readl(&udc->op_regs->epprime));
+			break;
+		}
+		loops--;
+		udelay(LOOPS_USEC);
+	}
+
+	/* Write 1s to the Flush register */
+	writel((u32)~0, &udc->op_regs->epflush);
+
+	if (readl(&udc->op_regs->portsc[0]) & PORTSCX_PORT_RESET) {
+		dev_info(&udc->dev->dev, "usb bus reset\n");
+		udc->usb_state = USB_STATE_DEFAULT;
+		/* reset all the queues, stop all USB activities */
+		stop_activity(udc, udc->driver);
+	} else {
+		dev_info(&udc->dev->dev, "USB reset portsc 0x%x\n",
+			readl(&udc->op_regs->portsc));
+
+		/*
+		 * re-initialize
+		 * controller reset
+		 */
+		udc_reset(udc);
+
+		/* reset all the queues, stop all USB activities */
+		stop_activity(udc, udc->driver);
+
+		/* reset ep0 dQH and endptctrl */
+		ep0_reset(udc);
+
+		/* enable interrupt and set controller to run state */
+		udc_start(udc);
+
+		udc->usb_state = USB_STATE_ATTACHED;
+	}
+}
+
+static void handle_bus_resume(struct mv_udc *udc)
+{
+	udc->usb_state = udc->resume_state;
+	udc->resume_state = 0;
+
+	/* report resume to the driver */
+	if (udc->driver) {
+		if (udc->driver->resume) {
+			spin_unlock(&udc->lock);
+			udc->driver->resume(&udc->gadget);
+			spin_lock(&udc->lock);
+		}
+	}
+}
+
+static void irq_process_suspend(struct mv_udc *udc)
+{
+	udc->resume_state = udc->usb_state;
+	udc->usb_state = USB_STATE_SUSPENDED;
+
+	if (udc->driver->suspend) {
+		spin_unlock(&udc->lock);
+		udc->driver->suspend(&udc->gadget);
+		spin_lock(&udc->lock);
+	}
+}
+
+static void irq_process_port_change(struct mv_udc *udc)
+{
+	u32 portsc;
+
+	portsc = readl(&udc->op_regs->portsc[0]);
+	if (!(portsc & PORTSCX_PORT_RESET)) {
+		/* Get the speed */
+		u32 speed = portsc & PORTSCX_PORT_SPEED_MASK;
+		switch (speed) {
+		case PORTSCX_PORT_SPEED_HIGH:
+			udc->gadget.speed = USB_SPEED_HIGH;
+			break;
+		case PORTSCX_PORT_SPEED_FULL:
+			udc->gadget.speed = USB_SPEED_FULL;
+			break;
+		case PORTSCX_PORT_SPEED_LOW:
+			udc->gadget.speed = USB_SPEED_LOW;
+			break;
+		default:
+			udc->gadget.speed = USB_SPEED_UNKNOWN;
+			break;
+		}
+	}
+
+	if (portsc & PORTSCX_PORT_SUSPEND) {
+		udc->resume_state = udc->usb_state;
+		udc->usb_state = USB_STATE_SUSPENDED;
+		if (udc->driver->suspend) {
+			spin_unlock(&udc->lock);
+			udc->driver->suspend(&udc->gadget);
+			spin_lock(&udc->lock);
+		}
+	}
+
+	if (!(portsc & PORTSCX_PORT_SUSPEND)
+		&& udc->usb_state == USB_STATE_SUSPENDED) {
+		handle_bus_resume(udc);
+	}
+
+	if (!udc->resume_state)
+		udc->usb_state = USB_STATE_DEFAULT;
+}
+
+static void irq_process_error(struct mv_udc *udc)
+{
+	/* Increment the error count */
+	udc->errors++;
+}
+
+static irqreturn_t mv_udc_irq(int irq, void *dev)
+{
+	struct mv_udc *udc = (struct mv_udc *)dev;
+	u32 status, intr;
+
+	spin_lock(&udc->lock);
+
+	status = readl(&udc->op_regs->usbsts);
+	intr = readl(&udc->op_regs->usbintr);
+	status &= intr;
+
+	if (status == 0) {
+		spin_unlock(&udc->lock);
+		return IRQ_NONE;
+	}
+
+	/* Clear all the interrupts occured */
+	writel(status, &udc->op_regs->usbsts);
+
+	if (status & USBSTS_ERR)
+		irq_process_error(udc);
+
+	if (status & USBSTS_RESET)
+		irq_process_reset(udc);
+
+	if (status & USBSTS_PORT_CHANGE)
+		irq_process_port_change(udc);
+
+	if (status & USBSTS_INT)
+		irq_process_tr_complete(udc);
+
+	if (status & USBSTS_SUSPEND)
+		irq_process_suspend(udc);
+
+	spin_unlock(&udc->lock);
+
+	return IRQ_HANDLED;
+}
+
+/* release device structure */
+static void gadget_release(struct device *_dev)
+{
+	struct mv_udc *udc = the_controller;
+
+	complete(udc->done);
+	kfree(udc);
+}
+
+static int mv_udc_remove(struct platform_device *dev)
+{
+	struct mv_udc *udc = the_controller;
+
+	DECLARE_COMPLETION(done);
+
+	udc->done = &done;
+
+	/* free memory allocated in probe */
+	if (udc->dtd_pool)
+		dma_pool_destroy(udc->dtd_pool);
+
+	if (udc->ep_dqh)
+		dma_free_coherent(&dev->dev, udc->ep_dqh_size,
+			udc->ep_dqh, udc->ep_dqh_dma);
+
+	kfree(udc->eps);
+
+	if (udc->irq)
+		free_irq(udc->irq, &dev->dev);
+
+	if (udc->cap_regs)
+		iounmap(udc->cap_regs);
+	udc->cap_regs = NULL;
+
+	if (udc->phy_regs)
+		iounmap((void *)udc->phy_regs);
+	udc->phy_regs = 0;
+
+	if (udc->status_req) {
+		kfree(udc->status_req->req.buf);
+		kfree(udc->status_req);
+	}
+
+	device_unregister(&udc->gadget.dev);
+
+	/* free dev, wait for the release() finished */
+	wait_for_completion(&done);
+
+	the_controller = NULL;
+
+	return 0;
+}
+
+int mv_udc_probe(struct platform_device *dev)
+{
+	struct mv_udc *udc;
+	int retval = 0;
+	struct resource *r;
+	size_t size;
+
+	udc = kzalloc(sizeof *udc, GFP_KERNEL);
+	if (udc == NULL) {
+		dev_err(&dev->dev, "failed to allocate memory for udc\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	spin_lock_init(&udc->lock);
+
+	udc->dev = dev;
+
+	udc->clk = clk_get(&dev->dev, "U2OCLK");
+	if (IS_ERR(udc->clk)) {
+		retval = PTR_ERR(udc->clk);
+		goto error;
+	}
+
+	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "u2o");
+	if (r == NULL) {
+		dev_err(&dev->dev, "no I/O memory resource defined\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	udc->cap_regs = (struct mv_cap_regs __iomem *)
+		ioremap(r->start, resource_size(r));
+	if (udc->cap_regs == NULL) {
+		dev_err(&dev->dev, "failed to map I/O memory\n");
+		retval = -EBUSY;
+		goto error;
+	}
+
+	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "u2ophy");
+	if (r == NULL) {
+		dev_err(&dev->dev, "no phy I/O memory resource defined\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	udc->phy_regs = (unsigned int)ioremap(r->start, resource_size(r));
+	if (udc->phy_regs == 0) {
+		dev_err(&dev->dev, "failed to map phy I/O memory\n");
+		retval = -EBUSY;
+		goto error;
+	}
+
+	/* we will acces controller register, so enable the clk */
+	clk_enable(udc->clk);
+	retval = mv_udc_phy_init(udc->phy_regs);
+	if (retval) {
+		dev_err(&dev->dev, "phy initialization error %d\n", retval);
+		goto error;
+	}
+
+	udc->op_regs = (struct mv_op_regs __iomem *)((u32)udc->cap_regs
+		+ (readl(&udc->cap_regs->caplength_hciversion)
+			& CAPLENGTH_MASK));
+	udc->max_eps = readl(&udc->cap_regs->dccparams) & DCCPARAMS_DEN_MASK;
+
+	size = udc->max_eps * sizeof(struct mv_dqh) *2;
+	size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1);
+	udc->ep_dqh = dma_alloc_coherent(&dev->dev, size,
+					&udc->ep_dqh_dma, GFP_KERNEL);
+
+	if (udc->ep_dqh == NULL) {
+		dev_err(&dev->dev, "allocate dQH memory failed\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+	udc->ep_dqh_size = size;
+
+	/* create dTD dma_pool resource */
+	udc->dtd_pool = dma_pool_create("mv_dtd",
+			&dev->dev,
+			sizeof(struct mv_dtd),
+			DTD_ALIGNMENT,
+			DMA_BOUNDARY);
+
+	if (!udc->dtd_pool) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	size = udc->max_eps * sizeof(struct mv_ep) *2;
+	udc->eps = kzalloc(size, GFP_KERNEL);
+	if (udc->eps == NULL) {
+		dev_err(&dev->dev, "allocate ep memory failed\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	/* initialize ep0 status request structure */
+	udc->status_req = kzalloc(sizeof(struct mv_req), GFP_KERNEL);
+	if (!udc->status_req) {
+		dev_err(&dev->dev, "allocate status_req memory failed\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+	INIT_LIST_HEAD(&udc->status_req->queue);
+
+	/* allocate a small amount of memory to get valid address */
+	udc->status_req->req.buf = kzalloc(8, GFP_KERNEL);
+	udc->status_req->req.dma = virt_to_phys(udc->status_req->req.buf);
+
+	udc->resume_state = USB_STATE_NOTATTACHED;
+	udc->usb_state = USB_STATE_POWERED;
+	udc->ep0_dir = EP_DIR_OUT;
+	udc->remote_wakeup = 0;
+
+	r = platform_get_resource(udc->dev, IORESOURCE_IRQ, 0);
+	if (r == NULL) {
+		dev_err(&dev->dev, "no IRQ resource defined\n");
+		retval = -ENODEV;
+		goto error;
+	}
+	udc->irq = r->start;
+	if (request_irq(udc->irq, mv_udc_irq,
+		IRQF_DISABLED | IRQF_SHARED, driver_name, udc)) {
+		dev_err(&dev->dev, "Request irq %d for UDC failed\n",
+			udc->irq);
+		retval = -ENODEV;
+		goto error;
+	}
+
+	/* initialize gadget structure */
+	udc->gadget.ops = &mv_ops;	/* usb_gadget_ops */
+	udc->gadget.ep0 = &udc->eps[0].ep;	/* gadget ep0 */
+	INIT_LIST_HEAD(&udc->gadget.ep_list);	/* ep_list */
+	udc->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */
+	udc->gadget.is_dualspeed = 1;		/* support dual speed */
+
+	/* the "gadget" abstracts/virtualizes the controller */
+	dev_set_name(&udc->gadget.dev, "gadget");
+	udc->gadget.dev.parent = &dev->dev;
+	udc->gadget.dev.dma_mask = dev->dev.dma_mask;
+	udc->gadget.dev.release = gadget_release;
+	udc->gadget.name = driver_name;		/* gadget name */
+
+	retval = device_register(&udc->gadget.dev);
+	if (retval)
+		goto error;
+
+	eps_init(udc);
+
+	the_controller = udc;
+
+	goto out;
+error:
+	if (udc)
+		mv_udc_remove(udc->dev);
+out:
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state)
+{
+	struct mv_udc *udc = the_controller;
+
+	udc_stop(udc);
+
+	return 0;
+}
+
+static int mv_udc_resume(struct platform_device *_dev)
+{
+	struct mv_udc *udc = the_controller;
+	int retval;
+
+	retval = mv_udc_phy_init(udc->phy_regs);
+	if (retval) {
+		dev_err(_dev, "phy initialization error %d\n", retval);
+		goto error;
+	}
+	udc_reset(udc);
+	ep0_reset(udc);
+	udc_start(udc);
+
+	return 0;
+}
+
+static const struct dev_pm_ops mv_udc_pm_ops = {
+	.suspend	= mv_udc_suspend,
+	.resume		= mv_udc_resume,
+};
+#endif
+
+static struct platform_driver udc_driver = {
+	.probe		= mv_udc_probe,
+	.remove		= __exit_p(mv_udc_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "pxa-u2o",
+#ifdef CONFIG_PM
+		.pm	= mv_udc_pm_ops,
+#endif
+	},
+};
+
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+
+static int __init init(void)
+{
+	return platform_driver_register(&udc_driver);
+}
+module_init(init);
+
+
+static void __exit cleanup(void)
+{
+	platform_driver_unregister(&udc_driver);
+}
+module_exit(cleanup);
+
diff --git a/drivers/usb/gadget/mv_udc_phy.c b/drivers/usb/gadget/mv_udc_phy.c
new file mode 100644
index 0000000..d4dea97
--- /dev/null
+++ b/drivers/usb/gadget/mv_udc_phy.c
@@ -0,0 +1,214 @@
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+
+#include <mach/cputype.h>
+
+#ifdef CONFIG_ARCH_MMP
+
+#define UTMI_REVISION		0x0
+#define UTMI_CTRL		0x4
+#define UTMI_PLL		0x8
+#define UTMI_TX			0xc
+#define UTMI_RX			0x10
+#define UTMI_IVREF		0x14
+#define UTMI_T0			0x18
+#define UTMI_T1			0x1c
+#define UTMI_T2			0x20
+#define UTMI_T3			0x24
+#define UTMI_T4			0x28
+#define UTMI_T5			0x2c
+#define UTMI_RESERVE		0x30
+#define UTMI_USB_INT		0x34
+#define UTMI_DBG_CTL		0x38
+#define UTMI_OTG_ADDON		0x3c
+
+/* For UTMICTRL Register */
+#define UTMI_CTRL_USB_CLK_EN			(1 << 31)
+/* pxa168 */
+#define UTMI_CTRL_SUSPEND_SET1			(1 << 30)
+#define UTMI_CTRL_SUSPEND_SET2			(1 << 29)
+#define UTMI_CTRL_RXBUF_PDWN			(1 << 24)
+#define UTMI_CTRL_TXBUF_PDWN			(1 << 11)
+
+#define UTMI_CTRL_INPKT_DELAY_SHIFT		30
+#define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT		28
+#define UTMI_CTRL_PU_REF_SHIFT			20
+#define UTMI_CTRL_ARC_PULLDN_SHIFT		12
+#define UTMI_CTRL_PLL_PWR_UP_SHIFT		1
+#define UTMI_CTRL_PWR_UP_SHIFT			0
+/* For UTMI_PLL Register */
+#define UTMI_PLL_CLK_BLK_EN_SHIFT		24
+#define UTMI_PLL_FBDIV_SHIFT			4
+#define UTMI_PLL_REFDIV_SHIFT			0
+#define UTMI_PLL_FBDIV_MASK			0x00000FF0
+#define UTMI_PLL_REFDIV_MASK			0x0000000F
+#define UTMI_PLL_ICP_MASK			0x00007000
+#define UTMI_PLL_KVCO_MASK			0x00031000
+#define UTMI_PLL_PLLCALI12_SHIFT		29
+#define UTMI_PLL_PLLCALI12_MASK			(0x3 << 29)
+#define UTMI_PLL_PLLVDD18_SHIFT			27
+#define UTMI_PLL_PLLVDD18_MASK			(0x3 << 27)
+#define UTMI_PLL_PLLVDD12_SHIFT			25
+#define UTMI_PLL_PLLVDD12_MASK			(0x3 << 25)
+#define UTMI_PLL_KVCO_SHIFT			15
+#define UTMI_PLL_ICP_SHIFT			12
+/* For UTMI_TX Register */
+#define UTMI_TX_REG_EXT_FS_RCAL_SHIFT		27
+#define UTMI_TX_REG_EXT_FS_RCAL_MASK		(0xf << 27)
+#define UTMI_TX_REG_EXT_FS_RCAL_EN_MASK		26
+#define UTMI_TX_REG_EXT_FS_RCAL_EN		(0x1 << 26)
+#define UTMI_TX_LOW_VDD_EN_SHIFT		11
+#define UTMI_TX_IMPCAL_VTH_SHIFT		14
+#define UTMI_TX_IMPCAL_VTH_MASK			(0x7 << 14)
+#define UTMI_TX_CK60_PHSEL_SHIFT		17
+#define UTMI_TX_CK60_PHSEL_MASK			(0xf << 17)
+#define UTMI_TX_TXVDD12_SHIFT                   22
+#define UTMI_TX_TXVDD12_MASK			(0x3 << 22)
+#define UTMI_TX_AMP_SHIFT			0
+#define UTMI_TX_AMP_MASK			(0x7 << 0)
+/* For UTMI_RX Register */
+#define UTMI_RX_SQ_THRESH_SHIFT			4
+#define UTMI_RX_SQ_THRESH_MASK			(0xf << 4)
+#define UTMI_REG_SQ_LENGTH_SHIFT		15
+#define UTMI_REG_SQ_LENGTH_MASK			(0x3 << 15)
+
+#define REG_RCAL_START				0x00001000
+#define VCOCAL_START				0x00200000
+#define KVCO_EXT				0x00400000
+#define PLL_READY				0x00800000
+#define CLK_BLK_EN				0x01000000
+#endif
+
+static unsigned int u2o_read(unsigned int base, unsigned int offset)
+{
+	return readl(base + offset);
+}
+
+static void u2o_set(unsigned int base, unsigned int offset, unsigned int value)
+{
+	unsigned int reg;
+
+	reg = readl(base + offset);
+	reg |= value;
+	writel(reg, base + offset);
+	readl(base + offset);
+}
+
+static void u2o_clear(unsigned int base, unsigned int offset,
+	unsigned int value)
+{
+	unsigned int reg;
+
+	reg = readl(base + offset);
+	reg &= ~value;
+	writel(reg, base + offset);
+	readl(base + offset);
+}
+
+static void u2o_write(unsigned int base, unsigned int offset,
+	unsigned int value)
+{
+	writel(value, base + offset);
+	readl(base + offset);
+}
+
+#ifdef CONFIG_ARCH_MMP
+int mv_udc_phy_init(unsigned int base)
+{
+	unsigned long timeout;
+
+	/* Initialize the USB PHY power */
+	if (cpu_is_pxa910()) {
+		u2o_set(base, UTMI_CTRL, (1 << UTMI_CTRL_INPKT_DELAY_SOF_SHIFT)
+			| (1 << UTMI_CTRL_PU_REF_SHIFT));
+	}
+
+	u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PLL_PWR_UP_SHIFT);
+	u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PWR_UP_SHIFT);
+
+	/* UTMI_PLL settings */
+	u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK
+		| UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK
+		| UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK
+		| UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK);
+
+	u2o_set(base, UTMI_PLL, (0xee << UTMI_PLL_FBDIV_SHIFT)
+		| (0xb << UTMI_PLL_REFDIV_SHIFT)
+		| (3 << UTMI_PLL_PLLVDD18_SHIFT)
+		| (3 << UTMI_PLL_PLLVDD12_SHIFT)
+		| (3 << UTMI_PLL_PLLCALI12_SHIFT)
+		| (1 << UTMI_PLL_ICP_SHIFT) | (3 << UTMI_PLL_KVCO_SHIFT));
+
+	/* UTMI_TX */
+	u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK
+		| UTMI_TX_TXVDD12_MASK
+		| UTMI_TX_CK60_PHSEL_MASK | UTMI_TX_IMPCAL_VTH_MASK
+		| UTMI_TX_REG_EXT_FS_RCAL_MASK | UTMI_TX_AMP_MASK);
+	u2o_set(base, UTMI_TX, (3 << UTMI_TX_TXVDD12_SHIFT)
+		| (4 << UTMI_TX_CK60_PHSEL_SHIFT)
+		| (4 << UTMI_TX_IMPCAL_VTH_SHIFT)
+		| (8 << UTMI_TX_REG_EXT_FS_RCAL_SHIFT)
+		| (3 << UTMI_TX_AMP_SHIFT));
+
+	/* UTMI_RX */
+	u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK
+		| UTMI_REG_SQ_LENGTH_MASK);
+	if (cpu_is_pxa168())
+		u2o_set(base, UTMI_RX, (7 << UTMI_RX_SQ_THRESH_SHIFT)
+			| (2 << UTMI_REG_SQ_LENGTH_SHIFT));
+	else
+		u2o_set(base, UTMI_RX, (0x7 << UTMI_RX_SQ_THRESH_SHIFT)
+			| (2 << UTMI_REG_SQ_LENGTH_SHIFT));
+
+	/* UTMI_IVREF */
+	if (cpu_is_pxa168())
+		/*
+		 * fixing Microsoft Altair board interface with NEC hub issue -
+		 * Set UTMI_IVREF from 0x4a3 to 0x4bf
+		 */
+		u2o_write(base, UTMI_IVREF, 0x4bf);
+
+	/* calibrate */
+	timeout = jiffies + 100;
+	while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) {
+		if (time_after(jiffies, timeout))
+			return -ETIME;
+		cpu_relax();
+	}
+
+	/* toggle VCOCAL_START bit of UTMI_PLL */
+	udelay(200);
+	u2o_set(base, UTMI_PLL, VCOCAL_START);
+	udelay(40);
+	u2o_clear(base, UTMI_PLL, VCOCAL_START);
+
+	/* toggle REG_RCAL_START bit of UTMI_TX */
+	udelay(200);
+	u2o_set(base, UTMI_TX, REG_RCAL_START);
+	udelay(40);
+	u2o_clear(base, UTMI_TX, REG_RCAL_START);
+	udelay(200);
+
+	/* make sure phy is ready */
+	timeout = jiffies + 100;
+	while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) {
+		if (time_after(jiffies, timeout))
+			return -ETIME;
+		cpu_relax();
+	}
+
+	if (cpu_is_pxa168()) {
+		u2o_set(base, UTMI_RESERVE, 1 << 5);
+		/* Turn on UTMI PHY OTG extension */
+		u2o_write(base, UTMI_OTG_ADDON, 1);
+	}
+	return 0;
+}
+#else
+int mv_udc_phy_init(unsigned int base)
+{
+	return 0;
+}
+#endif
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c
new file mode 100644
index 0000000..99c179a
--- /dev/null
+++ b/drivers/usb/gadget/ncm.c
@@ -0,0 +1,248 @@
+/*
+ * ncm.c -- NCM gadget driver
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Contact: Yauheni Kaliuta <yauheni.kaliuta@nokia.com>
+ *
+ * The driver borrows from ether.c which is:
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia 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
+ */
+
+/* #define DEBUG */
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+
+
+#include "u_ether.h"
+
+#define DRIVER_DESC		"NCM Gadget"
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_ncm.c"
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
+/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+
+/* Thanks to NetChip Technologies for donating this product ID.
+ * It's for devices with only CDC Ethernet configurations.
+ */
+#define CDC_VENDOR_NUM		0x0525	/* NetChip */
+#define CDC_PRODUCT_NUM		0xa4a1	/* Linux-USB Ethernet Gadget */
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+
+	.bcdUSB =		cpu_to_le16 (0x0200),
+
+	.bDeviceClass =		USB_CLASS_COMM,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
+	/* .bMaxPacketSize0 = f(hardware) */
+
+	/* Vendor and product id defaults change according to what configs
+	 * we support.  (As does bNumConfigurations.)  These values can
+	 * also be overridden by module parameters.
+	 */
+	.idVendor =		cpu_to_le16 (CDC_VENDOR_NUM),
+	.idProduct =		cpu_to_le16 (CDC_PRODUCT_NUM),
+	/* .bcdDevice = f(hardware) */
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	/* NO SERIAL NUMBER */
+	.bNumConfigurations =	1,
+};
+
+static struct usb_otg_descriptor otg_descriptor = {
+	.bLength =		sizeof otg_descriptor,
+	.bDescriptorType =	USB_DT_OTG,
+
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &otg_descriptor,
+	NULL,
+};
+
+
+/* string IDs are assigned dynamically */
+
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+
+static char manufacturer[50];
+
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dev = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dev,
+};
+
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
+static u8 hostaddr[ETH_ALEN];
+
+/*-------------------------------------------------------------------------*/
+
+static int __init ncm_do_config(struct usb_configuration *c)
+{
+	/* FIXME alloc iConfiguration string, set it in c->strings */
+
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	return ncm_bind_config(c, hostaddr);
+}
+
+static struct usb_configuration ncm_config_driver = {
+	/* .label = f(hardware) */
+	.label			= "CDC Ethernet (NCM)",
+	.bConfigurationValue	= 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init gncm_bind(struct usb_composite_dev *cdev)
+{
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			status;
+
+	/* set up network link layer */
+	status = gether_setup(cdev->gadget, hostaddr);
+	if (status < 0)
+		return status;
+
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
+	else {
+		/* We assume that can_support_ecm() tells the truth;
+		 * but if the controller isn't recognized at all then
+		 * that assumption is a bit more likely to be wrong.
+		 */
+		dev_warn(&gadget->dev,
+			 "controller '%s' not recognized; trying %s\n",
+			 gadget->name,
+			 ncm_config_driver.label);
+		device_desc.bcdDevice =
+			cpu_to_le16(0x0300 | 0x0099);
+	}
+
+
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
+	 */
+
+	/* device descriptor strings: manufacturer, product */
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		gadget->name);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
+	device_desc.iManufacturer = status;
+
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
+	device_desc.iProduct = status;
+
+	status = usb_add_config(cdev, &ncm_config_driver,
+				ncm_do_config);
+	if (status < 0)
+		goto fail;
+
+	dev_info(&gadget->dev, "%s\n", DRIVER_DESC);
+
+	return 0;
+
+fail:
+	gether_cleanup();
+	return status;
+}
+
+static int __exit gncm_unbind(struct usb_composite_dev *cdev)
+{
+	gether_cleanup();
+	return 0;
+}
+
+static struct usb_composite_driver ncm_driver = {
+	.name		= "g_ncm",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
+	.unbind		= __exit_p(gncm_unbind),
+};
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Yauheni Kaliuta");
+MODULE_LICENSE("GPL");
+
+static int __init init(void)
+{
+	return usb_composite_probe(&ncm_driver, gncm_bind);
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+	usb_composite_unregister(&ncm_driver);
+}
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
new file mode 100644
index 0000000..0c8dd81
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc.c
@@ -0,0 +1,2947 @@
+/*
+ * 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.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/* Address offset of Registers */
+#define UDC_EP_REG_SHIFT	0x20	/* Offset to next EP */
+
+#define UDC_EPCTL_ADDR		0x00	/* Endpoint control */
+#define UDC_EPSTS_ADDR		0x04	/* Endpoint status */
+#define UDC_BUFIN_FRAMENUM_ADDR	0x08	/* buffer size in / frame number out */
+#define UDC_BUFOUT_MAXPKT_ADDR	0x0C	/* buffer size out / maxpkt in */
+#define UDC_SUBPTR_ADDR		0x10	/* setup buffer pointer */
+#define UDC_DESPTR_ADDR		0x14	/* Data descriptor pointer */
+#define UDC_CONFIRM_ADDR	0x18	/* Write/Read confirmation */
+
+#define UDC_DEVCFG_ADDR		0x400	/* Device configuration */
+#define UDC_DEVCTL_ADDR		0x404	/* Device control */
+#define UDC_DEVSTS_ADDR		0x408	/* Device status */
+#define UDC_DEVIRQSTS_ADDR	0x40C	/* Device irq status */
+#define UDC_DEVIRQMSK_ADDR	0x410	/* Device irq mask */
+#define UDC_EPIRQSTS_ADDR	0x414	/* Endpoint irq status */
+#define UDC_EPIRQMSK_ADDR	0x418	/* Endpoint irq mask */
+#define UDC_DEVLPM_ADDR		0x41C	/* LPM control / status */
+#define UDC_CSR_BUSY_ADDR	0x4f0	/* UDC_CSR_BUSY Status register */
+#define UDC_SRST_ADDR		0x4fc	/* SOFT RESET register */
+#define UDC_CSR_ADDR		0x500	/* USB_DEVICE endpoint register */
+
+/* Endpoint control register */
+/* Bit position */
+#define UDC_EPCTL_MRXFLUSH		(1 << 12)
+#define UDC_EPCTL_RRDY			(1 << 9)
+#define UDC_EPCTL_CNAK			(1 << 8)
+#define UDC_EPCTL_SNAK			(1 << 7)
+#define UDC_EPCTL_NAK			(1 << 6)
+#define UDC_EPCTL_P			(1 << 3)
+#define UDC_EPCTL_F			(1 << 1)
+#define UDC_EPCTL_S			(1 << 0)
+#define UDC_EPCTL_ET_SHIFT		4
+/* Mask patern */
+#define UDC_EPCTL_ET_MASK		0x00000030
+/* Value for ET field */
+#define UDC_EPCTL_ET_CONTROL		0
+#define UDC_EPCTL_ET_ISO		1
+#define UDC_EPCTL_ET_BULK		2
+#define UDC_EPCTL_ET_INTERRUPT		3
+
+/* Endpoint status register */
+/* Bit position */
+#define UDC_EPSTS_XFERDONE		(1 << 27)
+#define UDC_EPSTS_RSS			(1 << 26)
+#define UDC_EPSTS_RCS			(1 << 25)
+#define UDC_EPSTS_TXEMPTY		(1 << 24)
+#define UDC_EPSTS_TDC			(1 << 10)
+#define UDC_EPSTS_HE			(1 << 9)
+#define UDC_EPSTS_MRXFIFO_EMP		(1 << 8)
+#define UDC_EPSTS_BNA			(1 << 7)
+#define UDC_EPSTS_IN			(1 << 6)
+#define UDC_EPSTS_OUT_SHIFT		4
+/* Mask patern */
+#define UDC_EPSTS_OUT_MASK		0x00000030
+#define UDC_EPSTS_ALL_CLR_MASK		0x1F0006F0
+/* Value for OUT field */
+#define UDC_EPSTS_OUT_SETUP		2
+#define UDC_EPSTS_OUT_DATA		1
+
+/* Device configuration register */
+/* Bit position */
+#define UDC_DEVCFG_CSR_PRG		(1 << 17)
+#define UDC_DEVCFG_SP			(1 << 3)
+/* SPD Valee */
+#define UDC_DEVCFG_SPD_HS		0x0
+#define UDC_DEVCFG_SPD_FS		0x1
+#define UDC_DEVCFG_SPD_LS		0x2
+
+/* Device control register */
+/* Bit position */
+#define UDC_DEVCTL_THLEN_SHIFT		24
+#define UDC_DEVCTL_BRLEN_SHIFT		16
+#define UDC_DEVCTL_CSR_DONE		(1 << 13)
+#define UDC_DEVCTL_SD			(1 << 10)
+#define UDC_DEVCTL_MODE			(1 << 9)
+#define UDC_DEVCTL_BREN			(1 << 8)
+#define UDC_DEVCTL_THE			(1 << 7)
+#define UDC_DEVCTL_DU			(1 << 4)
+#define UDC_DEVCTL_TDE			(1 << 3)
+#define UDC_DEVCTL_RDE			(1 << 2)
+#define UDC_DEVCTL_RES			(1 << 0)
+
+/* Device status register */
+/* Bit position */
+#define UDC_DEVSTS_TS_SHIFT		18
+#define UDC_DEVSTS_ENUM_SPEED_SHIFT	13
+#define UDC_DEVSTS_ALT_SHIFT		8
+#define UDC_DEVSTS_INTF_SHIFT		4
+#define UDC_DEVSTS_CFG_SHIFT		0
+/* Mask patern */
+#define UDC_DEVSTS_TS_MASK		0xfffc0000
+#define UDC_DEVSTS_ENUM_SPEED_MASK	0x00006000
+#define UDC_DEVSTS_ALT_MASK		0x00000f00
+#define UDC_DEVSTS_INTF_MASK		0x000000f0
+#define UDC_DEVSTS_CFG_MASK		0x0000000f
+/* value for maximum speed for SPEED field */
+#define UDC_DEVSTS_ENUM_SPEED_FULL	1
+#define UDC_DEVSTS_ENUM_SPEED_HIGH	0
+#define UDC_DEVSTS_ENUM_SPEED_LOW	2
+#define UDC_DEVSTS_ENUM_SPEED_FULLX	3
+
+/* Device irq register */
+/* Bit position */
+#define UDC_DEVINT_RWKP			(1 << 7)
+#define UDC_DEVINT_ENUM			(1 << 6)
+#define UDC_DEVINT_SOF			(1 << 5)
+#define UDC_DEVINT_US			(1 << 4)
+#define UDC_DEVINT_UR			(1 << 3)
+#define UDC_DEVINT_ES			(1 << 2)
+#define UDC_DEVINT_SI			(1 << 1)
+#define UDC_DEVINT_SC			(1 << 0)
+/* Mask patern */
+#define UDC_DEVINT_MSK			0x7f
+
+/* Endpoint irq register */
+/* Bit position */
+#define UDC_EPINT_IN_SHIFT		0
+#define UDC_EPINT_OUT_SHIFT		16
+#define UDC_EPINT_IN_EP0		(1 << 0)
+#define UDC_EPINT_OUT_EP0		(1 << 16)
+/* Mask patern */
+#define UDC_EPINT_MSK_DISABLE_ALL	0xffffffff
+
+/* UDC_CSR_BUSY Status register */
+/* Bit position */
+#define UDC_CSR_BUSY			(1 << 0)
+
+/* SOFT RESET register */
+/* Bit position */
+#define UDC_PSRST			(1 << 1)
+#define UDC_SRST			(1 << 0)
+
+/* USB_DEVICE endpoint register */
+/* Bit position */
+#define UDC_CSR_NE_NUM_SHIFT		0
+#define UDC_CSR_NE_DIR_SHIFT		4
+#define UDC_CSR_NE_TYPE_SHIFT		5
+#define UDC_CSR_NE_CFG_SHIFT		7
+#define UDC_CSR_NE_INTF_SHIFT		11
+#define UDC_CSR_NE_ALT_SHIFT		15
+#define UDC_CSR_NE_MAX_PKT_SHIFT	19
+/* Mask patern */
+#define UDC_CSR_NE_NUM_MASK		0x0000000f
+#define UDC_CSR_NE_DIR_MASK		0x00000010
+#define UDC_CSR_NE_TYPE_MASK		0x00000060
+#define UDC_CSR_NE_CFG_MASK		0x00000780
+#define UDC_CSR_NE_INTF_MASK		0x00007800
+#define UDC_CSR_NE_ALT_MASK		0x00078000
+#define UDC_CSR_NE_MAX_PKT_MASK		0x3ff80000
+
+#define PCH_UDC_CSR(ep)	(UDC_CSR_ADDR + ep*4)
+#define PCH_UDC_EPINT(in, num)\
+		(1 << (num + (in ? UDC_EPINT_IN_SHIFT : UDC_EPINT_OUT_SHIFT)))
+
+/* Index of endpoint */
+#define UDC_EP0IN_IDX		0
+#define UDC_EP0OUT_IDX		1
+#define UDC_EPIN_IDX(ep)	(ep * 2)
+#define UDC_EPOUT_IDX(ep)	(ep * 2 + 1)
+#define PCH_UDC_EP0		0
+#define PCH_UDC_EP1		1
+#define PCH_UDC_EP2		2
+#define PCH_UDC_EP3		3
+
+/* Number of endpoint */
+#define PCH_UDC_EP_NUM		32	/* Total number of EPs (16 IN,16 OUT) */
+#define PCH_UDC_USED_EP_NUM	4	/* EP number of EP's really used */
+/* Length Value */
+#define PCH_UDC_BRLEN		0x0F	/* Burst length */
+#define PCH_UDC_THLEN		0x1F	/* Threshold length */
+/* Value of EP Buffer Size */
+#define UDC_EP0IN_BUFF_SIZE	64
+#define UDC_EPIN_BUFF_SIZE	512
+#define UDC_EP0OUT_BUFF_SIZE	64
+#define UDC_EPOUT_BUFF_SIZE	512
+/* Value of EP maximum packet size */
+#define UDC_EP0IN_MAX_PKT_SIZE	64
+#define UDC_EP0OUT_MAX_PKT_SIZE	64
+#define UDC_BULK_MAX_PKT_SIZE	512
+
+/* DMA */
+#define DMA_DIR_RX		1	/* DMA for data receive */
+#define DMA_DIR_TX		2	/* DMA for data transmit */
+#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
+#define UDC_DMA_MAXPACKET	65536	/* maximum packet size for DMA */
+
+/**
+ * struct pch_udc_data_dma_desc - Structure to hold DMA descriptor information
+ *				  for data
+ * @status:		Status quadlet
+ * @reserved:		Reserved
+ * @dataptr:		Buffer descriptor
+ * @next:		Next descriptor
+ */
+struct pch_udc_data_dma_desc {
+	u32 status;
+	u32 reserved;
+	u32 dataptr;
+	u32 next;
+};
+
+/**
+ * struct pch_udc_stp_dma_desc - Structure to hold DMA descriptor information
+ *				 for control data
+ * @status:	Status
+ * @reserved:	Reserved
+ * @data12:	First setup word
+ * @data34:	Second setup word
+ */
+struct pch_udc_stp_dma_desc {
+	u32 status;
+	u32 reserved;
+	struct usb_ctrlrequest request;
+} __attribute((packed));
+
+/* DMA status definitions */
+/* Buffer status */
+#define PCH_UDC_BUFF_STS	0xC0000000
+#define PCH_UDC_BS_HST_RDY	0x00000000
+#define PCH_UDC_BS_DMA_BSY	0x40000000
+#define PCH_UDC_BS_DMA_DONE	0x80000000
+#define PCH_UDC_BS_HST_BSY	0xC0000000
+/*  Rx/Tx Status */
+#define PCH_UDC_RXTX_STS	0x30000000
+#define PCH_UDC_RTS_SUCC	0x00000000
+#define PCH_UDC_RTS_DESERR	0x10000000
+#define PCH_UDC_RTS_BUFERR	0x30000000
+/* Last Descriptor Indication */
+#define PCH_UDC_DMA_LAST	0x08000000
+/* Number of Rx/Tx Bytes Mask */
+#define PCH_UDC_RXTX_BYTES	0x0000ffff
+
+/**
+ * struct pch_udc_cfg_data - Structure to hold current configuration
+ *			     and interface information
+ * @cur_cfg:	current configuration in use
+ * @cur_intf:	current interface in use
+ * @cur_alt:	current alt interface in use
+ */
+struct pch_udc_cfg_data {
+	u16 cur_cfg;
+	u16 cur_intf;
+	u16 cur_alt;
+};
+
+/**
+ * struct pch_udc_ep - Structure holding a PCH USB device Endpoint information
+ * @ep:			embedded ep request
+ * @td_stp_phys:	for setup request
+ * @td_data_phys:	for data request
+ * @td_stp:		for setup request
+ * @td_data:		for data request
+ * @dev:		reference to device struct
+ * @offset_addr:	offset address of ep register
+ * @desc:		for this ep
+ * @queue:		queue for requests
+ * @num:		endpoint number
+ * @in:			endpoint is IN
+ * @halted:		endpoint halted?
+ * @epsts:		Endpoint status
+ */
+struct pch_udc_ep {
+	struct usb_ep			ep;
+	dma_addr_t			td_stp_phys;
+	dma_addr_t			td_data_phys;
+	struct pch_udc_stp_dma_desc	*td_stp;
+	struct pch_udc_data_dma_desc	*td_data;
+	struct pch_udc_dev		*dev;
+	unsigned long			offset_addr;
+	const struct usb_endpoint_descriptor	*desc;
+	struct list_head		queue;
+	unsigned			num:5,
+					in:1,
+					halted:1;
+	unsigned long			epsts;
+};
+
+/**
+ * struct pch_udc_dev - Structure holding complete information
+ *			of the PCH USB device
+ * @gadget:		gadget driver data
+ * @driver:		reference to gadget driver bound
+ * @pdev:		reference to the PCI device
+ * @ep:			array of endpoints
+ * @lock:		protects all state
+ * @active:		enabled the PCI device
+ * @stall:		stall requested
+ * @prot_stall:		protcol stall requested
+ * @irq_registered:	irq registered with system
+ * @mem_region:		device memory mapped
+ * @registered:		driver regsitered with system
+ * @suspended:		driver in suspended state
+ * @connected:		gadget driver associated
+ * @set_cfg_not_acked:	pending acknowledgement 4 setup
+ * @waiting_zlp_ack:	pending acknowledgement 4 ZLP
+ * @data_requests:	DMA pool for data requests
+ * @stp_requests:	DMA pool for setup requests
+ * @dma_addr:		DMA pool for received
+ * @ep0out_buf:		Buffer for DMA
+ * @setup_data:		Received setup data
+ * @phys_addr:		of device memory
+ * @base_addr:		for mapped device memory
+ * @irq:		IRQ line for the device
+ * @cfg_data:		current cfg, intf, and alt in use
+ */
+struct pch_udc_dev {
+	struct usb_gadget		gadget;
+	struct usb_gadget_driver	*driver;
+	struct pci_dev			*pdev;
+	struct pch_udc_ep		ep[PCH_UDC_EP_NUM];
+	spinlock_t			lock; /* protects all state */
+	unsigned	active:1,
+			stall:1,
+			prot_stall:1,
+			irq_registered:1,
+			mem_region:1,
+			registered:1,
+			suspended:1,
+			connected:1,
+			set_cfg_not_acked:1,
+			waiting_zlp_ack:1;
+	struct pci_pool		*data_requests;
+	struct pci_pool		*stp_requests;
+	dma_addr_t			dma_addr;
+	unsigned long			ep0out_buf[64];
+	struct usb_ctrlrequest		setup_data;
+	unsigned long			phys_addr;
+	void __iomem			*base_addr;
+	unsigned			irq;
+	struct pch_udc_cfg_data	cfg_data;
+};
+
+#define PCH_UDC_PCI_BAR			1
+#define PCI_DEVICE_ID_INTEL_EG20T_UDC	0x8808
+
+static const char	ep0_string[] = "ep0in";
+static DEFINE_SPINLOCK(udc_stall_spinlock);	/* stall spin lock */
+struct pch_udc_dev *pch_udc;		/* pointer to device object */
+
+static int speed_fs;
+module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
+MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
+
+/**
+ * struct pch_udc_request - Structure holding a PCH USB device request packet
+ * @req:		embedded ep request
+ * @td_data_phys:	phys. address
+ * @td_data:		first dma desc. of chain
+ * @td_data_last:	last dma desc. of chain
+ * @queue:		associated queue
+ * @dma_going:		DMA in progress for request
+ * @dma_mapped:		DMA memory mapped for request
+ * @dma_done:		DMA completed for request
+ * @chain_len:		chain length
+ */
+struct pch_udc_request {
+	struct usb_request		req;
+	dma_addr_t			td_data_phys;
+	struct pch_udc_data_dma_desc	*td_data;
+	struct pch_udc_data_dma_desc	*td_data_last;
+	struct list_head		queue;
+	unsigned			dma_going:1,
+					dma_mapped:1,
+					dma_done:1;
+	unsigned			chain_len;
+};
+
+static inline u32 pch_udc_readl(struct pch_udc_dev *dev, unsigned long reg)
+{
+	return ioread32(dev->base_addr + reg);
+}
+
+static inline void pch_udc_writel(struct pch_udc_dev *dev,
+				    unsigned long val, unsigned long reg)
+{
+	iowrite32(val, dev->base_addr + reg);
+}
+
+static inline void pch_udc_bit_set(struct pch_udc_dev *dev,
+				     unsigned long reg,
+				     unsigned long bitmask)
+{
+	pch_udc_writel(dev, pch_udc_readl(dev, reg) | bitmask, reg);
+}
+
+static inline void pch_udc_bit_clr(struct pch_udc_dev *dev,
+				     unsigned long reg,
+				     unsigned long bitmask)
+{
+	pch_udc_writel(dev, pch_udc_readl(dev, reg) & ~(bitmask), reg);
+}
+
+static inline u32 pch_udc_ep_readl(struct pch_udc_ep *ep, unsigned long reg)
+{
+	return ioread32(ep->dev->base_addr + ep->offset_addr + reg);
+}
+
+static inline void pch_udc_ep_writel(struct pch_udc_ep *ep,
+				    unsigned long val, unsigned long reg)
+{
+	iowrite32(val, ep->dev->base_addr + ep->offset_addr + reg);
+}
+
+static inline void pch_udc_ep_bit_set(struct pch_udc_ep *ep,
+				     unsigned long reg,
+				     unsigned long bitmask)
+{
+	pch_udc_ep_writel(ep, pch_udc_ep_readl(ep, reg) | bitmask, reg);
+}
+
+static inline void pch_udc_ep_bit_clr(struct pch_udc_ep *ep,
+				     unsigned long reg,
+				     unsigned long bitmask)
+{
+	pch_udc_ep_writel(ep, pch_udc_ep_readl(ep, reg) & ~(bitmask), reg);
+}
+
+/**
+ * pch_udc_csr_busy() - Wait till idle.
+ * @dev:	Reference to pch_udc_dev structure
+ */
+static void pch_udc_csr_busy(struct pch_udc_dev *dev)
+{
+	unsigned int count = 200;
+
+	/* Wait till idle */
+	while ((pch_udc_readl(dev, UDC_CSR_BUSY_ADDR) & UDC_CSR_BUSY)
+		&& --count)
+		cpu_relax();
+	if (!count)
+		dev_err(&dev->pdev->dev, "%s: wait error\n", __func__);
+}
+
+/**
+ * pch_udc_write_csr() - Write the command and status registers.
+ * @dev:	Reference to pch_udc_dev structure
+ * @val:	value to be written to CSR register
+ * @addr:	address of CSR register
+ */
+static void pch_udc_write_csr(struct pch_udc_dev *dev, unsigned long val,
+			       unsigned int ep)
+{
+	unsigned long reg = PCH_UDC_CSR(ep);
+
+	pch_udc_csr_busy(dev);		/* Wait till idle */
+	pch_udc_writel(dev, val, reg);
+	pch_udc_csr_busy(dev);		/* Wait till idle */
+}
+
+/**
+ * pch_udc_read_csr() - Read the command and status registers.
+ * @dev:	Reference to pch_udc_dev structure
+ * @addr:	address of CSR register
+ *
+ * Return codes:	content of CSR register
+ */
+static u32 pch_udc_read_csr(struct pch_udc_dev *dev, unsigned int ep)
+{
+	unsigned long reg = PCH_UDC_CSR(ep);
+
+	pch_udc_csr_busy(dev);		/* Wait till idle */
+	pch_udc_readl(dev, reg);	/* Dummy read */
+	pch_udc_csr_busy(dev);		/* Wait till idle */
+	return pch_udc_readl(dev, reg);
+}
+
+/**
+ * pch_udc_rmt_wakeup() - Initiate for remote wakeup
+ * @dev:	Reference to pch_udc_dev structure
+ */
+static inline void pch_udc_rmt_wakeup(struct pch_udc_dev *dev)
+{
+	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+	mdelay(1);
+	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
+/**
+ * pch_udc_get_frame() - Get the current frame from device status register
+ * @dev:	Reference to pch_udc_dev structure
+ * Retern	current frame
+ */
+static inline int pch_udc_get_frame(struct pch_udc_dev *dev)
+{
+	u32 frame = pch_udc_readl(dev, UDC_DEVSTS_ADDR);
+	return (frame & UDC_DEVSTS_TS_MASK) >> UDC_DEVSTS_TS_SHIFT;
+}
+
+/**
+ * pch_udc_clear_selfpowered() - Clear the self power control
+ * @dev:	Reference to pch_udc_regs structure
+ */
+static inline void pch_udc_clear_selfpowered(struct pch_udc_dev *dev)
+{
+	pch_udc_bit_clr(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_SP);
+}
+
+/**
+ * pch_udc_set_selfpowered() - Set the self power control
+ * @dev:	Reference to pch_udc_regs structure
+ */
+static inline void pch_udc_set_selfpowered(struct pch_udc_dev *dev)
+{
+	pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_SP);
+}
+
+/**
+ * pch_udc_set_disconnect() - Set the disconnect status.
+ * @dev:	Reference to pch_udc_regs structure
+ */
+static inline void pch_udc_set_disconnect(struct pch_udc_dev *dev)
+{
+	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+}
+
+/**
+ * pch_udc_clear_disconnect() - Clear the disconnect status.
+ * @dev:	Reference to pch_udc_regs structure
+ */
+static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
+{
+	/* Clear the disconnect */
+	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+	mdelay(1);
+	/* Resume USB signalling */
+	pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
+/**
+ * pch_udc_vbus_session() - set or clearr the disconnect status.
+ * @dev:	Reference to pch_udc_regs structure
+ * @is_active:	Parameter specifying the action
+ *		  0:   indicating VBUS power is ending
+ *		  !0:  indicating VBUS power is starting
+ */
+static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
+					  int is_active)
+{
+	if (is_active)
+		pch_udc_clear_disconnect(dev);
+	else
+		pch_udc_set_disconnect(dev);
+}
+
+/**
+ * pch_udc_ep_set_stall() - Set the stall of endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ */
+static void pch_udc_ep_set_stall(struct pch_udc_ep *ep)
+{
+	if (ep->in) {
+		pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_F);
+		pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
+	} else {
+		pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
+	}
+}
+
+/**
+ * pch_udc_ep_clear_stall() - Clear the stall of endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_clear_stall(struct pch_udc_ep *ep)
+{
+	/* Clear the stall */
+	pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_S);
+	/* Clear NAK by writing CNAK */
+	pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_CNAK);
+}
+
+/**
+ * pch_udc_ep_set_trfr_type() - Set the transfer type of endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * @type:	Type of endpoint
+ */
+static inline void pch_udc_ep_set_trfr_type(struct pch_udc_ep *ep,
+					u8 type)
+{
+	pch_udc_ep_writel(ep, ((type << UDC_EPCTL_ET_SHIFT) &
+				UDC_EPCTL_ET_MASK), UDC_EPCTL_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_bufsz() - Set the maximum packet size for the endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * @buf_size:	The buffer size
+ */
+static void pch_udc_ep_set_bufsz(struct pch_udc_ep *ep,
+						 u32 buf_size, u32 ep_in)
+{
+	u32 data;
+	if (ep_in) {
+		data = pch_udc_ep_readl(ep, UDC_BUFIN_FRAMENUM_ADDR);
+		data = (data & 0xffff0000) | (buf_size & 0xffff);
+		pch_udc_ep_writel(ep, data, UDC_BUFIN_FRAMENUM_ADDR);
+	} else {
+		data = pch_udc_ep_readl(ep, UDC_BUFOUT_MAXPKT_ADDR);
+		data = (buf_size << 16) | (data & 0xffff);
+		pch_udc_ep_writel(ep, data, UDC_BUFOUT_MAXPKT_ADDR);
+	}
+}
+
+/**
+ * pch_udc_ep_set_maxpkt() - Set the Max packet size for the endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * @pkt_size:	The packet size
+ */
+static void pch_udc_ep_set_maxpkt(struct pch_udc_ep *ep, u32 pkt_size)
+{
+	u32 data = pch_udc_ep_readl(ep, UDC_BUFOUT_MAXPKT_ADDR);
+	data = (data & 0xffff0000) | (pkt_size & 0xffff);
+	pch_udc_ep_writel(ep, data, UDC_BUFOUT_MAXPKT_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_subptr() - Set the Setup buffer pointer for the endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * @addr:	Address of the register
+ */
+static inline void pch_udc_ep_set_subptr(struct pch_udc_ep *ep, u32 addr)
+{
+	pch_udc_ep_writel(ep, addr, UDC_SUBPTR_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_ddptr() - Set the Data descriptor pointer for the endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * @addr:	Address of the register
+ */
+static inline void pch_udc_ep_set_ddptr(struct pch_udc_ep *ep, u32 addr)
+{
+	pch_udc_ep_writel(ep, addr, UDC_DESPTR_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_pd() - Set the poll demand bit for the endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_set_pd(struct pch_udc_ep *ep)
+{
+	pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_P);
+}
+
+/**
+ * pch_udc_ep_set_rrdy() - Set the receive ready bit for the endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_set_rrdy(struct pch_udc_ep *ep)
+{
+	pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_RRDY);
+}
+
+/**
+ * pch_udc_ep_clear_rrdy() - Clear the receive ready bit for the endpoint
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_clear_rrdy(struct pch_udc_ep *ep)
+{
+	pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_RRDY);
+}
+
+/**
+ * pch_udc_set_dma() - Set the 'TDE' or RDE bit of device control
+ *			register depending on the direction specified
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @dir:	whether Tx or Rx
+ *		  DMA_DIR_RX: Receive
+ *		  DMA_DIR_TX: Transmit
+ */
+static inline void pch_udc_set_dma(struct pch_udc_dev *dev, int dir)
+{
+	if (dir == DMA_DIR_RX)
+		pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RDE);
+	else if (dir == DMA_DIR_TX)
+		pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_TDE);
+}
+
+/**
+ * pch_udc_clear_dma() - Clear the 'TDE' or RDE bit of device control
+ *				 register depending on the direction specified
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @dir:	Whether Tx or Rx
+ *		  DMA_DIR_RX: Receive
+ *		  DMA_DIR_TX: Transmit
+ */
+static inline void pch_udc_clear_dma(struct pch_udc_dev *dev, int dir)
+{
+	if (dir == DMA_DIR_RX)
+		pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RDE);
+	else if (dir == DMA_DIR_TX)
+		pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_TDE);
+}
+
+/**
+ * pch_udc_set_csr_done() - Set the device control register
+ *				CSR done field (bit 13)
+ * @dev:	reference to structure of type pch_udc_regs
+ */
+static inline void pch_udc_set_csr_done(struct pch_udc_dev *dev)
+{
+	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_CSR_DONE);
+}
+
+/**
+ * pch_udc_disable_interrupts() - Disables the specified interrupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @mask:	Mask to disable interrupts
+ */
+static inline void pch_udc_disable_interrupts(struct pch_udc_dev *dev,
+					    u32 mask)
+{
+	pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_enable_interrupts() - Enable the specified interrupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @mask:	Mask to enable interrupts
+ */
+static inline void pch_udc_enable_interrupts(struct pch_udc_dev *dev,
+					   u32 mask)
+{
+	pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_disable_ep_interrupts() - Disable endpoint interrupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @mask:	Mask to disable interrupts
+ */
+static inline void pch_udc_disable_ep_interrupts(struct pch_udc_dev *dev,
+						u32 mask)
+{
+	pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_enable_ep_interrupts() - Enable endpoint interrupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @mask:	Mask to enable interrupts
+ */
+static inline void pch_udc_enable_ep_interrupts(struct pch_udc_dev *dev,
+					      u32 mask)
+{
+	pch_udc_bit_clr(dev, UDC_EPIRQMSK_ADDR, mask);
+}
+
+/**
+ * pch_udc_read_device_interrupts() - Read the device interrupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * Retern	The device interrupts
+ */
+static inline u32 pch_udc_read_device_interrupts(struct pch_udc_dev *dev)
+{
+	return pch_udc_readl(dev, UDC_DEVIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_write_device_interrupts() - Write device interrupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @val:	The value to be written to interrupt register
+ */
+static inline void pch_udc_write_device_interrupts(struct pch_udc_dev *dev,
+						     u32 val)
+{
+	pch_udc_writel(dev, val, UDC_DEVIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_read_ep_interrupts() - Read the endpoint interrupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * Retern	The endpoint interrupt
+ */
+static inline u32 pch_udc_read_ep_interrupts(struct pch_udc_dev *dev)
+{
+	return pch_udc_readl(dev, UDC_EPIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_write_ep_interrupts() - Clear endpoint interupts
+ * @dev:	Reference to structure of type pch_udc_regs
+ * @val:	The value to be written to interrupt register
+ */
+static inline void pch_udc_write_ep_interrupts(struct pch_udc_dev *dev,
+					     u32 val)
+{
+	pch_udc_writel(dev, val, UDC_EPIRQSTS_ADDR);
+}
+
+/**
+ * pch_udc_read_device_status() - Read the device status
+ * @dev:	Reference to structure of type pch_udc_regs
+ * Retern	The device status
+ */
+static inline u32 pch_udc_read_device_status(struct pch_udc_dev *dev)
+{
+	return pch_udc_readl(dev, UDC_DEVSTS_ADDR);
+}
+
+/**
+ * pch_udc_read_ep_control() - Read the endpoint control
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * Retern	The endpoint control register value
+ */
+static inline u32 pch_udc_read_ep_control(struct pch_udc_ep *ep)
+{
+	return pch_udc_ep_readl(ep, UDC_EPCTL_ADDR);
+}
+
+/**
+ * pch_udc_clear_ep_control() - Clear the endpoint control register
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * Retern	The endpoint control register value
+ */
+static inline void pch_udc_clear_ep_control(struct pch_udc_ep *ep)
+{
+	return pch_udc_ep_writel(ep, 0, UDC_EPCTL_ADDR);
+}
+
+/**
+ * pch_udc_read_ep_status() - Read the endpoint status
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * Retern	The endpoint status
+ */
+static inline u32 pch_udc_read_ep_status(struct pch_udc_ep *ep)
+{
+	return pch_udc_ep_readl(ep, UDC_EPSTS_ADDR);
+}
+
+/**
+ * pch_udc_clear_ep_status() - Clear the endpoint status
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ * @stat:	Endpoint status
+ */
+static inline void pch_udc_clear_ep_status(struct pch_udc_ep *ep,
+					 u32 stat)
+{
+	return pch_udc_ep_writel(ep, stat, UDC_EPSTS_ADDR);
+}
+
+/**
+ * pch_udc_ep_set_nak() - Set the bit 7 (SNAK field)
+ *				of the endpoint control register
+ * @ep:		Reference to structure of type pch_udc_ep_regs
+ */
+static inline void pch_udc_ep_set_nak(struct pch_udc_ep *ep)
+{
+	pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_SNAK);
+}
+
+/**
+ * pch_udc_ep_clear_nak() - Set the bit 8 (CNAK field)
+ *				of the endpoint control register
+ * @ep:		reference to structure of type pch_udc_ep_regs
+ */
+static void pch_udc_ep_clear_nak(struct pch_udc_ep *ep)
+{
+	unsigned int loopcnt = 0;
+	struct pch_udc_dev *dev = ep->dev;
+
+	if (!(pch_udc_ep_readl(ep, UDC_EPCTL_ADDR) & UDC_EPCTL_NAK))
+		return;
+	if (!ep->in) {
+		loopcnt = 10000;
+		while (!(pch_udc_read_ep_status(ep) & UDC_EPSTS_MRXFIFO_EMP) &&
+			--loopcnt)
+			udelay(5);
+		if (!loopcnt)
+			dev_err(&dev->pdev->dev, "%s: RxFIFO not Empty\n",
+				__func__);
+	}
+	loopcnt = 10000;
+	while ((pch_udc_read_ep_control(ep) & UDC_EPCTL_NAK) && --loopcnt) {
+		pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_CNAK);
+		udelay(5);
+	}
+	if (!loopcnt)
+		dev_err(&dev->pdev->dev, "%s: Clear NAK not set for ep%d%s\n",
+			__func__, ep->num, (ep->in ? "in" : "out"));
+}
+
+/**
+ * pch_udc_ep_fifo_flush() - Flush the endpoint fifo
+ * @ep:	reference to structure of type pch_udc_ep_regs
+ * @dir:	direction of endpoint
+ *		  0:  endpoint is OUT
+ *		  !0: endpoint is IN
+ */
+static void pch_udc_ep_fifo_flush(struct pch_udc_ep *ep, int dir)
+{
+	unsigned int loopcnt = 0;
+	struct pch_udc_dev *dev = ep->dev;
+
+	if (dir) {	/* IN ep */
+		pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_F);
+		return;
+	}
+
+	if (pch_udc_read_ep_status(ep) & UDC_EPSTS_MRXFIFO_EMP)
+		return;
+	pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_MRXFLUSH);
+	/* Wait for RxFIFO Empty */
+	loopcnt = 10000;
+	while (!(pch_udc_read_ep_status(ep) & UDC_EPSTS_MRXFIFO_EMP) &&
+		--loopcnt)
+		udelay(5);
+	if (!loopcnt)
+		dev_err(&dev->pdev->dev, "RxFIFO not Empty\n");
+	pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_MRXFLUSH);
+}
+
+/**
+ * pch_udc_ep_enable() - This api enables endpoint
+ * @regs:	Reference to structure pch_udc_ep_regs
+ * @desc:	endpoint descriptor
+ */
+static void pch_udc_ep_enable(struct pch_udc_ep *ep,
+			       struct pch_udc_cfg_data *cfg,
+			       const struct usb_endpoint_descriptor *desc)
+{
+	u32 val = 0;
+	u32 buff_size = 0;
+
+	pch_udc_ep_set_trfr_type(ep, desc->bmAttributes);
+	if (ep->in)
+		buff_size = UDC_EPIN_BUFF_SIZE;
+	else
+		buff_size = UDC_EPOUT_BUFF_SIZE;
+	pch_udc_ep_set_bufsz(ep, buff_size, ep->in);
+	pch_udc_ep_set_maxpkt(ep, le16_to_cpu(desc->wMaxPacketSize));
+	pch_udc_ep_set_nak(ep);
+	pch_udc_ep_fifo_flush(ep, ep->in);
+	/* Configure the endpoint */
+	val = ep->num << UDC_CSR_NE_NUM_SHIFT | ep->in << UDC_CSR_NE_DIR_SHIFT |
+	      ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) <<
+		UDC_CSR_NE_TYPE_SHIFT) |
+	      (cfg->cur_cfg << UDC_CSR_NE_CFG_SHIFT) |
+	      (cfg->cur_intf << UDC_CSR_NE_INTF_SHIFT) |
+	      (cfg->cur_alt << UDC_CSR_NE_ALT_SHIFT) |
+	      le16_to_cpu(desc->wMaxPacketSize) << UDC_CSR_NE_MAX_PKT_SHIFT;
+
+	if (ep->in)
+		pch_udc_write_csr(ep->dev, val, UDC_EPIN_IDX(ep->num));
+	else
+		pch_udc_write_csr(ep->dev, val, UDC_EPOUT_IDX(ep->num));
+}
+
+/**
+ * pch_udc_ep_disable() - This api disables endpoint
+ * @regs:	Reference to structure pch_udc_ep_regs
+ */
+static void pch_udc_ep_disable(struct pch_udc_ep *ep)
+{
+	if (ep->in) {
+		/* flush the fifo */
+		pch_udc_ep_writel(ep, UDC_EPCTL_F, UDC_EPCTL_ADDR);
+		/* set NAK */
+		pch_udc_ep_writel(ep, UDC_EPCTL_SNAK, UDC_EPCTL_ADDR);
+		pch_udc_ep_bit_set(ep, UDC_EPSTS_ADDR, UDC_EPSTS_IN);
+	} else {
+		/* set NAK */
+		pch_udc_ep_writel(ep, UDC_EPCTL_SNAK, UDC_EPCTL_ADDR);
+	}
+	/* reset desc pointer */
+	pch_udc_ep_writel(ep, 0, UDC_DESPTR_ADDR);
+}
+
+/**
+ * pch_udc_wait_ep_stall() - Wait EP stall.
+ * @dev:	Reference to pch_udc_dev structure
+ */
+static void pch_udc_wait_ep_stall(struct pch_udc_ep *ep)
+{
+	unsigned int count = 10000;
+
+	/* Wait till idle */
+	while ((pch_udc_read_ep_control(ep) & UDC_EPCTL_S) && --count)
+		udelay(5);
+	if (!count)
+		dev_err(&ep->dev->pdev->dev, "%s: wait error\n", __func__);
+}
+
+/**
+ * pch_udc_init() - This API initializes usb device controller
+ * @dev:	Rreference to pch_udc_regs structure
+ */
+static void pch_udc_init(struct pch_udc_dev *dev)
+{
+	if (NULL == dev) {
+		pr_err("%s: Invalid address\n", __func__);
+		return;
+	}
+	/* Soft Reset and Reset PHY */
+	pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+	pch_udc_writel(dev, UDC_SRST | UDC_PSRST, UDC_SRST_ADDR);
+	mdelay(1);
+	pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+	pch_udc_writel(dev, 0x00, UDC_SRST_ADDR);
+	mdelay(1);
+	/* mask and clear all device interrupts */
+	pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, UDC_DEVINT_MSK);
+	pch_udc_bit_set(dev, UDC_DEVIRQSTS_ADDR, UDC_DEVINT_MSK);
+
+	/* mask and clear all ep interrupts */
+	pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
+	pch_udc_bit_set(dev, UDC_EPIRQSTS_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
+
+	/* enable dynamic CSR programmingi, self powered and device speed */
+	if (speed_fs)
+		pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_CSR_PRG |
+				UDC_DEVCFG_SP | UDC_DEVCFG_SPD_FS);
+	else /* defaul high speed */
+		pch_udc_bit_set(dev, UDC_DEVCFG_ADDR, UDC_DEVCFG_CSR_PRG |
+				UDC_DEVCFG_SP | UDC_DEVCFG_SPD_HS);
+	pch_udc_bit_set(dev, UDC_DEVCTL_ADDR,
+			(PCH_UDC_THLEN << UDC_DEVCTL_THLEN_SHIFT) |
+			(PCH_UDC_BRLEN << UDC_DEVCTL_BRLEN_SHIFT) |
+			UDC_DEVCTL_MODE | UDC_DEVCTL_BREN |
+			UDC_DEVCTL_THE);
+}
+
+/**
+ * pch_udc_exit() - This API exit usb device controller
+ * @dev:	Reference to pch_udc_regs structure
+ */
+static void pch_udc_exit(struct pch_udc_dev *dev)
+{
+	/* mask all device interrupts */
+	pch_udc_bit_set(dev, UDC_DEVIRQMSK_ADDR, UDC_DEVINT_MSK);
+	/* mask all ep interrupts */
+	pch_udc_bit_set(dev, UDC_EPIRQMSK_ADDR, UDC_EPINT_MSK_DISABLE_ALL);
+	/* put device in disconnected state */
+	pch_udc_set_disconnect(dev);
+}
+
+/**
+ * pch_udc_pcd_get_frame() - This API is invoked to get the current frame number
+ * @gadget:	Reference to the gadget driver
+ *
+ * Return codes:
+ *	0:		Success
+ *	-EINVAL:	If the gadget passed is NULL
+ */
+static int pch_udc_pcd_get_frame(struct usb_gadget *gadget)
+{
+	struct pch_udc_dev	*dev;
+
+	if (!gadget)
+		return -EINVAL;
+	dev = container_of(gadget, struct pch_udc_dev, gadget);
+	return pch_udc_get_frame(dev);
+}
+
+/**
+ * pch_udc_pcd_wakeup() - This API is invoked to initiate a remote wakeup
+ * @gadget:	Reference to the gadget driver
+ *
+ * Return codes:
+ *	0:		Success
+ *	-EINVAL:	If the gadget passed is NULL
+ */
+static int pch_udc_pcd_wakeup(struct usb_gadget *gadget)
+{
+	struct pch_udc_dev	*dev;
+	unsigned long		flags;
+
+	if (!gadget)
+		return -EINVAL;
+	dev = container_of(gadget, struct pch_udc_dev, gadget);
+	spin_lock_irqsave(&dev->lock, flags);
+	pch_udc_rmt_wakeup(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return 0;
+}
+
+/**
+ * pch_udc_pcd_selfpowered() - This API is invoked to specify whether the device
+ *				is self powered or not
+ * @gadget:	Reference to the gadget driver
+ * @value:	Specifies self powered or not
+ *
+ * Return codes:
+ *	0:		Success
+ *	-EINVAL:	If the gadget passed is NULL
+ */
+static int pch_udc_pcd_selfpowered(struct usb_gadget *gadget, int value)
+{
+	struct pch_udc_dev	*dev;
+
+	if (!gadget)
+		return -EINVAL;
+	dev = container_of(gadget, struct pch_udc_dev, gadget);
+	if (value)
+		pch_udc_set_selfpowered(dev);
+	else
+		pch_udc_clear_selfpowered(dev);
+	return 0;
+}
+
+/**
+ * pch_udc_pcd_pullup() - This API is invoked to make the device
+ *				visible/invisible to the host
+ * @gadget:	Reference to the gadget driver
+ * @is_on:	Specifies whether the pull up is made active or inactive
+ *
+ * Return codes:
+ *	0:		Success
+ *	-EINVAL:	If the gadget passed is NULL
+ */
+static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct pch_udc_dev	*dev;
+
+	if (!gadget)
+		return -EINVAL;
+	dev = container_of(gadget, struct pch_udc_dev, gadget);
+	pch_udc_vbus_session(dev, is_on);
+	return 0;
+}
+
+/**
+ * pch_udc_pcd_vbus_session() - This API is used by a driver for an external
+ *				transceiver (or GPIO) that
+ *				detects a VBUS power session starting/ending
+ * @gadget:	Reference to the gadget driver
+ * @is_active:	specifies whether the session is starting or ending
+ *
+ * Return codes:
+ *	0:		Success
+ *	-EINVAL:	If the gadget passed is NULL
+ */
+static int pch_udc_pcd_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+	struct pch_udc_dev	*dev;
+
+	if (!gadget)
+		return -EINVAL;
+	dev = container_of(gadget, struct pch_udc_dev, gadget);
+	pch_udc_vbus_session(dev, is_active);
+	return 0;
+}
+
+/**
+ * pch_udc_pcd_vbus_draw() - This API is used by gadget drivers during
+ *				SET_CONFIGURATION calls to
+ *				specify how much power the device can consume
+ * @gadget:	Reference to the gadget driver
+ * @mA:		specifies the current limit in 2mA unit
+ *
+ * Return codes:
+ *	-EINVAL:	If the gadget passed is NULL
+ *	-EOPNOTSUPP:
+ */
+static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
+{
+	return -EOPNOTSUPP;
+}
+
+static const struct usb_gadget_ops pch_udc_ops = {
+	.get_frame = pch_udc_pcd_get_frame,
+	.wakeup = pch_udc_pcd_wakeup,
+	.set_selfpowered = pch_udc_pcd_selfpowered,
+	.pullup = pch_udc_pcd_pullup,
+	.vbus_session = pch_udc_pcd_vbus_session,
+	.vbus_draw = pch_udc_pcd_vbus_draw,
+};
+
+/**
+ * complete_req() - This API is invoked from the driver when processing
+ *			of a request is complete
+ * @ep:		Reference to the endpoint structure
+ * @req:	Reference to the request structure
+ * @status:	Indicates the success/failure of completion
+ */
+static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
+								 int status)
+{
+	struct pch_udc_dev	*dev;
+	unsigned halted = ep->halted;
+
+	list_del_init(&req->queue);
+
+	/* set new status if pending */
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	dev = ep->dev;
+	if (req->dma_mapped) {
+		if (ep->in)
+			pci_unmap_single(dev->pdev, req->req.dma,
+					 req->req.length, PCI_DMA_TODEVICE);
+		else
+			pci_unmap_single(dev->pdev, req->req.dma,
+					 req->req.length, PCI_DMA_FROMDEVICE);
+		req->dma_mapped = 0;
+		req->req.dma = DMA_ADDR_INVALID;
+	}
+	ep->halted = 1;
+	spin_unlock(&dev->lock);
+	if (!ep->in)
+		pch_udc_ep_clear_rrdy(ep);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&dev->lock);
+	ep->halted = halted;
+}
+
+/**
+ * empty_req_queue() - This API empties the request queue of an endpoint
+ * @ep:		Reference to the endpoint structure
+ */
+static void empty_req_queue(struct pch_udc_ep *ep)
+{
+	struct pch_udc_request	*req;
+
+	ep->halted = 1;
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+		complete_req(ep, req, -ESHUTDOWN);	/* Remove from list */
+	}
+}
+
+/**
+ * pch_udc_free_dma_chain() - This function frees the DMA chain created
+ *				for the request
+ * @dev		Reference to the driver structure
+ * @req		Reference to the request to be freed
+ *
+ * Return codes:
+ *	0: Success
+ */
+static void pch_udc_free_dma_chain(struct pch_udc_dev *dev,
+				   struct pch_udc_request *req)
+{
+	struct pch_udc_data_dma_desc *td = req->td_data;
+	unsigned i = req->chain_len;
+
+	for (; i > 1; --i) {
+		dma_addr_t addr = (dma_addr_t)td->next;
+		/* do not free first desc., will be done by free for request */
+		td = phys_to_virt(addr);
+		pci_pool_free(dev->data_requests, td, addr);
+	}
+}
+
+/**
+ * pch_udc_create_dma_chain() - This function creates or reinitializes
+ *				a DMA chain
+ * @ep:		Reference to the endpoint structure
+ * @req:	Reference to the request
+ * @buf_len:	The buffer length
+ * @gfp_flags:	Flags to be used while mapping the data buffer
+ *
+ * Return codes:
+ *	0:		success,
+ *	-ENOMEM:	pci_pool_alloc invocation fails
+ */
+static int pch_udc_create_dma_chain(struct pch_udc_ep *ep,
+				    struct pch_udc_request *req,
+				    unsigned long buf_len,
+				    gfp_t gfp_flags)
+{
+	struct pch_udc_data_dma_desc *td = req->td_data, *last;
+	unsigned long bytes = req->req.length, i = 0;
+	dma_addr_t dma_addr;
+	unsigned len = 1;
+
+	if (req->chain_len > 1)
+		pch_udc_free_dma_chain(ep->dev, req);
+
+	for (; ; bytes -= buf_len, ++len) {
+		if (ep->in)
+			td->status = PCH_UDC_BS_HST_BSY | min(buf_len, bytes);
+		else
+			td->status = PCH_UDC_BS_HST_BSY;
+
+		if (bytes <= buf_len)
+			break;
+
+		last = td;
+		td = pci_pool_alloc(ep->dev->data_requests, gfp_flags,
+				    &dma_addr);
+		if (!td)
+			goto nomem;
+
+		i += buf_len;
+		td->dataptr = req->req.dma + i;
+		last->next = dma_addr;
+	}
+
+	req->td_data_last = td;
+	td->status |= PCH_UDC_DMA_LAST;
+	td->next = req->td_data_phys;
+	req->chain_len = len;
+	return 0;
+
+nomem:
+	if (len > 1) {
+		req->chain_len = len;
+		pch_udc_free_dma_chain(ep->dev, req);
+	}
+	req->chain_len = 1;
+	return -ENOMEM;
+}
+
+/**
+ * prepare_dma() - This function creates and initializes the DMA chain
+ *			for the request
+ * @ep:		Reference to the endpoint structure
+ * @req:	Reference to the request
+ * @gfp:	Flag to be used while mapping the data buffer
+ *
+ * Return codes:
+ *	0:		Success
+ *	Other 0:	linux error number on failure
+ */
+static int prepare_dma(struct pch_udc_ep *ep, struct pch_udc_request *req,
+			  gfp_t gfp)
+{
+	int	retval;
+
+	req->td_data->dataptr = req->req.dma;
+	req->td_data->status |= PCH_UDC_DMA_LAST;
+	/* Allocate and create a DMA chain */
+	retval = pch_udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
+	if (retval) {
+		pr_err("%s: could not create DMA chain: %d\n",
+		       __func__, retval);
+		return retval;
+	}
+	if (!ep->in)
+		return 0;
+	if (req->req.length <= ep->ep.maxpacket)
+		req->td_data->status = PCH_UDC_DMA_LAST | PCH_UDC_BS_HST_BSY |
+				       req->req.length;
+	/* if bytes < max packet then tx bytes must
+	 * be written in packet per buffer mode
+	 */
+	if ((req->req.length < ep->ep.maxpacket) || !ep->num)
+		req->td_data->status = (req->td_data->status &
+					~PCH_UDC_RXTX_BYTES) | req->req.length;
+	req->td_data->status = (req->td_data->status &
+				~PCH_UDC_BUFF_STS) | PCH_UDC_BS_HST_BSY;
+	return 0;
+}
+
+/**
+ * process_zlp() - This function process zero length packets
+ *			from the gadget driver
+ * @ep:		Reference to the endpoint structure
+ * @req:	Reference to the request
+ */
+static void process_zlp(struct pch_udc_ep *ep, struct pch_udc_request *req)
+{
+	struct pch_udc_dev	*dev = ep->dev;
+
+	/* IN zlp's are handled by hardware */
+	complete_req(ep, req, 0);
+
+	/* if set_config or set_intf is waiting for ack by zlp
+	 * then set CSR_DONE
+	 */
+	if (dev->set_cfg_not_acked) {
+		pch_udc_set_csr_done(dev);
+		dev->set_cfg_not_acked = 0;
+	}
+	/* setup command is ACK'ed now by zlp */
+	if (!dev->stall && dev->waiting_zlp_ack) {
+		pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
+		dev->waiting_zlp_ack = 0;
+	}
+}
+
+/**
+ * pch_udc_start_rxrequest() - This function starts the receive requirement.
+ * @ep:		Reference to the endpoint structure
+ * @req:	Reference to the request structure
+ */
+static void pch_udc_start_rxrequest(struct pch_udc_ep *ep,
+					 struct pch_udc_request *req)
+{
+	struct pch_udc_data_dma_desc *td_data;
+
+	pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
+	td_data = req->td_data;
+	ep->td_data = req->td_data;
+	/* Set the status bits for all descriptors */
+	while (1) {
+		td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
+				    PCH_UDC_BS_HST_RDY;
+		if ((td_data->status & PCH_UDC_DMA_LAST) ==  PCH_UDC_DMA_LAST)
+			break;
+		td_data = phys_to_virt(td_data->next);
+	}
+	/* Write the descriptor pointer */
+	pch_udc_ep_set_ddptr(ep, req->td_data_phys);
+	req->dma_going = 1;
+	pch_udc_enable_ep_interrupts(ep->dev, UDC_EPINT_OUT_EP0 << ep->num);
+	pch_udc_set_dma(ep->dev, DMA_DIR_RX);
+	pch_udc_ep_clear_nak(ep);
+	pch_udc_ep_set_rrdy(ep);
+}
+
+/**
+ * pch_udc_pcd_ep_enable() - This API enables the endpoint. It is called
+ *				from gadget driver
+ * @usbep:	Reference to the USB endpoint structure
+ * @desc:	Reference to the USB endpoint descriptor structure
+ *
+ * Return codes:
+ *	0:		Success
+ *	-EINVAL:
+ *	-ESHUTDOWN:
+ */
+static int pch_udc_pcd_ep_enable(struct usb_ep *usbep,
+				    const struct usb_endpoint_descriptor *desc)
+{
+	struct pch_udc_ep	*ep;
+	struct pch_udc_dev	*dev;
+	unsigned long		iflags;
+
+	if (!usbep || (usbep->name == ep0_string) || !desc ||
+	    (desc->bDescriptorType != USB_DT_ENDPOINT) || !desc->wMaxPacketSize)
+		return -EINVAL;
+
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	dev = ep->dev;
+	if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
+		return -ESHUTDOWN;
+	spin_lock_irqsave(&dev->lock, iflags);
+	ep->desc = desc;
+	ep->halted = 0;
+	pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc);
+	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+	pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
+	spin_unlock_irqrestore(&dev->lock, iflags);
+	return 0;
+}
+
+/**
+ * pch_udc_pcd_ep_disable() - This API disables endpoint and is called
+ *				from gadget driver
+ * @usbep	Reference to the USB endpoint structure
+ *
+ * Return codes:
+ *	0:		Success
+ *	-EINVAL:
+ */
+static int pch_udc_pcd_ep_disable(struct usb_ep *usbep)
+{
+	struct pch_udc_ep	*ep;
+	struct pch_udc_dev	*dev;
+	unsigned long	iflags;
+
+	if (!usbep)
+		return -EINVAL;
+
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	dev = ep->dev;
+	if ((usbep->name == ep0_string) || !ep->desc)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, iflags);
+	empty_req_queue(ep);
+	ep->halted = 1;
+	pch_udc_ep_disable(ep);
+	pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
+	ep->desc = NULL;
+	INIT_LIST_HEAD(&ep->queue);
+	spin_unlock_irqrestore(&ep->dev->lock, iflags);
+	return 0;
+}
+
+/**
+ * pch_udc_alloc_request() - This function allocates request structure.
+ *				It is called by gadget driver
+ * @usbep:	Reference to the USB endpoint structure
+ * @gfp:	Flag to be used while allocating memory
+ *
+ * Return codes:
+ *	NULL:			Failure
+ *	Allocated address:	Success
+ */
+static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
+						  gfp_t gfp)
+{
+	struct pch_udc_request		*req;
+	struct pch_udc_ep		*ep;
+	struct pch_udc_data_dma_desc	*dma_desc;
+	struct pch_udc_dev		*dev;
+
+	if (!usbep)
+		return NULL;
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	dev = ep->dev;
+	req = kzalloc(sizeof *req, gfp);
+	if (!req)
+		return NULL;
+	req->req.dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD(&req->queue);
+	if (!ep->dev->dma_addr)
+		return &req->req;
+	/* ep0 in requests are allocated from data pool here */
+	dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp,
+				  &req->td_data_phys);
+	if (NULL == dma_desc) {
+		kfree(req);
+		return NULL;
+	}
+	/* prevent from using desc. - set HOST BUSY */
+	dma_desc->status |= PCH_UDC_BS_HST_BSY;
+	dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
+	req->td_data = dma_desc;
+	req->td_data_last = dma_desc;
+	req->chain_len = 1;
+	return &req->req;
+}
+
+/**
+ * pch_udc_free_request() - This function frees request structure.
+ *				It is called by gadget driver
+ * @usbep:	Reference to the USB endpoint structure
+ * @usbreq:	Reference to the USB request
+ */
+static void pch_udc_free_request(struct usb_ep *usbep,
+				  struct usb_request *usbreq)
+{
+	struct pch_udc_ep	*ep;
+	struct pch_udc_request	*req;
+	struct pch_udc_dev	*dev;
+
+	if (!usbep || !usbreq)
+		return;
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	req = container_of(usbreq, struct pch_udc_request, req);
+	dev = ep->dev;
+	if (!list_empty(&req->queue))
+		dev_err(&dev->pdev->dev, "%s: %s req=0x%p queue not empty\n",
+			__func__, usbep->name, req);
+	if (req->td_data != NULL) {
+		if (req->chain_len > 1)
+			pch_udc_free_dma_chain(ep->dev, req);
+		pci_pool_free(ep->dev->data_requests, req->td_data,
+			      req->td_data_phys);
+	}
+	kfree(req);
+}
+
+/**
+ * pch_udc_pcd_queue() - This function queues a request packet. It is called
+ *			by gadget driver
+ * @usbep:	Reference to the USB endpoint structure
+ * @usbreq:	Reference to the USB request
+ * @gfp:	Flag to be used while mapping the data buffer
+ *
+ * Return codes:
+ *	0:			Success
+ *	linux error number:	Failure
+ */
+static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
+								 gfp_t gfp)
+{
+	int retval = 0;
+	struct pch_udc_ep	*ep;
+	struct pch_udc_dev	*dev;
+	struct pch_udc_request	*req;
+	unsigned long	iflags;
+
+	if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf)
+		return -EINVAL;
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	dev = ep->dev;
+	if (!ep->desc && ep->num)
+		return -EINVAL;
+	req = container_of(usbreq, struct pch_udc_request, req);
+	if (!list_empty(&req->queue))
+		return -EINVAL;
+	if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
+		return -ESHUTDOWN;
+	spin_lock_irqsave(&ep->dev->lock, iflags);
+	/* map the buffer for dma */
+	if (usbreq->length &&
+	    ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) {
+		if (ep->in)
+			usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
+					usbreq->length, PCI_DMA_TODEVICE);
+		else
+			usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
+					usbreq->length, PCI_DMA_FROMDEVICE);
+		req->dma_mapped = 1;
+	}
+	if (usbreq->length > 0) {
+		retval = prepare_dma(ep, req, gfp);
+		if (retval)
+			goto probe_end;
+	}
+	usbreq->actual = 0;
+	usbreq->status = -EINPROGRESS;
+	req->dma_done = 0;
+	if (list_empty(&ep->queue) && !ep->halted) {
+		/* no pending transfer, so start this req */
+		if (!usbreq->length) {
+			process_zlp(ep, req);
+			retval = 0;
+			goto probe_end;
+		}
+		if (!ep->in) {
+			pch_udc_start_rxrequest(ep, req);
+		} else {
+			/*
+			* For IN trfr the descriptors will be programmed and
+			* P bit will be set when
+			* we get an IN token
+			*/
+			pch_udc_wait_ep_stall(ep);
+			pch_udc_ep_clear_nak(ep);
+			pch_udc_enable_ep_interrupts(ep->dev, (1 << ep->num));
+			pch_udc_set_dma(dev, DMA_DIR_TX);
+		}
+	}
+	/* Now add this request to the ep's pending requests */
+	if (req != NULL)
+		list_add_tail(&req->queue, &ep->queue);
+
+probe_end:
+	spin_unlock_irqrestore(&dev->lock, iflags);
+	return retval;
+}
+
+/**
+ * pch_udc_pcd_dequeue() - This function de-queues a request packet.
+ *				It is called by gadget driver
+ * @usbep:	Reference to the USB endpoint structure
+ * @usbreq:	Reference to the USB request
+ *
+ * Return codes:
+ *	0:			Success
+ *	linux error number:	Failure
+ */
+static int pch_udc_pcd_dequeue(struct usb_ep *usbep,
+				struct usb_request *usbreq)
+{
+	struct pch_udc_ep	*ep;
+	struct pch_udc_request	*req;
+	struct pch_udc_dev	*dev;
+	unsigned long		flags;
+	int ret = -EINVAL;
+
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	dev = ep->dev;
+	if (!usbep || !usbreq || (!ep->desc && ep->num))
+		return ret;
+	req = container_of(usbreq, struct pch_udc_request, req);
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	/* make sure it's still queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == usbreq) {
+			pch_udc_ep_set_nak(ep);
+			if (!list_empty(&req->queue))
+				complete_req(ep, req, -ECONNRESET);
+			ret = 0;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+	return ret;
+}
+
+/**
+ * pch_udc_pcd_set_halt() - This function Sets or clear the endpoint halt
+ *			    feature
+ * @usbep:	Reference to the USB endpoint structure
+ * @halt:	Specifies whether to set or clear the feature
+ *
+ * Return codes:
+ *	0:			Success
+ *	linux error number:	Failure
+ */
+static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt)
+{
+	struct pch_udc_ep	*ep;
+	struct pch_udc_dev	*dev;
+	unsigned long iflags;
+	int ret;
+
+	if (!usbep)
+		return -EINVAL;
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	dev = ep->dev;
+	if (!ep->desc && !ep->num)
+		return -EINVAL;
+	if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
+		return -ESHUTDOWN;
+	spin_lock_irqsave(&udc_stall_spinlock, iflags);
+	if (list_empty(&ep->queue)) {
+		if (halt) {
+			if (ep->num == PCH_UDC_EP0)
+				ep->dev->stall = 1;
+			pch_udc_ep_set_stall(ep);
+			pch_udc_enable_ep_interrupts(ep->dev,
+						     PCH_UDC_EPINT(ep->in,
+								   ep->num));
+		} else {
+			pch_udc_ep_clear_stall(ep);
+		}
+		ret = 0;
+	} else {
+		ret = -EAGAIN;
+	}
+	spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+	return ret;
+}
+
+/**
+ * pch_udc_pcd_set_wedge() - This function Sets or clear the endpoint
+ *				halt feature
+ * @usbep:	Reference to the USB endpoint structure
+ * @halt:	Specifies whether to set or clear the feature
+ *
+ * Return codes:
+ *	0:			Success
+ *	linux error number:	Failure
+ */
+static int pch_udc_pcd_set_wedge(struct usb_ep *usbep)
+{
+	struct pch_udc_ep	*ep;
+	struct pch_udc_dev	*dev;
+	unsigned long iflags;
+	int ret;
+
+	if (!usbep)
+		return -EINVAL;
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	dev = ep->dev;
+	if (!ep->desc && !ep->num)
+		return -EINVAL;
+	if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN))
+		return -ESHUTDOWN;
+	spin_lock_irqsave(&udc_stall_spinlock, iflags);
+	if (!list_empty(&ep->queue)) {
+		ret = -EAGAIN;
+	} else {
+		if (ep->num == PCH_UDC_EP0)
+			ep->dev->stall = 1;
+		pch_udc_ep_set_stall(ep);
+		pch_udc_enable_ep_interrupts(ep->dev,
+					     PCH_UDC_EPINT(ep->in, ep->num));
+		ep->dev->prot_stall = 1;
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+	return ret;
+}
+
+/**
+ * pch_udc_pcd_fifo_flush() - This function Flush the FIFO of specified endpoint
+ * @usbep:	Reference to the USB endpoint structure
+ */
+static void pch_udc_pcd_fifo_flush(struct usb_ep *usbep)
+{
+	struct pch_udc_ep  *ep;
+
+	if (!usbep)
+		return;
+
+	ep = container_of(usbep, struct pch_udc_ep, ep);
+	if (ep->desc || !ep->num)
+		pch_udc_ep_fifo_flush(ep, ep->in);
+}
+
+static const struct usb_ep_ops pch_udc_ep_ops = {
+	.enable		= pch_udc_pcd_ep_enable,
+	.disable	= pch_udc_pcd_ep_disable,
+	.alloc_request	= pch_udc_alloc_request,
+	.free_request	= pch_udc_free_request,
+	.queue		= pch_udc_pcd_queue,
+	.dequeue	= pch_udc_pcd_dequeue,
+	.set_halt	= pch_udc_pcd_set_halt,
+	.set_wedge	= pch_udc_pcd_set_wedge,
+	.fifo_status	= NULL,
+	.fifo_flush	= pch_udc_pcd_fifo_flush,
+};
+
+/**
+ * pch_udc_init_setup_buff() - This function initializes the SETUP buffer
+ * @td_stp:	Reference to the SETP buffer structure
+ */
+static void pch_udc_init_setup_buff(struct pch_udc_stp_dma_desc *td_stp)
+{
+	static u32	pky_marker;
+
+	if (!td_stp)
+		return;
+	td_stp->reserved = ++pky_marker;
+	memset(&td_stp->request, 0xFF, sizeof td_stp->request);
+	td_stp->status = PCH_UDC_BS_HST_RDY;
+}
+
+/**
+ * pch_udc_start_next_txrequest() - This function starts
+ *					the next transmission requirement
+ * @ep:	Reference to the endpoint structure
+ */
+static void pch_udc_start_next_txrequest(struct pch_udc_ep *ep)
+{
+	struct pch_udc_request *req;
+	struct pch_udc_data_dma_desc *td_data;
+
+	if (pch_udc_read_ep_control(ep) & UDC_EPCTL_P)
+		return;
+
+	if (list_empty(&ep->queue))
+		return;
+
+	/* next request */
+	req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+	if (req->dma_going)
+		return;
+	if (!req->td_data)
+		return;
+	pch_udc_wait_ep_stall(ep);
+	req->dma_going = 1;
+	pch_udc_ep_set_ddptr(ep, 0);
+	td_data = req->td_data;
+	while (1) {
+		td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
+				   PCH_UDC_BS_HST_RDY;
+		if ((td_data->status & PCH_UDC_DMA_LAST) == PCH_UDC_DMA_LAST)
+			break;
+		td_data = phys_to_virt(td_data->next);
+	}
+	pch_udc_ep_set_ddptr(ep, req->td_data_phys);
+	pch_udc_set_dma(ep->dev, DMA_DIR_TX);
+	pch_udc_ep_set_pd(ep);
+	pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
+	pch_udc_ep_clear_nak(ep);
+}
+
+/**
+ * pch_udc_complete_transfer() - This function completes a transfer
+ * @ep:		Reference to the endpoint structure
+ */
+static void pch_udc_complete_transfer(struct pch_udc_ep *ep)
+{
+	struct pch_udc_request *req;
+	struct pch_udc_dev *dev = ep->dev;
+
+	if (list_empty(&ep->queue))
+		return;
+	req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+	if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
+	    PCH_UDC_BS_DMA_DONE)
+		return;
+	if ((req->td_data_last->status & PCH_UDC_RXTX_STS) !=
+	     PCH_UDC_RTS_SUCC) {
+		dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) "
+			"epstatus=0x%08x\n",
+		       (req->td_data_last->status & PCH_UDC_RXTX_STS),
+		       (int)(ep->epsts));
+		return;
+	}
+
+	req->req.actual = req->req.length;
+	req->td_data_last->status = PCH_UDC_BS_HST_BSY | PCH_UDC_DMA_LAST;
+	req->td_data->status = PCH_UDC_BS_HST_BSY | PCH_UDC_DMA_LAST;
+	complete_req(ep, req, 0);
+	req->dma_going = 0;
+	if (!list_empty(&ep->queue)) {
+		pch_udc_wait_ep_stall(ep);
+		pch_udc_ep_clear_nak(ep);
+		pch_udc_enable_ep_interrupts(ep->dev,
+					     PCH_UDC_EPINT(ep->in, ep->num));
+	} else {
+		pch_udc_disable_ep_interrupts(ep->dev,
+					      PCH_UDC_EPINT(ep->in, ep->num));
+	}
+}
+
+/**
+ * pch_udc_complete_receiver() - This function completes a receiver
+ * @ep:		Reference to the endpoint structure
+ */
+static void pch_udc_complete_receiver(struct pch_udc_ep *ep)
+{
+	struct pch_udc_request *req;
+	struct pch_udc_dev *dev = ep->dev;
+	unsigned int count;
+
+	if (list_empty(&ep->queue))
+		return;
+
+	/* next request */
+	req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+	if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
+	    PCH_UDC_BS_DMA_DONE)
+		return;
+	pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
+	if ((req->td_data_last->status & PCH_UDC_RXTX_STS) !=
+	    PCH_UDC_RTS_SUCC) {
+		dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) "
+			"epstatus=0x%08x\n",
+			(req->td_data_last->status & PCH_UDC_RXTX_STS),
+			(int)(ep->epsts));
+		return;
+	}
+	count = req->td_data_last->status & PCH_UDC_RXTX_BYTES;
+
+	/* on 64k packets the RXBYTES field is zero */
+	if (!count && (req->req.length == UDC_DMA_MAXPACKET))
+		count = UDC_DMA_MAXPACKET;
+	req->td_data->status |= PCH_UDC_DMA_LAST;
+	req->td_data_last->status |= PCH_UDC_BS_HST_BSY;
+
+	req->dma_going = 0;
+	req->req.actual = count;
+	complete_req(ep, req, 0);
+	/* If there is a new/failed requests try that now */
+	if (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+		pch_udc_start_rxrequest(ep, req);
+	}
+}
+
+/**
+ * pch_udc_svc_data_in() - This function process endpoint interrupts
+ *				for IN endpoints
+ * @dev:	Reference to the device structure
+ * @ep_num:	Endpoint that generated the interrupt
+ */
+static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num)
+{
+	u32	epsts;
+	struct pch_udc_ep	*ep;
+
+	ep = &dev->ep[2*ep_num];
+	epsts = ep->epsts;
+	ep->epsts = 0;
+
+	if (!(epsts & (UDC_EPSTS_IN | UDC_EPSTS_BNA  | UDC_EPSTS_HE |
+		       UDC_EPSTS_TDC | UDC_EPSTS_RCS | UDC_EPSTS_TXEMPTY |
+		       UDC_EPSTS_RSS | UDC_EPSTS_XFERDONE)))
+		return;
+	if ((epsts & UDC_EPSTS_BNA))
+		return;
+	if (epsts & UDC_EPSTS_HE)
+		return;
+	if (epsts & UDC_EPSTS_RSS) {
+		pch_udc_ep_set_stall(ep);
+		pch_udc_enable_ep_interrupts(ep->dev,
+					     PCH_UDC_EPINT(ep->in, ep->num));
+	}
+	if (epsts & UDC_EPSTS_RCS) {
+		if (!dev->prot_stall) {
+			pch_udc_ep_clear_stall(ep);
+		} else {
+			pch_udc_ep_set_stall(ep);
+			pch_udc_enable_ep_interrupts(ep->dev,
+						PCH_UDC_EPINT(ep->in, ep->num));
+		}
+	}
+	if (epsts & UDC_EPSTS_TDC)
+		pch_udc_complete_transfer(ep);
+	/* On IN interrupt, provide data if we have any */
+	if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_RSS) &&
+	    !(epsts & UDC_EPSTS_TDC) && !(epsts & UDC_EPSTS_TXEMPTY))
+		pch_udc_start_next_txrequest(ep);
+}
+
+/**
+ * pch_udc_svc_data_out() - Handles interrupts from OUT endpoint
+ * @dev:	Reference to the device structure
+ * @ep_num:	Endpoint that generated the interrupt
+ */
+static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num)
+{
+	u32			epsts;
+	struct pch_udc_ep		*ep;
+	struct pch_udc_request		*req = NULL;
+
+	ep = &dev->ep[2*ep_num + 1];
+	epsts = ep->epsts;
+	ep->epsts = 0;
+
+	if ((epsts & UDC_EPSTS_BNA) && (!list_empty(&ep->queue))) {
+		/* next request */
+		req = list_entry(ep->queue.next, struct pch_udc_request,
+				 queue);
+		if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
+		     PCH_UDC_BS_DMA_DONE) {
+			if (!req->dma_going)
+				pch_udc_start_rxrequest(ep, req);
+			return;
+		}
+	}
+	if (epsts & UDC_EPSTS_HE)
+		return;
+	if (epsts & UDC_EPSTS_RSS)
+		pch_udc_ep_set_stall(ep);
+		pch_udc_enable_ep_interrupts(ep->dev,
+					     PCH_UDC_EPINT(ep->in, ep->num));
+	if (epsts & UDC_EPSTS_RCS) {
+		if (!dev->prot_stall) {
+			pch_udc_ep_clear_stall(ep);
+		} else {
+			pch_udc_ep_set_stall(ep);
+			pch_udc_enable_ep_interrupts(ep->dev,
+						PCH_UDC_EPINT(ep->in, ep->num));
+		}
+	}
+	if (((epsts & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
+	    UDC_EPSTS_OUT_DATA) {
+		if (ep->dev->prot_stall == 1) {
+			pch_udc_ep_set_stall(ep);
+			pch_udc_enable_ep_interrupts(ep->dev,
+						PCH_UDC_EPINT(ep->in, ep->num));
+		} else {
+			pch_udc_complete_receiver(ep);
+		}
+	}
+	if (list_empty(&ep->queue))
+		pch_udc_set_dma(dev, DMA_DIR_RX);
+}
+
+/**
+ * pch_udc_svc_control_in() - Handle Control IN endpoint interrupts
+ * @dev:	Reference to the device structure
+ */
+static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
+{
+	u32	epsts;
+	struct pch_udc_ep	*ep;
+
+	ep = &dev->ep[UDC_EP0IN_IDX];
+	epsts = ep->epsts;
+	ep->epsts = 0;
+
+	if (!(epsts & (UDC_EPSTS_IN | UDC_EPSTS_BNA | UDC_EPSTS_HE |
+		       UDC_EPSTS_TDC | UDC_EPSTS_RCS | UDC_EPSTS_TXEMPTY |
+		       UDC_EPSTS_XFERDONE)))
+		return;
+	if ((epsts & UDC_EPSTS_BNA))
+		return;
+	if (epsts & UDC_EPSTS_HE)
+		return;
+	if ((epsts & UDC_EPSTS_TDC) && (!dev->stall))
+		pch_udc_complete_transfer(ep);
+	/* On IN interrupt, provide data if we have any */
+	if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_TDC) &&
+	     !(epsts & UDC_EPSTS_TXEMPTY))
+		pch_udc_start_next_txrequest(ep);
+}
+
+/**
+ * pch_udc_svc_control_out() - Routine that handle Control
+ *					OUT endpoint interrupts
+ * @dev:	Reference to the device structure
+ */
+static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
+{
+	u32	stat;
+	int setup_supported;
+	struct pch_udc_ep	*ep;
+
+	ep = &dev->ep[UDC_EP0OUT_IDX];
+	stat = ep->epsts;
+	ep->epsts = 0;
+
+	/* If setup data */
+	if (((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
+	    UDC_EPSTS_OUT_SETUP) {
+		dev->stall = 0;
+		dev->ep[UDC_EP0IN_IDX].halted = 0;
+		dev->ep[UDC_EP0OUT_IDX].halted = 0;
+		/* In data not ready */
+		pch_udc_ep_set_nak(&(dev->ep[UDC_EP0IN_IDX]));
+		dev->setup_data = ep->td_stp->request;
+		pch_udc_init_setup_buff(ep->td_stp);
+		pch_udc_clear_dma(dev, DMA_DIR_TX);
+		pch_udc_ep_fifo_flush(&(dev->ep[UDC_EP0IN_IDX]),
+				      dev->ep[UDC_EP0IN_IDX].in);
+		if ((dev->setup_data.bRequestType & USB_DIR_IN))
+			dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
+		else /* OUT */
+			dev->gadget.ep0 = &ep->ep;
+		spin_unlock(&dev->lock);
+		/* If Mass storage Reset */
+		if ((dev->setup_data.bRequestType == 0x21) &&
+		    (dev->setup_data.bRequest == 0xFF))
+			dev->prot_stall = 0;
+		/* call gadget with setup data received */
+		setup_supported = dev->driver->setup(&dev->gadget,
+						     &dev->setup_data);
+		spin_lock(&dev->lock);
+		/* ep0 in returns data on IN phase */
+		if (setup_supported >= 0 && setup_supported <
+					    UDC_EP0IN_MAX_PKT_SIZE) {
+			pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
+			/* Gadget would have queued a request when
+			 * we called the setup */
+			pch_udc_set_dma(dev, DMA_DIR_RX);
+			pch_udc_ep_clear_nak(ep);
+		} else if (setup_supported < 0) {
+			/* if unsupported request, then stall */
+			pch_udc_ep_set_stall(&(dev->ep[UDC_EP0IN_IDX]));
+			pch_udc_enable_ep_interrupts(ep->dev,
+						PCH_UDC_EPINT(ep->in, ep->num));
+			dev->stall = 0;
+			pch_udc_set_dma(dev, DMA_DIR_RX);
+		} else {
+			dev->waiting_zlp_ack = 1;
+		}
+	} else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
+		     UDC_EPSTS_OUT_DATA) && !dev->stall) {
+		if (list_empty(&ep->queue)) {
+			dev_err(&dev->pdev->dev, "%s: No request\n", __func__);
+			ep->td_data->status = (ep->td_data->status &
+					       ~PCH_UDC_BUFF_STS) |
+					       PCH_UDC_BS_HST_RDY;
+			pch_udc_set_dma(dev, DMA_DIR_RX);
+		} else {
+			/* control write */
+			/* next function will pickuo an clear the status */
+			ep->epsts = stat;
+
+			pch_udc_svc_data_out(dev, 0);
+			/* re-program desc. pointer for possible ZLPs */
+			pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
+			pch_udc_set_dma(dev, DMA_DIR_RX);
+		}
+	}
+	pch_udc_ep_set_rrdy(ep);
+}
+
+
+/**
+ * pch_udc_postsvc_epinters() - This function enables end point interrupts
+ *				and clears NAK status
+ * @dev:	Reference to the device structure
+ * @ep_num:	End point number
+ */
+static void pch_udc_postsvc_epinters(struct pch_udc_dev *dev, int ep_num)
+{
+	struct pch_udc_ep	*ep;
+	struct pch_udc_request *req;
+
+	ep = &dev->ep[2*ep_num];
+	if (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct pch_udc_request, queue);
+		pch_udc_enable_ep_interrupts(ep->dev,
+					     PCH_UDC_EPINT(ep->in, ep->num));
+		pch_udc_ep_clear_nak(ep);
+	}
+}
+
+/**
+ * pch_udc_read_all_epstatus() - This function read all endpoint status
+ * @dev:	Reference to the device structure
+ * @ep_intr:	Status of endpoint interrupt
+ */
+static void pch_udc_read_all_epstatus(struct pch_udc_dev *dev, u32 ep_intr)
+{
+	int i;
+	struct pch_udc_ep	*ep;
+
+	for (i = 0; i < PCH_UDC_USED_EP_NUM; i++) {
+		/* IN */
+		if (ep_intr & (0x1 << i)) {
+			ep = &dev->ep[2*i];
+			ep->epsts = pch_udc_read_ep_status(ep);
+			pch_udc_clear_ep_status(ep, ep->epsts);
+		}
+		/* OUT */
+		if (ep_intr & (0x10000 << i)) {
+			ep = &dev->ep[2*i+1];
+			ep->epsts = pch_udc_read_ep_status(ep);
+			pch_udc_clear_ep_status(ep, ep->epsts);
+		}
+	}
+}
+
+/**
+ * pch_udc_activate_control_ep() - This function enables the control endpoints
+ *					for traffic after a reset
+ * @dev:	Reference to the device structure
+ */
+static void pch_udc_activate_control_ep(struct pch_udc_dev *dev)
+{
+	struct pch_udc_ep	*ep;
+	u32 val;
+
+	/* Setup the IN endpoint */
+	ep = &dev->ep[UDC_EP0IN_IDX];
+	pch_udc_clear_ep_control(ep);
+	pch_udc_ep_fifo_flush(ep, ep->in);
+	pch_udc_ep_set_bufsz(ep, UDC_EP0IN_BUFF_SIZE, ep->in);
+	pch_udc_ep_set_maxpkt(ep, UDC_EP0IN_MAX_PKT_SIZE);
+	/* Initialize the IN EP Descriptor */
+	ep->td_data      = NULL;
+	ep->td_stp       = NULL;
+	ep->td_data_phys = 0;
+	ep->td_stp_phys  = 0;
+
+	/* Setup the OUT endpoint */
+	ep = &dev->ep[UDC_EP0OUT_IDX];
+	pch_udc_clear_ep_control(ep);
+	pch_udc_ep_fifo_flush(ep, ep->in);
+	pch_udc_ep_set_bufsz(ep, UDC_EP0OUT_BUFF_SIZE, ep->in);
+	pch_udc_ep_set_maxpkt(ep, UDC_EP0OUT_MAX_PKT_SIZE);
+	val = UDC_EP0OUT_MAX_PKT_SIZE << UDC_CSR_NE_MAX_PKT_SHIFT;
+	pch_udc_write_csr(ep->dev, val, UDC_EP0OUT_IDX);
+
+	/* Initialize the SETUP buffer */
+	pch_udc_init_setup_buff(ep->td_stp);
+	/* Write the pointer address of dma descriptor */
+	pch_udc_ep_set_subptr(ep, ep->td_stp_phys);
+	/* Write the pointer address of Setup descriptor */
+	pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
+
+	/* Initialize the dma descriptor */
+	ep->td_data->status  = PCH_UDC_DMA_LAST;
+	ep->td_data->dataptr = dev->dma_addr;
+	ep->td_data->next    = ep->td_data_phys;
+
+	pch_udc_ep_clear_nak(ep);
+}
+
+
+/**
+ * pch_udc_svc_ur_interrupt() - This function handles a USB reset interrupt
+ * @dev:	Reference to driver structure
+ */
+static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
+{
+	struct pch_udc_ep	*ep;
+	int i;
+
+	pch_udc_clear_dma(dev, DMA_DIR_TX);
+	pch_udc_clear_dma(dev, DMA_DIR_RX);
+	/* Mask all endpoint interrupts */
+	pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+	/* clear all endpoint interrupts */
+	pch_udc_write_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+
+	for (i = 0; i < PCH_UDC_EP_NUM; i++) {
+		ep = &dev->ep[i];
+		pch_udc_clear_ep_status(ep, UDC_EPSTS_ALL_CLR_MASK);
+		pch_udc_clear_ep_control(ep);
+		pch_udc_ep_set_ddptr(ep, 0);
+		pch_udc_write_csr(ep->dev, 0x00, i);
+	}
+	dev->stall = 0;
+	dev->prot_stall = 0;
+	dev->waiting_zlp_ack = 0;
+	dev->set_cfg_not_acked = 0;
+
+	/* disable ep to empty req queue. Skip the control EP's */
+	for (i = 0; i < (PCH_UDC_USED_EP_NUM*2); i++) {
+		ep = &dev->ep[i];
+		pch_udc_ep_set_nak(ep);
+		pch_udc_ep_fifo_flush(ep, ep->in);
+		/* Complete request queue */
+		empty_req_queue(ep);
+	}
+	if (dev->driver && dev->driver->disconnect)
+		dev->driver->disconnect(&dev->gadget);
+}
+
+/**
+ * pch_udc_svc_enum_interrupt() - This function handles a USB speed enumeration
+ *				done interrupt
+ * @dev:	Reference to driver structure
+ */
+static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev)
+{
+	u32 dev_stat, dev_speed;
+	u32 speed = USB_SPEED_FULL;
+
+	dev_stat = pch_udc_read_device_status(dev);
+	dev_speed = (dev_stat & UDC_DEVSTS_ENUM_SPEED_MASK) >>
+						 UDC_DEVSTS_ENUM_SPEED_SHIFT;
+	switch (dev_speed) {
+	case UDC_DEVSTS_ENUM_SPEED_HIGH:
+		speed = USB_SPEED_HIGH;
+		break;
+	case  UDC_DEVSTS_ENUM_SPEED_FULL:
+		speed = USB_SPEED_FULL;
+		break;
+	case  UDC_DEVSTS_ENUM_SPEED_LOW:
+		speed = USB_SPEED_LOW;
+		break;
+	default:
+		BUG();
+	}
+	dev->gadget.speed = speed;
+	pch_udc_activate_control_ep(dev);
+	pch_udc_enable_ep_interrupts(dev, UDC_EPINT_IN_EP0 | UDC_EPINT_OUT_EP0);
+	pch_udc_set_dma(dev, DMA_DIR_TX);
+	pch_udc_set_dma(dev, DMA_DIR_RX);
+	pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX]));
+}
+
+/**
+ * pch_udc_svc_intf_interrupt() - This function handles a set interface
+ *				  interrupt
+ * @dev:	Reference to driver structure
+ */
+static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev)
+{
+	u32 reg, dev_stat = 0;
+	int i, ret;
+
+	dev_stat = pch_udc_read_device_status(dev);
+	dev->cfg_data.cur_intf = (dev_stat & UDC_DEVSTS_INTF_MASK) >>
+							 UDC_DEVSTS_INTF_SHIFT;
+	dev->cfg_data.cur_alt = (dev_stat & UDC_DEVSTS_ALT_MASK) >>
+							 UDC_DEVSTS_ALT_SHIFT;
+	dev->set_cfg_not_acked = 1;
+	/* Construct the usb request for gadget driver and inform it */
+	memset(&dev->setup_data, 0 , sizeof dev->setup_data);
+	dev->setup_data.bRequest = USB_REQ_SET_INTERFACE;
+	dev->setup_data.bRequestType = USB_RECIP_INTERFACE;
+	dev->setup_data.wValue = cpu_to_le16(dev->cfg_data.cur_alt);
+	dev->setup_data.wIndex = cpu_to_le16(dev->cfg_data.cur_intf);
+	/* programm the Endpoint Cfg registers */
+	/* Only one end point cfg register */
+	reg = pch_udc_read_csr(dev, UDC_EP0OUT_IDX);
+	reg = (reg & ~UDC_CSR_NE_INTF_MASK) |
+	      (dev->cfg_data.cur_intf << UDC_CSR_NE_INTF_SHIFT);
+	reg = (reg & ~UDC_CSR_NE_ALT_MASK) |
+	      (dev->cfg_data.cur_alt << UDC_CSR_NE_ALT_SHIFT);
+	pch_udc_write_csr(dev, reg, UDC_EP0OUT_IDX);
+	for (i = 0; i < PCH_UDC_USED_EP_NUM * 2; i++) {
+		/* clear stall bits */
+		pch_udc_ep_clear_stall(&(dev->ep[i]));
+		dev->ep[i].halted = 0;
+	}
+	dev->stall = 0;
+	spin_unlock(&dev->lock);
+	ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+	spin_lock(&dev->lock);
+}
+
+/**
+ * pch_udc_svc_cfg_interrupt() - This function handles a set configuration
+ *				interrupt
+ * @dev:	Reference to driver structure
+ */
+static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
+{
+	int i, ret;
+	u32 reg, dev_stat = 0;
+
+	dev_stat = pch_udc_read_device_status(dev);
+	dev->set_cfg_not_acked = 1;
+	dev->cfg_data.cur_cfg = (dev_stat & UDC_DEVSTS_CFG_MASK) >>
+				UDC_DEVSTS_CFG_SHIFT;
+	/* make usb request for gadget driver */
+	memset(&dev->setup_data, 0 , sizeof dev->setup_data);
+	dev->setup_data.bRequest = USB_REQ_SET_CONFIGURATION;
+	dev->setup_data.wValue = cpu_to_le16(dev->cfg_data.cur_cfg);
+	/* program the NE registers */
+	/* Only one end point cfg register */
+	reg = pch_udc_read_csr(dev, UDC_EP0OUT_IDX);
+	reg = (reg & ~UDC_CSR_NE_CFG_MASK) |
+	      (dev->cfg_data.cur_cfg << UDC_CSR_NE_CFG_SHIFT);
+	pch_udc_write_csr(dev, reg, UDC_EP0OUT_IDX);
+	for (i = 0; i < PCH_UDC_USED_EP_NUM * 2; i++) {
+		/* clear stall bits */
+		pch_udc_ep_clear_stall(&(dev->ep[i]));
+		dev->ep[i].halted = 0;
+	}
+	dev->stall = 0;
+
+	/* call gadget zero with setup data received */
+	spin_unlock(&dev->lock);
+	ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+	spin_lock(&dev->lock);
+}
+
+/**
+ * pch_udc_dev_isr() - This function services device interrupts
+ *			by invoking appropriate routines.
+ * @dev:	Reference to the device structure
+ * @dev_intr:	The Device interrupt status.
+ */
+static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
+{
+	/* USB Reset Interrupt */
+	if (dev_intr & UDC_DEVINT_UR)
+		pch_udc_svc_ur_interrupt(dev);
+	/* Enumeration Done Interrupt */
+	if (dev_intr & UDC_DEVINT_ENUM)
+		pch_udc_svc_enum_interrupt(dev);
+	/* Set Interface Interrupt */
+	if (dev_intr & UDC_DEVINT_SI)
+		pch_udc_svc_intf_interrupt(dev);
+	/* Set Config Interrupt */
+	if (dev_intr & UDC_DEVINT_SC)
+		pch_udc_svc_cfg_interrupt(dev);
+	/* USB Suspend interrupt */
+	if (dev_intr & UDC_DEVINT_US)
+		dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
+	/* Clear the SOF interrupt, if enabled */
+	if (dev_intr & UDC_DEVINT_SOF)
+		dev_dbg(&dev->pdev->dev, "SOF\n");
+	/* ES interrupt, IDLE > 3ms on the USB */
+	if (dev_intr & UDC_DEVINT_ES)
+		dev_dbg(&dev->pdev->dev, "ES\n");
+	/* RWKP interrupt */
+	if (dev_intr & UDC_DEVINT_RWKP)
+		dev_dbg(&dev->pdev->dev, "RWKP\n");
+}
+
+/**
+ * pch_udc_isr() - This function handles interrupts from the PCH USB Device
+ * @irq:	Interrupt request number
+ * @dev:	Reference to the device structure
+ */
+static irqreturn_t pch_udc_isr(int irq, void *pdev)
+{
+	struct pch_udc_dev *dev = (struct pch_udc_dev *) pdev;
+	u32 dev_intr, ep_intr;
+	int i;
+
+	dev_intr = pch_udc_read_device_interrupts(dev);
+	ep_intr = pch_udc_read_ep_interrupts(dev);
+
+	if (dev_intr)
+		/* Clear device interrupts */
+		pch_udc_write_device_interrupts(dev, dev_intr);
+	if (ep_intr)
+		/* Clear ep interrupts */
+		pch_udc_write_ep_interrupts(dev, ep_intr);
+	if (!dev_intr && !ep_intr)
+		return IRQ_NONE;
+	spin_lock(&dev->lock);
+	if (dev_intr)
+		pch_udc_dev_isr(dev, dev_intr);
+	if (ep_intr) {
+		pch_udc_read_all_epstatus(dev, ep_intr);
+		/* Process Control In interrupts, if present */
+		if (ep_intr & UDC_EPINT_IN_EP0) {
+			pch_udc_svc_control_in(dev);
+			pch_udc_postsvc_epinters(dev, 0);
+		}
+		/* Process Control Out interrupts, if present */
+		if (ep_intr & UDC_EPINT_OUT_EP0)
+			pch_udc_svc_control_out(dev);
+		/* Process data in end point interrupts */
+		for (i = 1; i < PCH_UDC_USED_EP_NUM; i++) {
+			if (ep_intr & (1 <<  i)) {
+				pch_udc_svc_data_in(dev, i);
+				pch_udc_postsvc_epinters(dev, i);
+			}
+		}
+		/* Process data out end point interrupts */
+		for (i = UDC_EPINT_OUT_SHIFT + 1; i < (UDC_EPINT_OUT_SHIFT +
+						 PCH_UDC_USED_EP_NUM); i++)
+			if (ep_intr & (1 <<  i))
+				pch_udc_svc_data_out(dev, i -
+							 UDC_EPINT_OUT_SHIFT);
+	}
+	spin_unlock(&dev->lock);
+	return IRQ_HANDLED;
+}
+
+/**
+ * pch_udc_setup_ep0() - This function enables control endpoint for traffic
+ * @dev:	Reference to the device structure
+ */
+static void pch_udc_setup_ep0(struct pch_udc_dev *dev)
+{
+	/* enable ep0 interrupts */
+	pch_udc_enable_ep_interrupts(dev, UDC_EPINT_IN_EP0 |
+						UDC_EPINT_OUT_EP0);
+	/* enable device interrupts */
+	pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
+				       UDC_DEVINT_ES | UDC_DEVINT_ENUM |
+				       UDC_DEVINT_SI | UDC_DEVINT_SC);
+}
+
+/**
+ * gadget_release() - Free the gadget driver private data
+ * @pdev	reference to struct pci_dev
+ */
+static void gadget_release(struct device *pdev)
+{
+	struct pch_udc_dev *dev = dev_get_drvdata(pdev);
+
+	kfree(dev);
+}
+
+/**
+ * pch_udc_pcd_reinit() - This API initializes the endpoint structures
+ * @dev:	Reference to the driver structure
+ */
+static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
+{
+	const char *const ep_string[] = {
+		ep0_string, "ep0out", "ep1in", "ep1out", "ep2in", "ep2out",
+		"ep3in", "ep3out", "ep4in", "ep4out", "ep5in", "ep5out",
+		"ep6in", "ep6out", "ep7in", "ep7out", "ep8in", "ep8out",
+		"ep9in", "ep9out", "ep10in", "ep10out", "ep11in", "ep11out",
+		"ep12in", "ep12out", "ep13in", "ep13out", "ep14in", "ep14out",
+		"ep15in", "ep15out",
+	};
+	int i;
+
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+
+	/* Initialize the endpoints structures */
+	memset(dev->ep, 0, sizeof dev->ep);
+	for (i = 0; i < PCH_UDC_EP_NUM; i++) {
+		struct pch_udc_ep *ep = &dev->ep[i];
+		ep->dev = dev;
+		ep->halted = 1;
+		ep->num = i / 2;
+		ep->in = ~i & 1;
+		ep->ep.name = ep_string[i];
+		ep->ep.ops = &pch_udc_ep_ops;
+		if (ep->in)
+			ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
+		else
+			ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
+					  UDC_EP_REG_SHIFT;
+		/* need to set ep->ep.maxpacket and set Default Configuration?*/
+		ep->ep.maxpacket = UDC_BULK_MAX_PKT_SIZE;
+		list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+		INIT_LIST_HEAD(&ep->queue);
+	}
+	dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
+	dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
+
+	dev->dma_addr = pci_map_single(dev->pdev, dev->ep0out_buf, 256,
+				  PCI_DMA_FROMDEVICE);
+
+	/* remove ep0 in and out from the list.  They have own pointer */
+	list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
+	list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list);
+
+	dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+}
+
+/**
+ * pch_udc_pcd_init() - This API initializes the driver structure
+ * @dev:	Reference to the driver structure
+ *
+ * Return codes:
+ *	0: Success
+ */
+static int pch_udc_pcd_init(struct pch_udc_dev *dev)
+{
+	pch_udc_init(dev);
+	pch_udc_pcd_reinit(dev);
+	return 0;
+}
+
+/**
+ * init_dma_pools() - create dma pools during initialization
+ * @pdev:	reference to struct pci_dev
+ */
+static int init_dma_pools(struct pch_udc_dev *dev)
+{
+	struct pch_udc_stp_dma_desc	*td_stp;
+	struct pch_udc_data_dma_desc	*td_data;
+
+	/* DMA setup */
+	dev->data_requests = pci_pool_create("data_requests", dev->pdev,
+		sizeof(struct pch_udc_data_dma_desc), 0, 0);
+	if (!dev->data_requests) {
+		dev_err(&dev->pdev->dev, "%s: can't get request data pool\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	/* dma desc for setup data */
+	dev->stp_requests = pci_pool_create("setup requests", dev->pdev,
+		sizeof(struct pch_udc_stp_dma_desc), 0, 0);
+	if (!dev->stp_requests) {
+		dev_err(&dev->pdev->dev, "%s: can't get setup request pool\n",
+			__func__);
+		return -ENOMEM;
+	}
+	/* setup */
+	td_stp = pci_pool_alloc(dev->stp_requests, GFP_KERNEL,
+				&dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
+	if (!td_stp) {
+		dev_err(&dev->pdev->dev,
+			"%s: can't allocate setup dma descriptor\n", __func__);
+		return -ENOMEM;
+	}
+	dev->ep[UDC_EP0OUT_IDX].td_stp = td_stp;
+
+	/* data: 0 packets !? */
+	td_data = pci_pool_alloc(dev->data_requests, GFP_KERNEL,
+				&dev->ep[UDC_EP0OUT_IDX].td_data_phys);
+	if (!td_data) {
+		dev_err(&dev->pdev->dev,
+			"%s: can't allocate data dma descriptor\n", __func__);
+		return -ENOMEM;
+	}
+	dev->ep[UDC_EP0OUT_IDX].td_data = td_data;
+	dev->ep[UDC_EP0IN_IDX].td_stp = NULL;
+	dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0;
+	dev->ep[UDC_EP0IN_IDX].td_data = NULL;
+	dev->ep[UDC_EP0IN_IDX].td_data_phys = 0;
+	return 0;
+}
+
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+	int (*bind)(struct usb_gadget *))
+{
+	struct pch_udc_dev	*dev = pch_udc;
+	int			retval;
+
+	if (!driver || (driver->speed == USB_SPEED_UNKNOWN) || !bind ||
+	    !driver->setup || !driver->unbind || !driver->disconnect) {
+		dev_err(&dev->pdev->dev,
+			"%s: invalid driver parameter\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!dev)
+		return -ENODEV;
+
+	if (dev->driver) {
+		dev_err(&dev->pdev->dev, "%s: already bound\n", __func__);
+		return -EBUSY;
+	}
+	driver->driver.bus = NULL;
+	dev->driver = driver;
+	dev->gadget.dev.driver = &driver->driver;
+
+	/* Invoke the bind routine of the gadget driver */
+	retval = bind(&dev->gadget);
+
+	if (retval) {
+		dev_err(&dev->pdev->dev, "%s: binding to %s returning %d\n",
+		       __func__, driver->driver.name, retval);
+		dev->driver = NULL;
+		dev->gadget.dev.driver = NULL;
+		return retval;
+	}
+	/* get ready for ep0 traffic */
+	pch_udc_setup_ep0(dev);
+
+	/* clear SD */
+	pch_udc_clear_disconnect(dev);
+
+	dev->connected = 1;
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct pch_udc_dev	*dev = pch_udc;
+
+	if (!dev)
+		return -ENODEV;
+
+	if (!driver || (driver != dev->driver)) {
+		dev_err(&dev->pdev->dev,
+			"%s: invalid driver parameter\n", __func__);
+		return -EINVAL;
+	}
+
+	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
+
+	/* Assues that there are no pending requets with this driver */
+	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
+	dev->driver = NULL;
+	dev->connected = 0;
+
+	/* set SD */
+	pch_udc_set_disconnect(dev);
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+static void pch_udc_shutdown(struct pci_dev *pdev)
+{
+	struct pch_udc_dev *dev = pci_get_drvdata(pdev);
+
+	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
+	pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+
+	/* disable the pullup so the host will think we're gone */
+	pch_udc_set_disconnect(dev);
+}
+
+static void pch_udc_remove(struct pci_dev *pdev)
+{
+	struct pch_udc_dev	*dev = pci_get_drvdata(pdev);
+
+	/* gadget driver must not be registered */
+	if (dev->driver)
+		dev_err(&pdev->dev,
+			"%s: gadget driver still bound!!!\n", __func__);
+	/* dma pool cleanup */
+	if (dev->data_requests)
+		pci_pool_destroy(dev->data_requests);
+
+	if (dev->stp_requests) {
+		/* cleanup DMA desc's for ep0in */
+		if (dev->ep[UDC_EP0OUT_IDX].td_stp) {
+			pci_pool_free(dev->stp_requests,
+				dev->ep[UDC_EP0OUT_IDX].td_stp,
+				dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
+		}
+		if (dev->ep[UDC_EP0OUT_IDX].td_data) {
+			pci_pool_free(dev->stp_requests,
+				dev->ep[UDC_EP0OUT_IDX].td_data,
+				dev->ep[UDC_EP0OUT_IDX].td_data_phys);
+		}
+		pci_pool_destroy(dev->stp_requests);
+	}
+
+	pch_udc_exit(dev);
+
+	if (dev->irq_registered)
+		free_irq(pdev->irq, dev);
+	if (dev->base_addr)
+		iounmap(dev->base_addr);
+	if (dev->mem_region)
+		release_mem_region(dev->phys_addr,
+				   pci_resource_len(pdev, PCH_UDC_PCI_BAR));
+	if (dev->active)
+		pci_disable_device(pdev);
+	if (dev->registered)
+		device_unregister(&dev->gadget.dev);
+	kfree(dev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int pch_udc_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct pch_udc_dev *dev = pci_get_drvdata(pdev);
+
+	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
+	pch_udc_disable_ep_interrupts(dev, UDC_EPINT_MSK_DISABLE_ALL);
+
+	pci_disable_device(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+
+	if (pci_save_state(pdev)) {
+		dev_err(&pdev->dev,
+			"%s: could not save PCI config state\n", __func__);
+		return -ENOMEM;
+	}
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return 0;
+}
+
+static int pch_udc_resume(struct pci_dev *pdev)
+{
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_restore_state(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: pci_restore_state failed\n", __func__);
+		return ret;
+	}
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__);
+		return ret;
+	}
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	return 0;
+}
+#else
+#define pch_udc_suspend	NULL
+#define pch_udc_resume	NULL
+#endif /* CONFIG_PM */
+
+static int pch_udc_probe(struct pci_dev *pdev,
+			  const struct pci_device_id *id)
+{
+	unsigned long		resource;
+	unsigned long		len;
+	int			retval;
+	struct pch_udc_dev	*dev;
+
+	/* one udc only */
+	if (pch_udc) {
+		pr_err("%s: already probed\n", __func__);
+		return -EBUSY;
+	}
+	/* init */
+	dev = kzalloc(sizeof *dev, GFP_KERNEL);
+	if (!dev) {
+		pr_err("%s: no memory for device structure\n", __func__);
+		return -ENOMEM;
+	}
+	/* pci setup */
+	if (pci_enable_device(pdev) < 0) {
+		kfree(dev);
+		pr_err("%s: pci_enable_device failed\n", __func__);
+		return -ENODEV;
+	}
+	dev->active = 1;
+	pci_set_drvdata(pdev, dev);
+
+	/* PCI resource allocation */
+	resource = pci_resource_start(pdev, 1);
+	len = pci_resource_len(pdev, 1);
+
+	if (!request_mem_region(resource, len, KBUILD_MODNAME)) {
+		dev_err(&pdev->dev, "%s: pci device used already\n", __func__);
+		retval = -EBUSY;
+		goto finished;
+	}
+	dev->phys_addr = resource;
+	dev->mem_region = 1;
+
+	dev->base_addr = ioremap_nocache(resource, len);
+	if (!dev->base_addr) {
+		pr_err("%s: device memory cannot be mapped\n", __func__);
+		retval = -ENOMEM;
+		goto finished;
+	}
+	if (!pdev->irq) {
+		dev_err(&pdev->dev, "%s: irq not set\n", __func__);
+		retval = -ENODEV;
+		goto finished;
+	}
+	pch_udc = dev;
+	/* initialize the hardware */
+	if (pch_udc_pcd_init(dev))
+		goto finished;
+	if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
+			dev)) {
+		dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,
+			pdev->irq);
+		retval = -ENODEV;
+		goto finished;
+	}
+	dev->irq = pdev->irq;
+	dev->irq_registered = 1;
+
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	/* device struct setup */
+	spin_lock_init(&dev->lock);
+	dev->pdev = pdev;
+	dev->gadget.ops = &pch_udc_ops;
+
+	retval = init_dma_pools(dev);
+	if (retval)
+		goto finished;
+
+	dev_set_name(&dev->gadget.dev, "gadget");
+	dev->gadget.dev.parent = &pdev->dev;
+	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
+	dev->gadget.dev.release = gadget_release;
+	dev->gadget.name = KBUILD_MODNAME;
+	dev->gadget.is_dualspeed = 1;
+
+	retval = device_register(&dev->gadget.dev);
+	if (retval)
+		goto finished;
+	dev->registered = 1;
+
+	/* Put the device in disconnected state till a driver is bound */
+	pch_udc_set_disconnect(dev);
+	return 0;
+
+finished:
+	pch_udc_remove(pdev);
+	return retval;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC),
+		.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+		.class_mask = 0xffffffff,
+	},
+	{ 0 },
+};
+
+MODULE_DEVICE_TABLE(pci, pch_udc_pcidev_id);
+
+
+static struct pci_driver pch_udc_driver = {
+	.name =	KBUILD_MODNAME,
+	.id_table =	pch_udc_pcidev_id,
+	.probe =	pch_udc_probe,
+	.remove =	pch_udc_remove,
+	.suspend =	pch_udc_suspend,
+	.resume =	pch_udc_resume,
+	.shutdown =	pch_udc_shutdown,
+};
+
+static int __init pch_udc_pci_init(void)
+{
+	return pci_register_driver(&pch_udc_driver);
+}
+module_init(pch_udc_pci_init);
+
+static void __exit pch_udc_pci_exit(void)
+{
+	pci_unregister_driver(&pch_udc_driver);
+}
+module_exit(pch_udc_pci_exit);
+
+MODULE_DESCRIPTION("Intel EG20T USB Device Controller");
+MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_audio.c
index 7a86d2c..59ffe1e 100644
--- a/drivers/usb/gadget/u_audio.c
+++ b/drivers/usb/gadget/u_audio.c
@@ -255,6 +255,7 @@
 		ERROR(card, "No such PCM capture device: %s\n", fn_cap);
 		snd->substream = NULL;
 		snd->card = NULL;
+		snd->filp = NULL;
 	} else {
 		pcm_file = snd->filp->private_data;
 		snd->substream = pcm_file->substream;
@@ -273,17 +274,17 @@
 
 	/* Close control device */
 	snd = &gau->control;
-	if (!IS_ERR(snd->filp))
+	if (snd->filp)
 		filp_close(snd->filp, current->files);
 
 	/* Close PCM playback device and setup substream */
 	snd = &gau->playback;
-	if (!IS_ERR(snd->filp))
+	if (snd->filp)
 		filp_close(snd->filp, current->files);
 
 	/* Close PCM capture device and setup substream */
 	snd = &gau->capture;
-	if (!IS_ERR(snd->filp))
+	if (snd->filp)
 		filp_close(snd->filp, current->files);
 
 	return 0;
@@ -304,8 +305,7 @@
 	ret = gaudio_open_snd_dev(card);
 	if (ret)
 		ERROR(card, "we need at least one control device\n");
-
-	if (!the_card)
+	else if (!the_card)
 		the_card = card;
 
 	return ret;
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index fbe86ca..1eda968 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -240,6 +240,9 @@
 	size += out->maxpacket - 1;
 	size -= size % out->maxpacket;
 
+	if (dev->port_usb->is_fixed)
+		size = max(size, dev->port_usb->fixed_out_len);
+
 	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
 	if (skb == NULL) {
 		DBG(dev, "no rx skb\n");
@@ -578,12 +581,19 @@
 	req->context = skb;
 	req->complete = tx_complete;
 
+	/* NCM requires no zlp if transfer is dwNtbInMaxSize */
+	if (dev->port_usb->is_fixed &&
+	    length == dev->port_usb->fixed_in_len &&
+	    (length % in->maxpacket) == 0)
+		req->zero = 0;
+	else
+		req->zero = 1;
+
 	/* use zlp framing on tx for strict CDC-Ether conformance,
 	 * though any robust network rx path ignores extra padding.
 	 * and some hardware doesn't like to write zlps.
 	 */
-	req->zero = 1;
-	if (!dev->zlp && (length % in->maxpacket) == 0)
+	if (req->zero && !dev->zlp && (length % in->maxpacket) == 0)
 		length++;
 
 	req->length = length;
@@ -829,11 +839,9 @@
 		return;
 
 	unregister_netdev(the_dev->net);
+	flush_work_sync(&the_dev->work);
 	free_netdev(the_dev->net);
 
-	/* assuming we used keventd, it must quiesce too */
-	flush_scheduled_work();
-
 	the_dev = NULL;
 }
 
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 3c8c0c9..b56e1e7 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -62,6 +62,10 @@
 
 	/* hooks for added framing, as needed for RNDIS and EEM. */
 	u32				header_len;
+	/* NCM requires fixed size bundles */
+	bool				is_fixed;
+	u32				fixed_out_len;
+	u32				fixed_in_len;
 	struct sk_buff			*(*wrap)(struct gether *port,
 						struct sk_buff *skb);
 	int				(*unwrap)(struct gether *port,
@@ -103,6 +107,7 @@
 /* each configuration may bind one instance of an ethernet link */
 int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
 int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
 int eem_bind_config(struct usb_configuration *c);
 
 #ifdef USB_ETH_RNDIS
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6f4f8e6..24046c0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -133,6 +133,25 @@
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 
+config USB_EHCI_HCD_OMAP
+	bool "EHCI support for OMAP3 and later chips"
+	depends on USB_EHCI_HCD && ARCH_OMAP
+	default y
+	--- help ---
+	  Enables support for the on-chip EHCI controller on
+	  OMAP3 and later chips.
+
+config USB_EHCI_MSM
+	bool "Support for MSM on-chip EHCI USB controller"
+	depends on USB_EHCI_HCD && ARCH_MSM
+	select USB_EHCI_ROOT_HUB_TT
+	select USB_MSM_OTG_72K
+	---help---
+	  Enables support for the USB Host controller present on the
+	  Qualcomm chipsets. Root Hub has inbuilt TT.
+	  This driver depends on OTG driver for PHY initialization,
+	  clock management, powering up VBUS, and power management.
+
 config USB_EHCI_HCD_PPC_OF
 	bool "EHCI support for PPC USB controller on OF platform bus"
 	depends on USB_EHCI_HCD && PPC_OF
@@ -147,6 +166,14 @@
 	---help---
 		Enables support for the W90X900 USB controller
 
+config USB_CNS3XXX_EHCI
+	bool "Cavium CNS3XXX EHCI Module"
+	depends on USB_EHCI_HCD && ARCH_CNS3XXX
+	---help---
+	  Enable support for the CNS3XXX SOC's on-chip EHCI controller.
+	  It is needed for high-speed (480Mbit/sec) USB 2.0 device
+	  support.
+
 config USB_OXU210HP_HCD
 	tristate "OXU210HP HCD support"
 	depends on USB
@@ -286,6 +313,13 @@
 
 	  If unsure, say N.
 
+config USB_CNS3XXX_OHCI
+	bool "Cavium CNS3XXX OHCI Module"
+	depends on USB_OHCI_HCD && ARCH_CNS3XXX
+	---help---
+	  Enable support for the CNS3XXX SOC's on-chip OHCI controller.
+	  It is needed for low-speed USB 1.0 device support.
+
 config USB_OHCI_BIG_ENDIAN_DESC
 	bool
 	depends on USB_OHCI_HCD
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 51bd0ed..d6a69d5 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -99,6 +99,7 @@
 	.urb_enqueue		= ehci_urb_enqueue,
 	.urb_dequeue		= ehci_urb_dequeue,
 	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
 
 	/* scheduling support */
 	.get_frame_number	= ehci_get_frame,
@@ -110,6 +111,8 @@
 	.bus_resume		= ehci_bus_resume,
 	.relinquish_port	= ehci_relinquish_port,
 	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
 static int __init ehci_atmel_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
new file mode 100644
index 0000000..708a05b
--- /dev/null
+++ b/drivers/usb/host/ehci-cns3xxx.c
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/atomic.h>
+#include <mach/cns3xxx.h>
+#include <mach/pm.h>
+
+static int cns3xxx_ehci_init(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 *
+	 * Set USB AHB INCR length to 16
+	 */
+	if (atomic_inc_return(&usb_pwr_ref) == 1) {
+		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+			MISC_CHIP_CONFIG_REG);
+	}
+
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs
+		+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	hcd->has_tt = 0;
+	ehci_reset(ehci);
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+static const struct hc_driver cns3xxx_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "CNS3XXX EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+	.reset			= cns3xxx_ehci_init,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+	.get_frame_number	= ehci_get_frame,
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#ifdef CONFIG_PM
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int cns3xxx_ehci_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_hcd *hcd;
+	const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
+	struct resource *res;
+	int irq;
+	int retval;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "Found HC with no IRQ.\n");
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "Found HC with no register addr.\n");
+		retval = -ENODEV;
+		goto err1;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				driver->description)) {
+		dev_dbg(dev, "controller already in use\n");
+		retval = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_dbg(dev, "error mapping memory\n");
+		retval = -EFAULT;
+		goto err2;
+	}
+
+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (retval == 0)
+		return retval;
+
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+
+	return retval;
+}
+
+static int cns3xxx_ehci_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 */
+	if (atomic_dec_return(&usb_pwr_ref) == 0)
+		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+
+	usb_put_hcd(hcd);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:cns3xxx-ehci");
+
+static struct platform_driver cns3xxx_ehci_driver = {
+	.probe = cns3xxx_ehci_probe,
+	.remove = cns3xxx_ehci_remove,
+	.driver = {
+		.name = "cns3xxx-ehci",
+	},
+};
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 6e25996..3be238a 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -879,7 +879,7 @@
 	int ret = 0;
 
 	if (!buf->output_buf)
-		buf->output_buf = (char *)vmalloc(buf->alloc_size);
+		buf->output_buf = vmalloc(buf->alloc_size);
 
 	if (!buf->output_buf) {
 		ret = -ENOMEM;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e906280..6fee3cd 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -114,6 +114,9 @@
 
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
+/* for ASPM quirk of ISOC on AMD SB800 */
+static struct pci_dev *amd_nb_dev;
+
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
@@ -529,6 +532,11 @@
 	spin_unlock_irq (&ehci->lock);
 	ehci_mem_cleanup (ehci);
 
+	if (amd_nb_dev) {
+		pci_dev_put(amd_nb_dev);
+		amd_nb_dev = NULL;
+	}
+
 #ifdef	EHCI_STATS
 	ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
 		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
@@ -1166,12 +1174,17 @@
 #define PLATFORM_DRIVER		ehci_mxc_driver
 #endif
 
+#ifdef CONFIG_CPU_SUBTYPE_SH7786
+#include "ehci-sh.c"
+#define PLATFORM_DRIVER		ehci_hcd_sh_driver
+#endif
+
 #ifdef CONFIG_SOC_AU1200
 #include "ehci-au1xxx.c"
 #define	PLATFORM_DRIVER		ehci_hcd_au1xxx_driver
 #endif
 
-#ifdef CONFIG_ARCH_OMAP3
+#ifdef CONFIG_USB_EHCI_HCD_OMAP
 #include "ehci-omap.c"
 #define        PLATFORM_DRIVER         ehci_hcd_omap_driver
 #endif
@@ -1216,6 +1229,26 @@
 #define PLATFORM_DRIVER		ehci_octeon_driver
 #endif
 
+#ifdef CONFIG_USB_CNS3XXX_EHCI
+#include "ehci-cns3xxx.c"
+#define PLATFORM_DRIVER		cns3xxx_ehci_driver
+#endif
+
+#ifdef CONFIG_ARCH_VT8500
+#include "ehci-vt8500.c"
+#define	PLATFORM_DRIVER		vt8500_ehci_driver
+#endif
+
+#ifdef CONFIG_PLAT_SPEAR
+#include "ehci-spear.c"
+#define PLATFORM_DRIVER		spear_ehci_hcd_driver
+#endif
+
+#ifdef CONFIG_USB_EHCI_MSM
+#include "ehci-msm.c"
+#define PLATFORM_DRIVER		ehci_msm_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
new file mode 100644
index 0000000..413f4de
--- /dev/null
+++ b/drivers/usb/host/ehci-msm.c
@@ -0,0 +1,345 @@
+/* ehci-msm.c - HSUSB Host Controller Driver Implementation
+ *
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * Partly derived from ehci-fsl.c and ehci-hcd.c
+ * Copyright (c) 2000-2004 by David Brownell
+ * Copyright (c) 2005 MontaVista Software
+ *
+ * All source code in this file is licensed under the following license except
+ * where indicated.
+ *
+ * This program is free software; you can 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, you can find it at http://www.fsf.org
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/msm_hsusb_hw.h>
+
+#define MSM_USB_BASE (hcd->regs)
+
+static struct otg_transceiver *otg;
+
+/*
+ * ehci_run defined in drivers/usb/host/ehci-hcd.c reset the controller and
+ * the configuration settings in ehci_msm_reset vanish after controller is
+ * reset. Resetting the controler in ehci_run seems to be un-necessary
+ * provided HCD reset the controller before calling ehci_run. Most of the HCD
+ * do but some are not. So this function is same as ehci_run but we don't
+ * reset the controller here.
+ */
+static int ehci_msm_run(struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+	u32			temp;
+	u32			hcc_params;
+
+	hcd->uses_new_polling = 1;
+
+	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
+	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
+
+	/*
+	 * hcc_params controls whether ehci->regs->segment must (!!!)
+	 * be used; it constrains QH/ITD/SITD and QTD locations.
+	 * pci_pool consistent memory always uses segment zero.
+	 * streaming mappings for I/O buffers, like pci_map_single(),
+	 * can return segments above 4GB, if the device allows.
+	 *
+	 * NOTE:  the dma mask is visible through dma_supported(), so
+	 * drivers can pass this info along ... like NETIF_F_HIGHDMA,
+	 * Scsi_Host.highmem_io, and so forth.  It's readonly to all
+	 * host side drivers though.
+	 */
+	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
+	if (HCC_64BIT_ADDR(hcc_params))
+		ehci_writel(ehci, 0, &ehci->regs->segment);
+
+	/*
+	 * Philips, Intel, and maybe others need CMD_RUN before the
+	 * root hub will detect new devices (why?); NEC doesn't
+	 */
+	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+	ehci->command |= CMD_RUN;
+	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+	dbg_cmd(ehci, "init", ehci->command);
+
+	/*
+	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
+	 * are explicitly handed to companion controller(s), so no TT is
+	 * involved with the root hub.  (Except where one is integrated,
+	 * and there's no companion controller unless maybe for USB OTG.)
+	 *
+	 * Turning on the CF flag will transfer ownership of all ports
+	 * from the companions to the EHCI controller.  If any of the
+	 * companions are in the middle of a port reset at the time, it
+	 * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
+	 * guarantees that no resets are in progress.  After we set CF,
+	 * a short delay lets the hardware catch up; new resets shouldn't
+	 * be started before the port switching actions could complete.
+	 */
+	down_write(&ehci_cf_port_reset_rwsem);
+	hcd->state = HC_STATE_RUNNING;
+	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+	usleep_range(5000, 5500);
+	up_write(&ehci_cf_port_reset_rwsem);
+	ehci->last_periodic_enable = ktime_get_real();
+
+	temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	ehci_info(ehci,
+		"USB %x.%x started, EHCI %x.%02x%s\n",
+		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
+		temp >> 8, temp & 0xff,
+		ignore_oc ? ", overcurrent ignored" : "");
+
+	ehci_writel(ehci, INTR_MASK,
+		    &ehci->regs->intr_enable); /* Turn On Interrupts */
+
+	/* GRR this is run-once init(), being done every time the HC starts.
+	 * So long as they're part of class devices, we can't do it init()
+	 * since the class device isn't created that early.
+	 */
+	create_debug_files(ehci);
+	create_companion_file(ehci);
+
+	return 0;
+}
+
+static int ehci_msm_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	ehci->caps = USB_CAPLENGTH;
+	ehci->regs = USB_CAPLENGTH +
+		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+	/* cache the data to minimize the chip reads*/
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	hcd->has_tt = 1;
+	ehci->sbrn = HCD_USB2;
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	retval = ehci_reset(ehci);
+	if (retval)
+		return retval;
+
+	/* bursts of unspecified length. */
+	writel(0, USB_AHBBURST);
+	/* Use the AHB transactor */
+	writel(0, USB_AHBMODE);
+	/* Disable streaming mode and select host mode */
+	writel(0x13, USB_USBMODE);
+
+	ehci_port_power(ehci, 1);
+	return 0;
+}
+
+static struct hc_driver msm_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Qualcomm On-Chip EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ehci_irq,
+	.flags			= HCD_USB2 | HCD_MEMORY,
+
+	.reset			= ehci_msm_reset,
+	.start			= ehci_msm_run,
+
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	/*
+	 * PM support
+	 */
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+};
+
+static int ehci_msm_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int ret;
+
+	dev_dbg(&pdev->dev, "ehci_msm proble\n");
+
+	hcd = usb_create_hcd(&msm_hc_driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "Unable to create HCD\n");
+		return  -ENOMEM;
+	}
+
+	hcd->irq = platform_get_irq(pdev, 0);
+	if (hcd->irq < 0) {
+		dev_err(&pdev->dev, "Unable to get IRQ resource\n");
+		ret = hcd->irq;
+		goto put_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Unable to get memory resource\n");
+		ret = -ENODEV;
+		goto put_hcd;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto put_hcd;
+	}
+
+	/*
+	 * OTG driver takes care of PHY initialization, clock management,
+	 * powering up VBUS, mapping of registers address space and power
+	 * management.
+	 */
+	otg = otg_get_transceiver();
+	if (!otg) {
+		dev_err(&pdev->dev, "unable to find transceiver\n");
+		ret = -ENODEV;
+		goto unmap;
+	}
+
+	ret = otg_set_host(otg, &hcd->self);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to register with transceiver\n");
+		goto put_transceiver;
+	}
+
+	device_init_wakeup(&pdev->dev, 1);
+	/*
+	 * OTG device parent of HCD takes care of putting
+	 * hardware into low power mode.
+	 */
+	pm_runtime_no_callbacks(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+put_transceiver:
+	otg_put_transceiver(otg);
+unmap:
+	iounmap(hcd->regs);
+put_hcd:
+	usb_put_hcd(hcd);
+
+	return ret;
+}
+
+static int __devexit ehci_msm_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	device_init_wakeup(&pdev->dev, 0);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+
+	otg_set_host(otg, NULL);
+	otg_put_transceiver(otg);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ehci_msm_pm_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	bool wakeup = device_may_wakeup(dev);
+
+	dev_dbg(dev, "ehci-msm PM suspend\n");
+
+	/*
+	 * EHCI helper function has also the same check before manipulating
+	 * port wakeup flags.  We do check here the same condition before
+	 * calling the same helper function to avoid bringing hardware
+	 * from Low power mode when there is no need for adjusting port
+	 * wakeup flags.
+	 */
+	if (hcd->self.root_hub->do_remote_wakeup && !wakeup) {
+		pm_runtime_resume(dev);
+		ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
+				wakeup);
+	}
+
+	return 0;
+}
+
+static int ehci_msm_pm_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "ehci-msm PM resume\n");
+	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+
+	return 0;
+}
+#else
+#define ehci_msm_pm_suspend	NULL
+#define ehci_msm_pm_resume	NULL
+#endif
+
+static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
+	.suspend         = ehci_msm_pm_suspend,
+	.resume          = ehci_msm_pm_resume,
+};
+
+static struct platform_driver ehci_msm_driver = {
+	.probe	= ehci_msm_probe,
+	.remove	= __devexit_p(ehci_msm_remove),
+	.driver = {
+		   .name = "msm_hsusb_host",
+		   .pm = &ehci_msm_dev_pm_ops,
+	},
+};
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index bce8505..fa59b26 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -28,7 +28,7 @@
 #define ULPI_VIEWPORT_OFFSET	0x170
 
 struct ehci_mxc_priv {
-	struct clk *usbclk, *ahbclk;
+	struct clk *usbclk, *ahbclk, *phy1clk;
 	struct usb_hcd *hcd;
 };
 
@@ -36,14 +36,8 @@
 static int ehci_mxc_setup(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	struct device *dev = hcd->self.controller;
-	struct mxc_usbh_platform_data *pdata = dev_get_platdata(dev);
 	int retval;
 
-	/* EHCI registers start at offset 0x100 */
-	ehci->caps = hcd->regs + 0x100;
-	ehci->regs = hcd->regs + 0x100 +
-	    HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
 	dbg_hcs_params(ehci, "reset");
 	dbg_hcc_params(ehci, "reset");
 
@@ -65,12 +59,6 @@
 
 	ehci_reset(ehci);
 
-	/* set up the PORTSCx register */
-	ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
-
-	/* is this really needed? */
-	msleep(10);
-
 	ehci_port_power(ehci, 0);
 	return 0;
 }
@@ -100,6 +88,7 @@
 	.urb_enqueue = ehci_urb_enqueue,
 	.urb_dequeue = ehci_urb_dequeue,
 	.endpoint_disable = ehci_endpoint_disable,
+	.endpoint_reset = ehci_endpoint_reset,
 
 	/*
 	 * scheduling support
@@ -115,6 +104,8 @@
 	.bus_resume = ehci_bus_resume,
 	.relinquish_port = ehci_relinquish_port,
 	.port_handed_over = ehci_port_handed_over,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
 static int ehci_mxc_drv_probe(struct platform_device *pdev)
@@ -125,6 +116,7 @@
 	int irq, ret;
 	struct ehci_mxc_priv *priv;
 	struct device *dev = &pdev->dev;
+	struct ehci_hcd *ehci;
 
 	dev_info(&pdev->dev, "initializing i.MX USB Controller\n");
 
@@ -168,17 +160,6 @@
 		goto err_ioremap;
 	}
 
-	/* call platform specific init function */
-	if (pdata->init) {
-		ret = pdata->init(pdev);
-		if (ret) {
-			dev_err(dev, "platform init failed\n");
-			goto err_init;
-		}
-		/* platforms need some time to settle changed IO settings */
-		mdelay(10);
-	}
-
 	/* enable clocks */
 	priv->usbclk = clk_get(dev, "usb");
 	if (IS_ERR(priv->usbclk)) {
@@ -196,11 +177,46 @@
 		clk_enable(priv->ahbclk);
 	}
 
+	/* "dr" device has its own clock */
+	if (pdev->id == 0) {
+		priv->phy1clk = clk_get(dev, "usb_phy1");
+		if (IS_ERR(priv->phy1clk)) {
+			ret = PTR_ERR(priv->phy1clk);
+			goto err_clk_phy;
+		}
+		clk_enable(priv->phy1clk);
+	}
+
+
+	/* call platform specific init function */
+	if (pdata->init) {
+		ret = pdata->init(pdev);
+		if (ret) {
+			dev_err(dev, "platform init failed\n");
+			goto err_init;
+		}
+		/* platforms need some time to settle changed IO settings */
+		mdelay(10);
+	}
+
 	/* setup specific usb hw */
 	ret = mxc_initialize_usb_hw(pdev->id, pdata->flags);
 	if (ret < 0)
 		goto err_init;
 
+	ehci = hcd_to_ehci(hcd);
+
+	/* EHCI registers start at offset 0x100 */
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+	    HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+	/* set up the PORTSCx register */
+	ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
+
+	/* is this really needed? */
+	msleep(10);
+
 	/* Initialize the transceiver */
 	if (pdata->otg) {
 		pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
@@ -230,6 +246,11 @@
 	if (pdata && pdata->exit)
 		pdata->exit(pdev);
 err_init:
+	if (priv->phy1clk) {
+		clk_disable(priv->phy1clk);
+		clk_put(priv->phy1clk);
+	}
+err_clk_phy:
 	if (priv->ahbclk) {
 		clk_disable(priv->ahbclk);
 		clk_put(priv->ahbclk);
@@ -273,6 +294,10 @@
 		clk_disable(priv->ahbclk);
 		clk_put(priv->ahbclk);
 	}
+	if (priv->phy1clk) {
+		clk_disable(priv->phy1clk);
+		clk_put(priv->phy1clk);
+	}
 
 	kfree(priv);
 
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 116ae28..680f2ef 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -1,11 +1,12 @@
 /*
- * ehci-omap.c - driver for USBHOST on OMAP 34xx processor
+ * ehci-omap.c - driver for USBHOST on OMAP3/4 processors
  *
- * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller
- * Tested on OMAP3430 ES2.0 SDP
+ * Bus Glue for the EHCI controllers in OMAP3/4
+ * Tested on several OMAP3 boards, and OMAP4 Pandaboard
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2010 Texas Instruments, Inc.
  *	Author: Vikram Pandita <vikram.pandita@ti.com>
+ *	Author: Anand Gadiyar <gadiyar@ti.com>
  *
  * Copyright (C) 2009 Nokia Corporation
  *	Contact: Felipe Balbi <felipe.balbi@nokia.com>
@@ -26,11 +27,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- * TODO (last updated Feb 12, 2010):
+ * TODO (last updated Nov 21, 2010):
  *	- add kernel-doc
  *	- enable AUTOIDLE
  *	- add suspend/resume
  *	- move workarounds to board-files
+ *	- factor out code common to OHCI
+ *	- add HSIC and TLL support
+ *	- convert to use hwmod and runtime PM
  */
 
 #include <linux/platform_device.h>
@@ -86,9 +90,9 @@
 #define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
 
 #define OMAP_TLL_CHANNEL_COUNT				3
-#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 1)
-#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 2)
-#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 4)
+#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
+#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
+#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
 
 /* UHH Register Set */
 #define	OMAP_UHH_REVISION				(0x00)
@@ -114,6 +118,23 @@
 #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
 #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
 
+/* OMAP4-specific defines */
+#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR		(3 << 2)
+#define OMAP4_UHH_SYSCONFIG_NOIDLE			(1 << 2)
+
+#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR		(3 << 4)
+#define OMAP4_UHH_SYSCONFIG_NOSTDBY			(1 << 4)
+#define OMAP4_UHH_SYSCONFIG_SOFTRESET			(1 << 0)
+
+#define OMAP4_P1_MODE_CLEAR				(3 << 16)
+#define OMAP4_P1_MODE_TLL				(1 << 16)
+#define OMAP4_P1_MODE_HSIC				(3 << 16)
+#define OMAP4_P2_MODE_CLEAR				(3 << 18)
+#define OMAP4_P2_MODE_TLL				(1 << 18)
+#define OMAP4_P2_MODE_HSIC				(3 << 18)
+
+#define OMAP_REV2_TLL_CHANNEL_COUNT			2
+
 #define	OMAP_UHH_DEBUG_CSR				(0x44)
 
 /* EHCI Register Set */
@@ -127,6 +148,17 @@
 #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
 #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
 
+/* Values of UHH_REVISION - Note: these are not given in the TRM */
+#define OMAP_EHCI_REV1	0x00000010	/* OMAP3 */
+#define OMAP_EHCI_REV2	0x50700100	/* OMAP4 */
+
+#define is_omap_ehci_rev1(x)	(x->omap_ehci_rev == OMAP_EHCI_REV1)
+#define is_omap_ehci_rev2(x)	(x->omap_ehci_rev == OMAP_EHCI_REV2)
+
+#define is_ehci_phy_mode(x)	(x == EHCI_HCD_OMAP_MODE_PHY)
+#define is_ehci_tll_mode(x)	(x == EHCI_HCD_OMAP_MODE_TLL)
+#define is_ehci_hsic_mode(x)	(x == EHCI_HCD_OMAP_MODE_HSIC)
+
 /*-------------------------------------------------------------------------*/
 
 static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val)
@@ -156,10 +188,14 @@
 	struct device		*dev;
 
 	struct clk		*usbhost_ick;
-	struct clk		*usbhost2_120m_fck;
-	struct clk		*usbhost1_48m_fck;
+	struct clk		*usbhost_hs_fck;
+	struct clk		*usbhost_fs_fck;
 	struct clk		*usbtll_fck;
 	struct clk		*usbtll_ick;
+	struct clk		*xclk60mhsp1_ck;
+	struct clk		*xclk60mhsp2_ck;
+	struct clk		*utmi_p1_fck;
+	struct clk		*utmi_p2_fck;
 
 	/* FIXME the following two workarounds are
 	 * board specific not silicon-specific so these
@@ -176,6 +212,9 @@
 	/* phy reset workaround */
 	int			phy_reset;
 
+	/* IP revision */
+	u32			omap_ehci_rev;
+
 	/* desired phy_mode: TLL, PHY */
 	enum ehci_hcd_omap_mode	port_mode[OMAP3_HS_USB_PORTS];
 
@@ -191,13 +230,14 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask)
+static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask,
+				u8 tll_channel_count)
 {
 	unsigned reg;
 	int i;
 
 	/* Program the 3 TLL channels upfront */
-	for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
+	for (i = 0; i < tll_channel_count; i++) {
 		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
 
 		/* Disable AutoIdle, BitStuffing and use SDR Mode */
@@ -217,7 +257,7 @@
 	ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
 
 	/* Enable channels now */
-	for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
+	for (i = 0; i < tll_channel_count; i++) {
 		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
 
 		/* Enable only the reg that is needed */
@@ -286,19 +326,19 @@
 	}
 	clk_enable(omap->usbhost_ick);
 
-	omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck");
-	if (IS_ERR(omap->usbhost2_120m_fck)) {
-		ret = PTR_ERR(omap->usbhost2_120m_fck);
+	omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck");
+	if (IS_ERR(omap->usbhost_hs_fck)) {
+		ret = PTR_ERR(omap->usbhost_hs_fck);
 		goto err_host_120m_fck;
 	}
-	clk_enable(omap->usbhost2_120m_fck);
+	clk_enable(omap->usbhost_hs_fck);
 
-	omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck");
-	if (IS_ERR(omap->usbhost1_48m_fck)) {
-		ret = PTR_ERR(omap->usbhost1_48m_fck);
+	omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck");
+	if (IS_ERR(omap->usbhost_fs_fck)) {
+		ret = PTR_ERR(omap->usbhost_fs_fck);
 		goto err_host_48m_fck;
 	}
-	clk_enable(omap->usbhost1_48m_fck);
+	clk_enable(omap->usbhost_fs_fck);
 
 	if (omap->phy_reset) {
 		/* Refer: ISSUE1 */
@@ -333,6 +373,80 @@
 	}
 	clk_enable(omap->usbtll_ick);
 
+	omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base,
+						OMAP_UHH_REVISION);
+	dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n",
+					omap->omap_ehci_rev);
+
+	/*
+	 * Enable per-port clocks as needed (newer controllers only).
+	 * - External ULPI clock for PHY mode
+	 * - Internal clocks for TLL and HSIC modes (TODO)
+	 */
+	if (is_omap_ehci_rev2(omap)) {
+		switch (omap->port_mode[0]) {
+		case EHCI_HCD_OMAP_MODE_PHY:
+			omap->xclk60mhsp1_ck = clk_get(omap->dev,
+							"xclk60mhsp1_ck");
+			if (IS_ERR(omap->xclk60mhsp1_ck)) {
+				ret = PTR_ERR(omap->xclk60mhsp1_ck);
+				dev_err(omap->dev,
+					"Unable to get Port1 ULPI clock\n");
+			}
+
+			omap->utmi_p1_fck = clk_get(omap->dev,
+							"utmi_p1_gfclk");
+			if (IS_ERR(omap->utmi_p1_fck)) {
+				ret = PTR_ERR(omap->utmi_p1_fck);
+				dev_err(omap->dev,
+					"Unable to get utmi_p1_fck\n");
+			}
+
+			ret = clk_set_parent(omap->utmi_p1_fck,
+						omap->xclk60mhsp1_ck);
+			if (ret != 0) {
+				dev_err(omap->dev,
+					"Unable to set P1 f-clock\n");
+			}
+			break;
+		case EHCI_HCD_OMAP_MODE_TLL:
+			/* TODO */
+		default:
+			break;
+		}
+		switch (omap->port_mode[1]) {
+		case EHCI_HCD_OMAP_MODE_PHY:
+			omap->xclk60mhsp2_ck = clk_get(omap->dev,
+							"xclk60mhsp2_ck");
+			if (IS_ERR(omap->xclk60mhsp2_ck)) {
+				ret = PTR_ERR(omap->xclk60mhsp2_ck);
+				dev_err(omap->dev,
+					"Unable to get Port2 ULPI clock\n");
+			}
+
+			omap->utmi_p2_fck = clk_get(omap->dev,
+							"utmi_p2_gfclk");
+			if (IS_ERR(omap->utmi_p2_fck)) {
+				ret = PTR_ERR(omap->utmi_p2_fck);
+				dev_err(omap->dev,
+					"Unable to get utmi_p2_fck\n");
+			}
+
+			ret = clk_set_parent(omap->utmi_p2_fck,
+						omap->xclk60mhsp2_ck);
+			if (ret != 0) {
+				dev_err(omap->dev,
+					"Unable to set P2 f-clock\n");
+			}
+			break;
+		case EHCI_HCD_OMAP_MODE_TLL:
+			/* TODO */
+		default:
+			break;
+		}
+	}
+
+
 	/* perform TLL soft reset, and wait until reset is complete */
 	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
 			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
@@ -360,12 +474,20 @@
 
 	/* Put UHH in NoIdle/NoStandby mode */
 	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
-	reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
-			| OMAP_UHH_SYSCONFIG_SIDLEMODE
-			| OMAP_UHH_SYSCONFIG_CACTIVITY
-			| OMAP_UHH_SYSCONFIG_MIDLEMODE);
-	reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
+	if (is_omap_ehci_rev1(omap)) {
+		reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
+				| OMAP_UHH_SYSCONFIG_SIDLEMODE
+				| OMAP_UHH_SYSCONFIG_CACTIVITY
+				| OMAP_UHH_SYSCONFIG_MIDLEMODE);
+		reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
 
+
+	} else if (is_omap_ehci_rev2(omap)) {
+		reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
+		reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
+		reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
+		reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
+	}
 	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
 
 	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
@@ -376,40 +498,56 @@
 			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
 	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
 
-	if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
-	if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
-	if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
+	if (is_omap_ehci_rev1(omap)) {
+		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
+		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
+		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
 
-	/* Bypass the TLL module for PHY mode operation */
-	if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
-		dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
-		if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
-			(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
-				(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-		else
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-	} else {
-		dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
-		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-		else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
+		/* Bypass the TLL module for PHY mode operation */
+		if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
+			dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
+			if (is_ehci_phy_mode(omap->port_mode[0]) ||
+				is_ehci_phy_mode(omap->port_mode[1]) ||
+					is_ehci_phy_mode(omap->port_mode[2]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+		} else {
+			dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
+			if (is_ehci_phy_mode(omap->port_mode[0]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
+			else if (is_ehci_tll_mode(omap->port_mode[0]))
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
 
-		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-		else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
+			if (is_ehci_phy_mode(omap->port_mode[1]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
+			else if (is_ehci_tll_mode(omap->port_mode[1]))
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
 
-		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-		else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
+			if (is_ehci_phy_mode(omap->port_mode[2]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
+			else if (is_ehci_tll_mode(omap->port_mode[2]))
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
+		}
+	} else if (is_omap_ehci_rev2(omap)) {
+		/* Clear port mode fields for PHY mode*/
+		reg &= ~OMAP4_P1_MODE_CLEAR;
+		reg &= ~OMAP4_P2_MODE_CLEAR;
 
+		if (is_ehci_tll_mode(omap->port_mode[0]))
+			reg |= OMAP4_P1_MODE_TLL;
+		else if (is_ehci_hsic_mode(omap->port_mode[0]))
+			reg |= OMAP4_P1_MODE_HSIC;
+
+		if (is_ehci_tll_mode(omap->port_mode[1]))
+			reg |= OMAP4_P2_MODE_TLL;
+		else if (is_ehci_hsic_mode(omap->port_mode[1]))
+			reg |= OMAP4_P2_MODE_HSIC;
 	}
+
 	ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
 	dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
 
@@ -438,7 +576,7 @@
 			tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK;
 
 		/* Enable UTMI mode for required TLL channels */
-		omap_usb_utmi_init(omap, tll_ch_mask);
+		omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT);
 	}
 
 	if (omap->phy_reset) {
@@ -464,6 +602,14 @@
 	return 0;
 
 err_sys_status:
+	clk_disable(omap->utmi_p2_fck);
+	clk_put(omap->utmi_p2_fck);
+	clk_disable(omap->xclk60mhsp2_ck);
+	clk_put(omap->xclk60mhsp2_ck);
+	clk_disable(omap->utmi_p1_fck);
+	clk_put(omap->utmi_p1_fck);
+	clk_disable(omap->xclk60mhsp1_ck);
+	clk_put(omap->xclk60mhsp1_ck);
 	clk_disable(omap->usbtll_ick);
 	clk_put(omap->usbtll_ick);
 
@@ -472,8 +618,8 @@
 	clk_put(omap->usbtll_fck);
 
 err_tll_fck:
-	clk_disable(omap->usbhost1_48m_fck);
-	clk_put(omap->usbhost1_48m_fck);
+	clk_disable(omap->usbhost_fs_fck);
+	clk_put(omap->usbhost_fs_fck);
 
 	if (omap->phy_reset) {
 		if (gpio_is_valid(omap->reset_gpio_port[0]))
@@ -484,8 +630,8 @@
 	}
 
 err_host_48m_fck:
-	clk_disable(omap->usbhost2_120m_fck);
-	clk_put(omap->usbhost2_120m_fck);
+	clk_disable(omap->usbhost_hs_fck);
+	clk_put(omap->usbhost_hs_fck);
 
 err_host_120m_fck:
 	clk_disable(omap->usbhost_ick);
@@ -503,6 +649,8 @@
 
 	/* Reset OMAP modules for insmod/rmmod to work */
 	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
+			is_omap_ehci_rev2(omap) ?
+			OMAP4_UHH_SYSCONFIG_SOFTRESET :
 			OMAP_UHH_SYSCONFIG_SOFTRESET);
 	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
 				& (1 << 0))) {
@@ -550,16 +698,16 @@
 		omap->usbhost_ick = NULL;
 	}
 
-	if (omap->usbhost1_48m_fck != NULL) {
-		clk_disable(omap->usbhost1_48m_fck);
-		clk_put(omap->usbhost1_48m_fck);
-		omap->usbhost1_48m_fck = NULL;
+	if (omap->usbhost_fs_fck != NULL) {
+		clk_disable(omap->usbhost_fs_fck);
+		clk_put(omap->usbhost_fs_fck);
+		omap->usbhost_fs_fck = NULL;
 	}
 
-	if (omap->usbhost2_120m_fck != NULL) {
-		clk_disable(omap->usbhost2_120m_fck);
-		clk_put(omap->usbhost2_120m_fck);
-		omap->usbhost2_120m_fck = NULL;
+	if (omap->usbhost_hs_fck != NULL) {
+		clk_disable(omap->usbhost_hs_fck);
+		clk_put(omap->usbhost_hs_fck);
+		omap->usbhost_hs_fck = NULL;
 	}
 
 	if (omap->usbtll_ick != NULL) {
@@ -568,6 +716,32 @@
 		omap->usbtll_ick = NULL;
 	}
 
+	if (is_omap_ehci_rev2(omap)) {
+		if (omap->xclk60mhsp1_ck != NULL) {
+			clk_disable(omap->xclk60mhsp1_ck);
+			clk_put(omap->xclk60mhsp1_ck);
+			omap->xclk60mhsp1_ck = NULL;
+		}
+
+		if (omap->utmi_p1_fck != NULL) {
+			clk_disable(omap->utmi_p1_fck);
+			clk_put(omap->utmi_p1_fck);
+			omap->utmi_p1_fck = NULL;
+		}
+
+		if (omap->xclk60mhsp2_ck != NULL) {
+			clk_disable(omap->xclk60mhsp2_ck);
+			clk_put(omap->xclk60mhsp2_ck);
+			omap->xclk60mhsp2_ck = NULL;
+		}
+
+		if (omap->utmi_p2_fck != NULL) {
+			clk_disable(omap->utmi_p2_fck);
+			clk_put(omap->utmi_p2_fck);
+			omap->utmi_p2_fck = NULL;
+		}
+	}
+
 	if (omap->phy_reset) {
 		if (gpio_is_valid(omap->reset_gpio_port[0]))
 			gpio_free(omap->reset_gpio_port[0]);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 655f3c9..76179c3 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -22,6 +22,9 @@
 #error "This file is PCI bus glue.  CONFIG_PCI must be defined."
 #endif
 
+/* defined here to avoid adding to pci_ids.h for single instance use */
+#define PCI_DEVICE_ID_INTEL_CE4100_USB	0x2e70
+
 /*-------------------------------------------------------------------------*/
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -41,6 +44,35 @@
 	return 0;
 }
 
+static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci)
+{
+	struct pci_dev *amd_smbus_dev;
+	u8 rev = 0;
+
+	amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
+	if (!amd_smbus_dev)
+		return 0;
+
+	pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+	if (rev < 0x40) {
+		pci_dev_put(amd_smbus_dev);
+		amd_smbus_dev = NULL;
+		return 0;
+	}
+
+	if (!amd_nb_dev)
+		amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
+	if (!amd_nb_dev)
+		ehci_err(ehci, "QUIRK: unable to get AMD NB device\n");
+
+	ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n");
+
+	pci_dev_put(amd_smbus_dev);
+	amd_smbus_dev = NULL;
+
+	return 1;
+}
+
 /* called during probe() after chip reset completes */
 static int ehci_pci_setup(struct usb_hcd *hcd)
 {
@@ -99,6 +131,9 @@
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
+	if (ehci_quirk_amd_SB800(ehci))
+		ehci->amd_l1_fix = 1;
+
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
@@ -137,6 +172,10 @@
 			ehci_info(ehci, "disable lpm for langwell/penwell\n");
 			ehci->has_lpm = 0;
 		}
+		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) {
+			hcd->has_tt = 1;
+			tdi_reset(ehci);
+		}
 		break;
 	case PCI_VENDOR_ID_TDI:
 		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index d9f78eb..aa46f57 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1590,6 +1590,63 @@
 	*hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
 }
 
+#define AB_REG_BAR_LOW 0xe0
+#define AB_REG_BAR_HIGH 0xe1
+#define AB_INDX(addr) ((addr) + 0x00)
+#define AB_DATA(addr) ((addr) + 0x04)
+#define NB_PCIE_INDX_ADDR 0xe0
+#define NB_PCIE_INDX_DATA 0xe4
+#define NB_PIF0_PWRDOWN_0 0x01100012
+#define NB_PIF0_PWRDOWN_1 0x01100013
+
+static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable)
+{
+	u32 addr, addr_low, addr_high, val;
+
+	outb_p(AB_REG_BAR_LOW, 0xcd6);
+	addr_low = inb_p(0xcd7);
+	outb_p(AB_REG_BAR_HIGH, 0xcd6);
+	addr_high = inb_p(0xcd7);
+	addr = addr_high << 8 | addr_low;
+	outl_p(0x30, AB_INDX(addr));
+	outl_p(0x40, AB_DATA(addr));
+	outl_p(0x34, AB_INDX(addr));
+	val = inl_p(AB_DATA(addr));
+
+	if (disable) {
+		val &= ~0x8;
+		val |= (1 << 4) | (1 << 9);
+	} else {
+		val |= 0x8;
+		val &= ~((1 << 4) | (1 << 9));
+	}
+	outl_p(val, AB_DATA(addr));
+
+	if (amd_nb_dev) {
+		addr = NB_PIF0_PWRDOWN_0;
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
+
+		addr = NB_PIF0_PWRDOWN_1;
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
+	}
+
+	return;
+}
+
 /* fit urb's itds into the selected schedule slot; activate as needed */
 static int
 itd_link_urb (
@@ -1616,6 +1673,12 @@
 			urb->interval,
 			next_uframe >> 3, next_uframe & 0x7);
 	}
+
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 1);
+	}
+
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
 	/* fill iTDs uframe by uframe */
@@ -1740,6 +1803,11 @@
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 0);
+	}
+
 	if (unlikely(list_is_singular(&stream->td_list))) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
@@ -2025,6 +2093,12 @@
 			(next_uframe >> 3) & (ehci->periodic_size - 1),
 			stream->interval, hc32_to_cpu(ehci, stream->splits));
 	}
+
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 1);
+	}
+
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
 	/* fill sITDs frame by frame */
@@ -2125,6 +2199,11 @@
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 0);
+	}
+
 	if (list_is_singular(&stream->td_list)) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
new file mode 100644
index 0000000..595f70f
--- /dev/null
+++ b/drivers/usb/host/ehci-sh.c
@@ -0,0 +1,243 @@
+/*
+ * SuperH EHCI host controller driver
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * Based on ohci-sh.c and ehci-atmel.c.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+struct ehci_sh_priv {
+	struct clk *iclk, *fclk;
+	struct usb_hcd *hcd;
+};
+
+static int ehci_sh_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int ret;
+
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci,
+		&ehci->caps->hc_capbase));
+
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	ret = ehci_halt(ehci);
+	if (unlikely(ret))
+		return ret;
+
+	ret = ehci_init(hcd);
+	if (unlikely(ret))
+		return ret;
+
+	ehci->sbrn = 0x20;
+
+	ehci_reset(ehci);
+	ehci_port_power(ehci, 0);
+
+	return ret;
+}
+
+static const struct hc_driver ehci_sh_hc_driver = {
+	.description			= hcd_name,
+	.product_desc			= "SuperH EHCI",
+	.hcd_priv_size			= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq				= ehci_irq,
+	.flags				= HCD_USB2 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset				= ehci_sh_reset,
+	.start				= ehci_run,
+	.stop				= ehci_stop,
+	.shutdown			= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue			= ehci_urb_enqueue,
+	.urb_dequeue			= ehci_urb_dequeue,
+	.endpoint_disable		= ehci_endpoint_disable,
+	.endpoint_reset			= ehci_endpoint_reset,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number		= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data		= ehci_hub_status_data,
+	.hub_control			= ehci_hub_control,
+
+#ifdef CONFIG_PM
+	.bus_suspend			= ehci_bus_suspend,
+	.bus_resume			= ehci_bus_resume,
+#endif
+
+	.relinquish_port		= ehci_relinquish_port,
+	.port_handed_over		= ehci_port_handed_over,
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_hcd_sh_probe(struct platform_device *pdev)
+{
+	const struct hc_driver *driver = &ehci_sh_hc_driver;
+	struct resource *res;
+	struct ehci_sh_priv *priv;
+	struct usb_hcd *hcd;
+	int irq, ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		ret = -ENODEV;
+		goto fail_create_hcd;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(&pdev->dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		ret = -ENODEV;
+		goto fail_create_hcd;
+	}
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev,
+			     dev_name(&pdev->dev));
+	if (!hcd) {
+		ret = -ENOMEM;
+		goto fail_create_hcd;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				driver->description)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		ret = -EBUSY;
+		goto fail_request_resource;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		ret = -ENXIO;
+		goto fail_ioremap;
+	}
+
+	priv = kmalloc(sizeof(struct ehci_sh_priv), GFP_KERNEL);
+	if (!priv) {
+		dev_dbg(&pdev->dev, "error allocating priv data\n");
+		ret = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	/* These are optional, we don't care if they fail */
+	priv->fclk = clk_get(&pdev->dev, "usb_fck");
+	if (IS_ERR(priv->fclk))
+		priv->fclk = NULL;
+
+	priv->iclk = clk_get(&pdev->dev, "usb_ick");
+	if (IS_ERR(priv->iclk))
+		priv->iclk = NULL;
+
+	clk_enable(priv->fclk);
+	clk_enable(priv->iclk);
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to add hcd");
+		goto fail_add_hcd;
+	}
+
+	priv->hcd = hcd;
+	platform_set_drvdata(pdev, priv);
+
+	return ret;
+
+fail_add_hcd:
+	clk_disable(priv->iclk);
+	clk_disable(priv->fclk);
+
+	clk_put(priv->iclk);
+	clk_put(priv->fclk);
+
+	kfree(priv);
+fail_alloc:
+	iounmap(hcd->regs);
+fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+fail_request_resource:
+	usb_put_hcd(hcd);
+fail_create_hcd:
+	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret);
+
+	return ret;
+}
+
+static int __exit ehci_hcd_sh_remove(struct platform_device *pdev)
+{
+	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = priv->hcd;
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
+
+	clk_disable(priv->fclk);
+	clk_disable(priv->iclk);
+
+	clk_put(priv->fclk);
+	clk_put(priv->iclk);
+
+	kfree(priv);
+
+	return 0;
+}
+
+static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
+{
+	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = priv->hcd;
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+}
+
+static struct platform_driver ehci_hcd_sh_driver = {
+	.probe		= ehci_hcd_sh_probe,
+	.remove		= __exit_p(ehci_hcd_sh_remove),
+	.shutdown	= ehci_hcd_sh_shutdown,
+	.driver		= {
+		.name	= "sh_ehci",
+		.owner	= THIS_MODULE,
+	},
+};
+
+MODULE_ALIAS("platform:sh_ehci");
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
new file mode 100644
index 0000000..75c0087
--- /dev/null
+++ b/drivers/usb/host/ehci-spear.c
@@ -0,0 +1,212 @@
+/*
+* Driver for EHCI HCD on SPEAR SOC
+*
+* Copyright (C) 2010 ST Micro Electronics,
+* Deepak Sikri <deepak.sikri@st.com>
+*
+* Based on various ehci-*.c drivers
+*
+* 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/platform_device.h>
+#include <linux/clk.h>
+
+struct spear_ehci {
+	struct ehci_hcd ehci;
+	struct clk *clk;
+};
+
+#define to_spear_ehci(hcd)	(struct spear_ehci *)hcd_to_ehci(hcd)
+
+static void spear_start_ehci(struct spear_ehci *ehci)
+{
+	clk_enable(ehci->clk);
+}
+
+static void spear_stop_ehci(struct spear_ehci *ehci)
+{
+	clk_disable(ehci->clk);
+}
+
+static int ehci_spear_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval = 0;
+
+	/* registers start at offset 0x0 */
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci,
+				&ehci->caps->hc_capbase));
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci_reset(ehci);
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+static const struct hc_driver ehci_spear_hc_driver = {
+	.description			= hcd_name,
+	.product_desc			= "SPEAr EHCI",
+	.hcd_priv_size			= sizeof(struct spear_ehci),
+
+	/* generic hardware linkage */
+	.irq				= ehci_irq,
+	.flags				= HCD_MEMORY | HCD_USB2,
+
+	/* basic lifecycle operations */
+	.reset				= ehci_spear_setup,
+	.start				= ehci_run,
+	.stop				= ehci_stop,
+	.shutdown			= ehci_shutdown,
+
+	/* managing i/o requests and associated device resources */
+	.urb_enqueue			= ehci_urb_enqueue,
+	.urb_dequeue			= ehci_urb_dequeue,
+	.endpoint_disable		= ehci_endpoint_disable,
+	.endpoint_reset			= ehci_endpoint_reset,
+
+	/* scheduling support */
+	.get_frame_number		= ehci_get_frame,
+
+	/* root hub support */
+	.hub_status_data		= ehci_hub_status_data,
+	.hub_control			= ehci_hub_control,
+	.bus_suspend			= ehci_bus_suspend,
+	.bus_resume			= ehci_bus_resume,
+	.relinquish_port		= ehci_relinquish_port,
+	.port_handed_over		= ehci_port_handed_over,
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd ;
+	struct spear_ehci *ehci;
+	struct resource *res;
+	struct clk *usbh_clk;
+	const struct hc_driver *driver = &ehci_spear_hc_driver;
+	int *pdata = pdev->dev.platform_data;
+	int irq, retval;
+	char clk_name[20] = "usbh_clk";
+
+	if (pdata == NULL)
+		return -EFAULT;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		retval = irq;
+		goto fail_irq_get;
+	}
+
+	if (*pdata >= 0)
+		sprintf(clk_name, "usbh.%01d_clk", *pdata);
+
+	usbh_clk = clk_get(NULL, clk_name);
+	if (IS_ERR(usbh_clk)) {
+		dev_err(&pdev->dev, "Error getting interface clock\n");
+		retval = PTR_ERR(usbh_clk);
+		goto fail_get_usbh_clk;
+	}
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto fail_create_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		retval = -ENODEV;
+		goto fail_request_resource;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				driver->description)) {
+		retval = -EBUSY;
+		goto fail_request_resource;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		retval = -ENOMEM;
+		goto fail_ioremap;
+	}
+
+	ehci = (struct spear_ehci *)hcd_to_ehci(hcd);
+	ehci->clk = usbh_clk;
+
+	spear_start_ehci(ehci);
+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED);
+	if (retval)
+		goto fail_add_hcd;
+
+	return retval;
+
+fail_add_hcd:
+	spear_stop_ehci(ehci);
+	iounmap(hcd->regs);
+fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+fail_request_resource:
+	usb_put_hcd(hcd);
+fail_create_hcd:
+	clk_put(usbh_clk);
+fail_get_usbh_clk:
+fail_irq_get:
+	dev_err(&pdev->dev, "init fail, %d\n", retval);
+
+	return retval ;
+}
+
+static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct spear_ehci *ehci_p = to_spear_ehci(hcd);
+
+	if (!hcd)
+		return 0;
+	if (in_interrupt())
+		BUG();
+	usb_remove_hcd(hcd);
+
+	if (ehci_p->clk)
+		spear_stop_ehci(ehci_p);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	if (ehci_p->clk)
+		clk_put(ehci_p->clk);
+
+	return 0;
+}
+
+static struct platform_driver spear_ehci_hcd_driver = {
+	.probe		= spear_ehci_hcd_drv_probe,
+	.remove		= spear_ehci_hcd_drv_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.name = "spear-ehci",
+		.bus = &platform_bus_type
+	}
+};
+
+MODULE_ALIAS("platform:spear-ehci");
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
new file mode 100644
index 0000000..2016806
--- /dev/null
+++ b/drivers/usb/host/ehci-vt8500.c
@@ -0,0 +1,172 @@
+/*
+ * drivers/usb/host/ehci-vt8500.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on ehci-au1xxx.c
+ *
+ * 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/platform_device.h>
+
+static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int rc = 0;
+
+	if (!udev->parent) /* udev is root hub itself, impossible */
+		rc = -1;
+	/* we only support lpm device connected to root hub yet */
+	if (ehci->has_lpm && !udev->parent->parent) {
+		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+		if (!rc)
+			rc = ehci_lpm_check(ehci, udev->portnum);
+	}
+	return rc;
+}
+
+static const struct hc_driver vt8500_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "VT8500 EHCI",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= ehci_init,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	/*
+	 * call back when device connected and addressed
+	 */
+	.update_device =	ehci_update_device,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int vt8500_ehci_drv_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
+	struct resource *res;
+	int ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+		pr_debug("resource[1] is not IORESOURCE_IRQ");
+		return -ENOMEM;
+	}
+	hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500");
+	if (!hcd)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_debug("request_mem_region failed");
+		ret = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
+
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+
+	ehci_port_power(ehci, 1);
+
+	ret = usb_add_hcd(hcd, pdev->resource[1].start,
+			  IRQF_DISABLED | IRQF_SHARED);
+	if (ret == 0) {
+		platform_set_drvdata(pdev, hcd);
+		return ret;
+	}
+
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int vt8500_ehci_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver vt8500_ehci_driver = {
+	.probe		= vt8500_ehci_drv_probe,
+	.remove		= vt8500_ehci_drv_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver = {
+		.name	= "vt8500-ehci",
+		.owner	= THIS_MODULE,
+	}
+};
+
+MODULE_ALIAS("platform:vt8500-ehci");
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index cfa21ea..6bc3580 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -130,6 +130,7 @@
 	.urb_enqueue = ehci_urb_enqueue,
 	.urb_dequeue = ehci_urb_dequeue,
 	.endpoint_disable = ehci_endpoint_disable,
+	.endpoint_reset = ehci_endpoint_reset,
 
 	/*
 	 * scheduling support
@@ -147,6 +148,8 @@
 #endif
 	.relinquish_port	= ehci_relinquish_port,
 	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
 static int __devinit ehci_w90x900_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 6c8076a..e8f4f36 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -117,6 +117,7 @@
 	.urb_enqueue		= ehci_urb_enqueue,
 	.urb_dequeue		= ehci_urb_dequeue,
 	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
 
 	/*
 	 * scheduling support
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index ba8eab3..799ac16 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -131,6 +131,7 @@
 	unsigned		has_amcc_usb23:1;
 	unsigned		need_io_watchdog:1;
 	unsigned		broken_periodic:1;
+	unsigned		amd_l1_fix:1;
 	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
 
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
new file mode 100644
index 0000000..f05ef87
--- /dev/null
+++ b/drivers/usb/host/ohci-cns3xxx.c
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/atomic.h>
+#include <mach/cns3xxx.h>
+#include <mach/pm.h>
+
+static int __devinit
+cns3xxx_ohci_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	int ret;
+
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 *
+	 * Set USB AHB INCR length to 16
+	 */
+	if (atomic_inc_return(&usb_pwr_ref) == 1) {
+		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+			MISC_CHIP_CONFIG_REG);
+	}
+
+	ret = ohci_init(ohci);
+	if (ret < 0)
+		return ret;
+
+	ohci->num_ports = 1;
+
+	ret = ohci_run(ohci);
+	if (ret < 0) {
+		err("can't start %s", hcd->self.bus_name);
+		ohci_stop(hcd);
+		return ret;
+	}
+	return 0;
+}
+
+static const struct hc_driver cns3xxx_ohci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "CNS3XXX OHCI Host controller",
+	.hcd_priv_size		= sizeof(struct ohci_hcd),
+	.irq			= ohci_irq,
+	.flags			= HCD_USB11 | HCD_MEMORY,
+	.start			= cns3xxx_ohci_start,
+	.stop			= ohci_stop,
+	.shutdown		= ohci_shutdown,
+	.urb_enqueue		= ohci_urb_enqueue,
+	.urb_dequeue		= ohci_urb_dequeue,
+	.endpoint_disable	= ohci_endpoint_disable,
+	.get_frame_number	= ohci_get_frame,
+	.hub_status_data	= ohci_hub_status_data,
+	.hub_control		= ohci_hub_control,
+#ifdef CONFIG_PM
+	.bus_suspend		= ohci_bus_suspend,
+	.bus_resume		= ohci_bus_resume,
+#endif
+	.start_port_reset	= ohci_start_port_reset,
+};
+
+static int cns3xxx_ohci_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct usb_hcd *hcd;
+	const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
+	struct resource *res;
+	int irq;
+	int retval;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "Found HC with no IRQ.\n");
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	hcd = usb_create_hcd(driver, dev, dev_name(dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "Found HC with no register addr.\n");
+		retval = -ENODEV;
+		goto err1;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+			driver->description)) {
+		dev_dbg(dev, "controller already in use\n");
+		retval = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_dbg(dev, "error mapping memory\n");
+		retval = -EFAULT;
+		goto err2;
+	}
+
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (retval == 0)
+		return retval;
+
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+	return retval;
+}
+
+static int cns3xxx_ohci_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	/*
+	 * EHCI and OHCI share the same clock and power,
+	 * resetting twice would cause the 1st controller been reset.
+	 * Therefore only do power up  at the first up device, and
+	 * power down at the last down device.
+	 */
+	if (atomic_dec_return(&usb_pwr_ref) == 0)
+		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+
+	usb_put_hcd(hcd);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:cns3xxx-ohci");
+
+static struct platform_driver ohci_hcd_cns3xxx_driver = {
+	.probe = cns3xxx_ohci_probe,
+	.remove = cns3xxx_ohci_remove,
+	.driver = {
+		.name = "cns3xxx-ohci",
+	},
+};
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 5179acb..759a12f 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -901,7 +901,8 @@
 
 	ohci_dump (ohci, 1);
 
-	flush_scheduled_work();
+	if (quirk_nec(ohci))
+		flush_work_sync(&ohci->nec_work);
 
 	ohci_usb_reset (ohci);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
@@ -1081,6 +1082,11 @@
 #define OF_PLATFORM_DRIVER	ohci_hcd_ppc_of_driver
 #endif
 
+#ifdef CONFIG_PLAT_SPEAR
+#include "ohci-spear.c"
+#define PLATFORM_DRIVER		spear_ohci_hcd_driver
+#endif
+
 #ifdef CONFIG_PPC_PS3
 #include "ohci-ps3.c"
 #define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_driver
@@ -1111,6 +1117,11 @@
 #define PLATFORM_DRIVER		ohci_octeon_driver
 #endif
 
+#ifdef CONFIG_USB_CNS3XXX_OHCI
+#include "ohci-cns3xxx.c"
+#define PLATFORM_DRIVER		ohci_hcd_cns3xxx_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(OMAP1_PLATFORM_DRIVER) &&	\
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 2cc8a50..a37d599 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -648,7 +648,7 @@
 
 	ret = omap3_start_ohci(omap, hcd);
 	if (ret) {
-		dev_dbg(&pdev->dev, "failed to start ehci\n");
+		dev_dbg(&pdev->dev, "failed to start ohci\n");
 		goto err_start;
 	}
 
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index 0b35d22..f47867f 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -109,7 +109,7 @@
 	hcd->regs = (void __iomem *)res->start;
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
-	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (ret != 0) {
 		err("Failed to add hcd");
 		usb_put_hcd(hcd);
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
new file mode 100644
index 0000000..4fd4bea
--- /dev/null
+++ b/drivers/usb/host/ohci-spear.c
@@ -0,0 +1,240 @@
+/*
+* OHCI HCD (Host Controller Driver) for USB.
+*
+* Copyright (C) 2010 ST Microelectronics.
+* Deepak Sikri<deepak.sikri@st.com>
+*
+* Based on various ohci-*.c drivers
+*
+* 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/signal.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+struct spear_ohci {
+	struct ohci_hcd ohci;
+	struct clk *clk;
+};
+
+#define to_spear_ohci(hcd)	(struct spear_ohci *)hcd_to_ohci(hcd)
+
+static void spear_start_ohci(struct spear_ohci *ohci)
+{
+	clk_enable(ohci->clk);
+}
+
+static void spear_stop_ohci(struct spear_ohci *ohci)
+{
+	clk_disable(ohci->clk);
+}
+
+static int __devinit ohci_spear_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int ret;
+
+	ret = ohci_init(ohci);
+	if (ret < 0)
+		return ret;
+	ohci->regs = hcd->regs;
+
+	ret = ohci_run(ohci);
+	if (ret < 0) {
+		dev_err(hcd->self.controller, "can't start\n");
+		ohci_stop(hcd);
+		return ret;
+	}
+
+	create_debug_files(ohci);
+
+#ifdef DEBUG
+	ohci_dump(ohci, 1);
+#endif
+	return 0;
+}
+
+static const struct hc_driver ohci_spear_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "SPEAr OHCI",
+	.hcd_priv_size		= sizeof(struct spear_ohci),
+
+	/* generic hardware linkage */
+	.irq			= ohci_irq,
+	.flags			= HCD_USB11 | HCD_MEMORY,
+
+	/* basic lifecycle operations */
+	.start			= ohci_spear_start,
+	.stop			= ohci_stop,
+	.shutdown		= ohci_shutdown,
+#ifdef	CONFIG_PM
+	.bus_suspend		= ohci_bus_suspend,
+	.bus_resume		= ohci_bus_resume,
+#endif
+
+	/* managing i/o requests and associated device resources */
+	.urb_enqueue		= ohci_urb_enqueue,
+	.urb_dequeue		= ohci_urb_dequeue,
+	.endpoint_disable	= ohci_endpoint_disable,
+
+	/* scheduling support */
+	.get_frame_number	= ohci_get_frame,
+
+	/* root hub support */
+	.hub_status_data	= ohci_hub_status_data,
+	.hub_control		= ohci_hub_control,
+
+	.start_port_reset	= ohci_start_port_reset,
+};
+
+static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
+{
+	const struct hc_driver *driver = &ohci_spear_hc_driver;
+	struct usb_hcd *hcd = NULL;
+	struct clk *usbh_clk;
+	struct spear_ohci *ohci_p;
+	struct resource *res;
+	int retval, irq;
+	int *pdata = pdev->dev.platform_data;
+	char clk_name[20] = "usbh_clk";
+
+	if (pdata == NULL)
+		return -EFAULT;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		retval = irq;
+		goto fail_irq_get;
+	}
+
+	if (*pdata >= 0)
+		sprintf(clk_name, "usbh.%01d_clk", *pdata);
+
+	usbh_clk = clk_get(NULL, clk_name);
+	if (IS_ERR(usbh_clk)) {
+		dev_err(&pdev->dev, "Error getting interface clock\n");
+		retval = PTR_ERR(usbh_clk);
+		goto fail_get_usbh_clk;
+	}
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto fail_create_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		retval = -ENODEV;
+		goto fail_request_resource;
+	}
+
+	hcd->rsrc_start = pdev->resource[0].start;
+	hcd->rsrc_len = resource_size(res);
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		retval = -EBUSY;
+		goto fail_request_resource;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_dbg(&pdev->dev, "ioremap failed\n");
+		retval = -ENOMEM;
+		goto fail_ioremap;
+	}
+
+	ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
+	ohci_p->clk = usbh_clk;
+	spear_start_ohci(ohci_p);
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), IRQF_DISABLED);
+	if (retval == 0)
+		return retval;
+
+	spear_stop_ohci(ohci_p);
+	iounmap(hcd->regs);
+fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+fail_request_resource:
+	usb_put_hcd(hcd);
+fail_create_hcd:
+	clk_put(usbh_clk);
+fail_get_usbh_clk:
+fail_irq_get:
+	dev_err(&pdev->dev, "init fail, %d\n", retval);
+
+	return retval;
+}
+
+static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+
+	usb_remove_hcd(hcd);
+	if (ohci_p->clk)
+		spear_stop_ohci(ohci_p);
+
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	if (ohci_p->clk)
+		clk_put(ohci_p->clk);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+#if defined(CONFIG_PM)
+static int spear_ohci_hcd_drv_suspend(struct platform_device *dev,
+		pm_message_t message)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	spear_stop_ohci(ohci_p);
+	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+	return 0;
+}
+
+static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	spear_start_ohci(ohci_p);
+	ohci_finish_controller_resume(hcd);
+	return 0;
+}
+#endif
+
+/* Driver definition to register with the platform bus */
+static struct platform_driver spear_ohci_hcd_driver = {
+	.probe =	spear_ohci_hcd_drv_probe,
+	.remove =	spear_ohci_hcd_drv_remove,
+#ifdef CONFIG_PM
+	.suspend =	spear_ohci_hcd_drv_suspend,
+	.resume =	spear_ohci_hcd_drv_resume,
+#endif
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "spear-ohci",
+	},
+};
+
+MODULE_ALIAS("platform:spear-ohci");
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index f52d04d..cee8678 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -569,7 +569,7 @@
  */
 static void uhci_shutdown(struct pci_dev *pdev)
 {
-	struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
+	struct usb_hcd *hcd = pci_get_drvdata(pdev);
 
 	uhci_hc_died(hcd_to_uhci(hcd));
 }
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 2090b45..af77abb 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -29,7 +29,7 @@
 {
 	if (uhci->is_stopped)
 		mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
-	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
+	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
 }
 
 static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
@@ -195,7 +195,9 @@
 		} else {
 			struct uhci_td *ntd;
 
-			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
+			ntd = list_entry(td->fl_list.next,
+					 struct uhci_td,
+					 fl_list);
 			uhci->frame[td->frame] = LINK_TO_TD(ntd);
 			uhci->frame_cpu[td->frame] = ntd;
 		}
@@ -728,7 +730,7 @@
 
 	urbp->urb = urb;
 	urb->hcpriv = urbp;
-	
+
 	INIT_LIST_HEAD(&urbp->node);
 	INIT_LIST_HEAD(&urbp->td_list);
 
@@ -846,7 +848,7 @@
 
 		/* Alternate Data0/1 (start with Data1) */
 		destination ^= TD_TOKEN_TOGGLE;
-	
+
 		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
 				data);
@@ -857,7 +859,7 @@
 	}
 
 	/*
-	 * Build the final TD for control status 
+	 * Build the final TD for control status
 	 */
 	td = uhci_alloc_td(uhci);
 	if (!td)
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index 72b6892..9546f6c 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -356,7 +356,7 @@
 module_exit(whci_hc_driver_exit);
 
 /* PCI device ID's that we handle (so it gets loaded) */
-static struct pci_device_id whci_hcd_id_table[] = {
+static struct pci_device_id __used whci_hcd_id_table[] = {
 	{ PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) },
 	{ /* empty last entry */ }
 };
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index c96f51d..1732d9b 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -1,5 +1,5 @@
 /*
- * USB LED driver - 1.1
+ * USB LED driver
  *
  * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
  *
@@ -20,12 +20,17 @@
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
 #define DRIVER_DESC "USB LED Driver"
 
-#define VENDOR_ID	0x0fc5
-#define PRODUCT_ID	0x1223
+enum led_type {
+	DELCOM_VISUAL_SIGNAL_INDICATOR,
+	DREAM_CHEEKY_WEBMAIL_NOTIFIER,
+};
 
 /* table of devices that work with this driver */
 static const struct usb_device_id id_table[] = {
-	{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
+	{ USB_DEVICE(0x0fc5, 0x1223),
+			.driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR },
+	{ USB_DEVICE(0x1d34, 0x0004),
+			.driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },
 	{ },
 };
 MODULE_DEVICE_TABLE (usb, id_table);
@@ -35,15 +40,12 @@
 	unsigned char		blue;
 	unsigned char		red;
 	unsigned char		green;
+	enum led_type		type;
 };
 
-#define BLUE	0x04
-#define RED	0x02
-#define GREEN	0x01
 static void change_color(struct usb_led *led)
 {
 	int retval;
-	unsigned char color = 0x07;
 	unsigned char *buffer;
 
 	buffer = kmalloc(8, GFP_KERNEL);
@@ -52,25 +54,59 @@
 		return;
 	}
 
-	if (led->blue)
-		color &= ~(BLUE);
-	if (led->red)
-		color &= ~(RED);
-	if (led->green)
-		color &= ~(GREEN);
-	dev_dbg(&led->udev->dev,
-		"blue = %d, red = %d, green = %d, color = %.2x\n",
-		led->blue, led->red, led->green, color);
+	switch (led->type) {
+	case DELCOM_VISUAL_SIGNAL_INDICATOR: {
+		unsigned char color = 0x07;
 
-	retval = usb_control_msg(led->udev,
-				usb_sndctrlpipe(led->udev, 0),
-				0x12,
-				0xc8,
-				(0x02 * 0x100) + 0x0a,
-				(0x00 * 0x100) + color,
-				buffer,	
-				8,
-				2000);
+		if (led->blue)
+			color &= ~0x04;
+		if (led->red)
+			color &= ~0x02;
+		if (led->green)
+			color &= ~0x01;
+		dev_dbg(&led->udev->dev,
+			"blue = %d, red = %d, green = %d, color = %.2x\n",
+			led->blue, led->red, led->green, color);
+
+		retval = usb_control_msg(led->udev,
+					usb_sndctrlpipe(led->udev, 0),
+					0x12,
+					0xc8,
+					(0x02 * 0x100) + 0x0a,
+					(0x00 * 0x100) + color,
+					buffer,
+					8,
+					2000);
+		break;
+	}
+
+	case DREAM_CHEEKY_WEBMAIL_NOTIFIER:
+		dev_dbg(&led->udev->dev,
+			"red = %d, green = %d, blue = %d\n",
+			led->red, led->green, led->blue);
+
+		buffer[0] = led->red;
+		buffer[1] = led->green;
+		buffer[2] = led->blue;
+		buffer[3] = buffer[4] = buffer[5] = 0;
+		buffer[6] = 0x1a;
+		buffer[7] = 0x05;
+
+		retval = usb_control_msg(led->udev,
+					usb_sndctrlpipe(led->udev, 0),
+					0x09,
+					0x21,
+					0x200,
+					0,
+					buffer,
+					8,
+					2000);
+		break;
+
+	default:
+		dev_err(&led->udev->dev, "unknown device type %d\n", led->type);
+	}
+
 	if (retval)
 		dev_dbg(&led->udev->dev, "retval = %d\n", retval);
 	kfree(buffer);
@@ -107,11 +143,12 @@
 
 	dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL);
 	if (dev == NULL) {
-		dev_err(&interface->dev, "Out of memory\n");
+		dev_err(&interface->dev, "out of memory\n");
 		goto error_mem;
 	}
 
 	dev->udev = usb_get_dev(udev);
+	dev->type = id->driver_info;
 
 	usb_set_intfdata (interface, dev);
 
@@ -125,6 +162,31 @@
 	if (retval)
 		goto error;
 
+	if (dev->type == DREAM_CHEEKY_WEBMAIL_NOTIFIER) {
+		unsigned char *enable;
+
+		enable = kmemdup("\x1f\x02\0\x5f\0\0\x1a\x03", 8, GFP_KERNEL);
+		if (!enable) {
+			dev_err(&interface->dev, "out of memory\n");
+			retval = -ENOMEM;
+			goto error;
+		}
+
+		retval = usb_control_msg(udev,
+					usb_sndctrlpipe(udev, 0),
+					0x09,
+					0x21,
+					0x200,
+					0,
+					enable,
+					8,
+					2000);
+
+		kfree(enable);
+		if (retval != 8)
+			goto error;
+	}
+
 	dev_info(&interface->dev, "USB LED device now attached\n");
 	return 0;
 
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index c436e1e..a09dbd2 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -436,6 +436,28 @@
 	return length;
 }
 
+/*
+ * This is the look-ahead pass in case of 'C Zi', when actual_length cannot
+ * be used to determine the length of the whole contiguous buffer.
+ */
+static unsigned int mon_bin_collate_isodesc(const struct mon_reader_bin *rp,
+    struct urb *urb, unsigned int ndesc)
+{
+	struct usb_iso_packet_descriptor *fp;
+	unsigned int length;
+
+	length = 0;
+	fp = urb->iso_frame_desc;
+	while (ndesc-- != 0) {
+		if (fp->actual_length != 0) {
+			if (fp->offset + fp->actual_length > length)
+				length = fp->offset + fp->actual_length;
+		}
+		fp++;
+	}
+	return length;
+}
+
 static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
     unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
 {
@@ -478,6 +500,10 @@
 	/*
 	 * Find the maximum allowable length, then allocate space.
 	 */
+	urb_length = (ev_type == 'S') ?
+	    urb->transfer_buffer_length : urb->actual_length;
+	length = urb_length;
+
 	if (usb_endpoint_xfer_isoc(epd)) {
 		if (urb->number_of_packets < 0) {
 			ndesc = 0;
@@ -486,14 +512,16 @@
 		} else {
 			ndesc = urb->number_of_packets;
 		}
+		if (ev_type == 'C' && usb_urb_dir_in(urb))
+			length = mon_bin_collate_isodesc(rp, urb, ndesc);
 	} else {
 		ndesc = 0;
 	}
 	lendesc = ndesc*sizeof(struct mon_bin_isodesc);
 
-	urb_length = (ev_type == 'S') ?
-	    urb->transfer_buffer_length : urb->actual_length;
-	length = urb_length;
+	/* not an issue unless there's a subtle bug in a HCD somewhere */
+	if (length >= urb->transfer_buffer_length)
+		length = urb->transfer_buffer_length;
 
 	if (length >= rp->b_size/5)
 		length = rp->b_size/5;
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 341a37a..4cbb7e4 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -12,6 +12,7 @@
 	depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523))
 	select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
 	select TWL4030_USB if MACH_OMAP_3430SDP
+	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
 	select USB_OTG_UTILS
 	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 	help
@@ -30,57 +31,41 @@
 	  If you do not know what this is, please say N.
 
 	  To compile this driver as a module, choose M here; the
-	  module will be called "musb_hdrc".
+	  module will be called "musb-hdrc".
 
-config USB_MUSB_SOC
-	boolean
+choice
+	prompt "Platform Glue Layer"
 	depends on USB_MUSB_HDRC
-	default y if ARCH_DAVINCI
-	default y if ARCH_OMAP2430
-	default y if ARCH_OMAP3
-	default y if ARCH_OMAP4
-	default y if (BF54x && !BF544)
-	default y if (BF52x && !BF522 && !BF523)
 
-comment "DaVinci 35x and 644x USB support"
-	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx
+config USB_MUSB_DAVINCI
+	bool "DaVinci"
+	depends on ARCH_DAVINCI_DMx
 
-comment "DA8xx/OMAP-L1x USB support"
-	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DA8XX
+config USB_MUSB_DA8XX
+	bool "DA8xx/OMAP-L1x"
+	depends on ARCH_DAVINCI_DA8XX
 
-comment "OMAP 243x high speed USB support"
-	depends on USB_MUSB_HDRC && ARCH_OMAP2430
+config USB_MUSB_TUSB6010
+	bool "TUSB6010"
+	depends on ARCH_OMAP
 
-comment "OMAP 343x high speed USB support"
-	depends on USB_MUSB_HDRC && ARCH_OMAP3
-
-comment "OMAP 44xx high speed USB support"
-	depends on USB_MUSB_HDRC && ARCH_OMAP4
-
-comment "Blackfin high speed USB Support"
-	depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523))
+config USB_MUSB_OMAP2PLUS
+	bool "OMAP2430 and onwards"
+	depends on ARCH_OMAP2PLUS
 
 config USB_MUSB_AM35X
-	bool
-	depends on USB_MUSB_HDRC && !ARCH_OMAP2430 && !ARCH_OMAP4
-	select NOP_USB_XCEIV
-	default MACH_OMAP3517EVM
-	help
-	  Select this option if your platform is based on AM35x. As
-	  AM35x has an updated MUSB with CPPI4.1 DMA so this config
-	  is introduced to differentiate musb ip between OMAP3x and
-	  AM35x platforms.
+	bool "AM35x"
+	depends on ARCH_OMAP
 
-config USB_TUSB6010
-	boolean "TUSB 6010 support"
-	depends on USB_MUSB_HDRC && !USB_MUSB_SOC
-	select NOP_USB_XCEIV
-	default y
-	help
-	  The TUSB 6010 chip, from Texas Instruments, connects a discrete
-	  HDRC core using a 16-bit parallel bus (NOR flash style) or VLYNQ
-	  (a high speed serial link).  It can use system-specific external
-	  DMA controllers.
+config USB_MUSB_BLACKFIN
+	bool "Blackfin"
+	depends on (BF54x && !BF544) || (BF52x && ! BF522 && !BF523)
+
+config USB_MUSB_UX500
+	bool "U8500 and U5500"
+	depends on (ARCH_U8500 && AB8500_USB) || (ARCH_U5500)
+
+endchoice
 
 choice
 	prompt "Driver Mode"
@@ -158,7 +143,7 @@
 config MUSB_PIO_ONLY
 	bool 'Disable DMA (always use PIO)'
 	depends on USB_MUSB_HDRC
-	default USB_TUSB6010 || ARCH_DAVINCI_DA8XX || USB_MUSB_AM35X
+	default USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X
 	help
 	  All data is copied between memory and FIFO by the CPU.
 	  DMA controllers are ignored.
@@ -171,21 +156,21 @@
 config USB_INVENTRA_DMA
 	bool
 	depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
-	default ARCH_OMAP2430 || ARCH_OMAP3 || BLACKFIN || ARCH_OMAP4
+	default USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 	help
 	  Enable DMA transfers using Mentor's engine.
 
 config USB_TI_CPPI_DMA
 	bool
 	depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
-	default ARCH_DAVINCI
+	default USB_MUSB_DAVINCI
 	help
 	  Enable DMA transfers when TI CPPI DMA is available.
 
 config USB_TUSB_OMAP_DMA
 	bool
 	depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY
-	depends on USB_TUSB6010
+	depends on USB_MUSB_TUSB6010
 	depends on ARCH_OMAP
 	default y
 	help
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index ce164e8..74df528 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -8,22 +8,19 @@
 
 musb_hdrc-y := musb_core.o
 
-musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx)		+= davinci.o
-musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX)		+= da8xx.o
-musb_hdrc-$(CONFIG_USB_TUSB6010)		+= tusb6010.o
-musb_hdrc-$(CONFIG_ARCH_OMAP2430)		+= omap2430.o
-ifeq ($(CONFIG_USB_MUSB_AM35X),y)
-	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= am35x.o
-else
-	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= omap2430.o
-endif
-musb_hdrc-$(CONFIG_ARCH_OMAP4)			+= omap2430.o
-musb_hdrc-$(CONFIG_BF54x)			+= blackfin.o
-musb_hdrc-$(CONFIG_BF52x)			+= blackfin.o
 musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC)	+= musb_gadget_ep0.o musb_gadget.o
 musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD)		+= musb_virthub.o musb_host.o
 musb_hdrc-$(CONFIG_DEBUG_FS)			+= musb_debugfs.o
 
+# Hardware Glue Layer
+obj-$(CONFIG_USB_MUSB_OMAP2PLUS)		+= omap2430.o
+obj-$(CONFIG_USB_MUSB_AM35X)			+= am35x.o
+obj-$(CONFIG_USB_MUSB_TUSB6010)			+= tusb6010.o
+obj-$(CONFIG_USB_MUSB_DAVINCI)			+= davinci.o
+obj-$(CONFIG_USB_MUSB_DA8XX)			+= da8xx.o
+obj-$(CONFIG_USB_MUSB_BLACKFIN)			+= blackfin.o
+obj-$(CONFIG_USB_MUSB_UX500)			+= ux500.o
+
 # the kconfig must guarantee that only one of the
 # possible I/O schemes will be enabled at a time ...
 # PIO only, or DMA (several potential schemes).
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index b0aabf3..d5a3da3 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -29,8 +29,9 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
-#include <plat/control.h>
 #include <plat/usb.h>
 
 #include "musb_core.h"
@@ -80,51 +81,18 @@
 
 #define USB_MENTOR_CORE_OFFSET	0x400
 
-static inline void phy_on(void)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-	u32 devconf2;
-
-	/*
-	 * 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);
-
-	DBG(1, "Waiting for PHY clock good...\n");
-	while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
-			& CONF2_PHYCLKGD)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			DBG(1, "musb PHY clock good timed out\n");
-			break;
-		}
-	}
-}
-
-static inline void phy_off(void)
-{
-	u32 devconf2;
-
-	/*
-	 * 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);
-}
+struct am35x_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*phy_clk;
+	struct clk		*clk;
+};
+#define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
 /*
- * musb_platform_enable - enable interrupts
+ * am35x_musb_enable - enable interrupts
  */
-void musb_platform_enable(struct musb *musb)
+static void am35x_musb_enable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 epmask;
@@ -143,9 +111,9 @@
 }
 
 /*
- * musb_platform_disable - disable HDRC and flush interrupts
+ * am35x_musb_disable - disable HDRC and flush interrupts
  */
-void musb_platform_disable(struct musb *musb)
+static void am35x_musb_disable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 
@@ -162,7 +130,7 @@
 #define portstate(stmt)
 #endif
 
-static void am35x_set_vbus(struct musb *musb, int is_on)
+static void am35x_musb_set_vbus(struct musb *musb, int is_on)
 {
 	WARN_ON(is_on && is_peripheral_active(musb));
 }
@@ -221,7 +189,7 @@
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	static unsigned long last_timer;
 
@@ -251,13 +219,16 @@
 	mod_timer(&otg_workaround, timeout);
 }
 
-static irqreturn_t am35x_interrupt(int irq, void *hci)
+static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 {
 	struct musb  *musb = hci;
 	void __iomem *reg_base = musb->ctrl_base;
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
 	unsigned long flags;
 	irqreturn_t ret = IRQ_NONE;
-	u32 epintr, usbintr, lvl_intr;
+	u32 epintr, usbintr;
 
 	spin_lock_irqsave(&musb->lock, flags);
 
@@ -346,9 +317,8 @@
 	/* EOI needs to be written for the IRQ to be re-asserted. */
 	if (ret == IRQ_HANDLED || epintr || usbintr) {
 		/* clear level interrupt */
-		lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-		lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
-		omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+		if (data->clear_irq)
+			data->clear_irq();
 		/* write EOI */
 		musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
 	}
@@ -362,137 +332,85 @@
 	return ret;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
-	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+	int     retval = 0;
 
-	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:
-		DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
-	}
+	if (data->set_mode)
+		data->set_mode(musb_mode);
+	else
+		retval = -EIO;
 
-	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-	return 0;
+	return retval;
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static int am35x_musb_init(struct musb *musb)
 {
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
 	void __iomem *reg_base = musb->ctrl_base;
-	u32 rev, lvl_intr, sw_reset;
-	int status;
+	u32 rev;
 
 	musb->mregs += USB_MENTOR_CORE_OFFSET;
 
-	clk_enable(musb->clock);
-	DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock));
-
-	musb->phy_clock = clk_get(musb->controller, "fck");
-	if (IS_ERR(musb->phy_clock)) {
-		status = PTR_ERR(musb->phy_clock);
-		goto exit0;
-	}
-	clk_enable(musb->phy_clock);
-	DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock));
-
 	/* Returns zero if e.g. not clocked */
 	rev = musb_readl(reg_base, USB_REVISION_REG);
-	if (!rev) {
-		status = -ENODEV;
-		goto exit1;
-	}
+	if (!rev)
+		return -ENODEV;
 
 	usb_nop_xceiv_register();
 	musb->xceiv = otg_get_transceiver();
-	if (!musb->xceiv) {
-		status = -ENODEV;
-		goto exit1;
-	}
+	if (!musb->xceiv)
+		return -ENODEV;
 
 	if (is_host_enabled(musb))
 		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
 
-	musb->board_set_vbus = am35x_set_vbus;
-
-	/* Global reset */
-	sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-
-	sw_reset |= AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
-
-	sw_reset &= ~AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+	/* Reset the musb */
+	if (data->reset)
+		data->reset();
 
 	/* Reset the controller */
 	musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);
 
 	/* Start the on-chip PHY and its PLL. */
-	phy_on();
+	if (data->set_phy_power)
+		data->set_phy_power(1);
 
 	msleep(5);
 
-	musb->isr = am35x_interrupt;
+	musb->isr = am35x_musb_interrupt;
 
 	/* clear level interrupt */
-	lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-	lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
-	omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	if (data->clear_irq)
+		data->clear_irq();
+
 	return 0;
-exit1:
-	clk_disable(musb->phy_clock);
-	clk_put(musb->phy_clock);
-exit0:
-	clk_disable(musb->clock);
-	return status;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int am35x_musb_exit(struct musb *musb)
 {
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+
 	if (is_host_enabled(musb))
 		del_timer_sync(&otg_workaround);
 
-	phy_off();
+	/* Shutdown the on-chip PHY and its PLL. */
+	if (data->set_phy_power)
+		data->set_phy_power(0);
 
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
-	clk_disable(musb->clock);
-
-	clk_disable(musb->phy_clock);
-	clk_put(musb->phy_clock);
-
 	return 0;
 }
 
-#ifdef CONFIG_PM
-void musb_platform_save_context(struct musb *musb,
-	struct musb_context_registers *musb_context)
-{
-	phy_off();
-}
-
-void musb_platform_restore_context(struct musb *musb,
-	struct musb_context_registers *musb_context)
-{
-	phy_on();
-}
-#endif
-
 /* AM35x supports only 32bit read operation */
 void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 {
@@ -522,3 +440,215 @@
 		memcpy(dst, &val, len);
 	}
 }
+
+static const struct musb_platform_ops am35x_ops = {
+	.init		= am35x_musb_init,
+	.exit		= am35x_musb_exit,
+
+	.enable		= am35x_musb_enable,
+	.disable	= am35x_musb_disable,
+
+	.set_mode	= am35x_musb_set_mode,
+	.try_idle	= am35x_musb_try_idle,
+
+	.set_vbus	= am35x_musb_set_vbus,
+};
+
+static u64 am35x_dmamask = DMA_BIT_MASK(32);
+
+static int __init am35x_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct am35x_glue		*glue;
+
+	struct clk			*phy_clk;
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	phy_clk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(phy_clk)) {
+		dev_err(&pdev->dev, "failed to get PHY clock\n");
+		ret = PTR_ERR(phy_clk);
+		goto err2;
+	}
+
+	clk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err3;
+	}
+
+	ret = clk_enable(phy_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable PHY clock\n");
+		goto err4;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err5;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &am35x_dmamask;
+	musb->dev.coherent_dma_mask	= am35x_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->phy_clk			= phy_clk;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &am35x_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err6;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err6;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err6;
+	}
+
+	return 0;
+
+err6:
+	clk_disable(clk);
+
+err5:
+	clk_disable(phy_clk);
+
+err4:
+	clk_put(clk);
+
+err3:
+	clk_put(phy_clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit am35x_remove(struct platform_device *pdev)
+{
+	struct am35x_glue	*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_disable(glue->phy_clk);
+	clk_put(glue->clk);
+	clk_put(glue->phy_clk);
+	kfree(glue);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int am35x_suspend(struct device *dev)
+{
+	struct am35x_glue	*glue = dev_get_drvdata(dev);
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+
+	/* Shutdown the on-chip PHY and its PLL. */
+	if (data->set_phy_power)
+		data->set_phy_power(0);
+
+	clk_disable(glue->phy_clk);
+	clk_disable(glue->clk);
+
+	return 0;
+}
+
+static int am35x_resume(struct device *dev)
+{
+	struct am35x_glue	*glue = dev_get_drvdata(dev);
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
+	int			ret;
+
+	/* Start the on-chip PHY and its PLL. */
+	if (data->set_phy_power)
+		data->set_phy_power(1);
+
+	ret = clk_enable(glue->phy_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable PHY clock\n");
+		return ret;
+	}
+
+	ret = clk_enable(glue->clk);
+	if (ret) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct dev_pm_ops am35x_pm_ops = {
+	.suspend	= am35x_suspend,
+	.resume		= am35x_resume,
+};
+
+#define DEV_PM_OPS	&am35x_pm_ops
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver am35x_driver = {
+	.remove		= __exit_p(am35x_remove),
+	.driver		= {
+		.name	= "musb-am35x",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("AM35x MUSB Glue Layer");
+MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init am35x_init(void)
+{
+	return platform_driver_probe(&am35x_driver, am35x_probe);
+}
+subsys_initcall(am35x_init);
+
+static void __exit am35x_exit(void)
+{
+	platform_driver_unregister(&am35x_driver);
+}
+module_exit(am35x_exit);
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index fcb5206..eeba228 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -15,12 +15,20 @@
 #include <linux/list.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/cacheflush.h>
 
 #include "musb_core.h"
 #include "blackfin.h"
 
+struct bfin_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+};
+#define glue_to_musb(g)		platform_get_drvdata(g->musb)
+
 /*
  * Load an endpoint's FIFO
  */
@@ -278,7 +286,7 @@
 	DBG(4, "state is %s\n", otg_state_string(musb));
 }
 
-void musb_platform_enable(struct musb *musb)
+static void bfin_musb_enable(struct musb *musb)
 {
 	if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
 		mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
@@ -286,11 +294,11 @@
 	}
 }
 
-void musb_platform_disable(struct musb *musb)
+static void bfin_musb_disable(struct musb *musb)
 {
 }
 
-static void bfin_set_vbus(struct musb *musb, int is_on)
+static void bfin_musb_set_vbus(struct musb *musb, int is_on)
 {
 	int value = musb->config->gpio_vrsel_active;
 	if (!is_on)
@@ -303,28 +311,28 @@
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
-static int bfin_set_power(struct otg_transceiver *x, unsigned mA)
+static int bfin_musb_set_power(struct otg_transceiver *x, unsigned mA)
 {
 	return 0;
 }
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void bfin_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	if (!is_otg_enabled(musb) && is_host_enabled(musb))
 		mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
 }
 
-int musb_platform_get_vbus_status(struct musb *musb)
+static int bfin_musb_get_vbus_status(struct musb *musb)
 {
 	return 0;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	return -EIO;
 }
 
-static void musb_platform_reg_init(struct musb *musb)
+static void bfin_musb_reg_init(struct musb *musb)
 {
 	if (ANOMALY_05000346) {
 		bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
@@ -362,7 +370,7 @@
 	SSYNC();
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static int bfin_musb_init(struct musb *musb)
 {
 
 	/*
@@ -386,25 +394,124 @@
 		return -ENODEV;
 	}
 
-	musb_platform_reg_init(musb);
+	bfin_musb_reg_init(musb);
 
 	if (is_host_enabled(musb)) {
-		musb->board_set_vbus = bfin_set_vbus;
 		setup_timer(&musb_conn_timer,
 			musb_conn_timer_handler, (unsigned long) musb);
 	}
 	if (is_peripheral_enabled(musb))
-		musb->xceiv->set_power = bfin_set_power;
+		musb->xceiv->set_power = bfin_musb_set_power;
 
 	musb->isr = blackfin_interrupt;
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
-void musb_platform_save_context(struct musb *musb,
-			struct musb_context_registers *musb_context)
+static int bfin_musb_exit(struct musb *musb)
 {
+	gpio_free(musb->config->gpio_vrsel);
+
+	otg_put_transceiver(musb->xceiv);
+	usb_nop_xceiv_unregister();
+	return 0;
+}
+
+static const struct musb_platform_ops bfin_ops = {
+	.init		= bfin_musb_init,
+	.exit		= bfin_musb_exit,
+
+	.enable		= bfin_musb_enable,
+	.disable	= bfin_musb_disable,
+
+	.set_mode	= bfin_musb_set_mode,
+	.try_idle	= bfin_musb_try_idle,
+
+	.vbus_status	= bfin_musb_vbus_status,
+	.set_vbus	= bfin_musb_set_vbus,
+};
+
+static u64 bfin_dmamask = DMA_BIT_MASK(32);
+
+static int __init bfin_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct bfin_glue		*glue;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &bfin_dmamask;
+	musb->dev.coherent_dma_mask	= bfin_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+
+	pdata->platform_ops		= &bfin_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err2;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err2;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err2;
+	}
+
+	return 0;
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit bfin_remove(struct platform_device *pdev)
+{
+	struct bfin_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	kfree(glue);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_suspend(struct device *dev)
+{
+	struct bfin_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+
 	if (is_host_active(musb))
 		/*
 		 * During hibernate gpio_vrsel will change from high to low
@@ -413,20 +520,50 @@
 		 * wakeup event.
 		 */
 		gpio_set_value(musb->config->gpio_vrsel, 0);
-}
 
-void musb_platform_restore_context(struct musb *musb,
-			struct musb_context_registers *musb_context)
-{
-	musb_platform_reg_init(musb);
-}
-#endif
-
-int musb_platform_exit(struct musb *musb)
-{
-	gpio_free(musb->config->gpio_vrsel);
-
-	otg_put_transceiver(musb->xceiv);
-	usb_nop_xceiv_unregister();
 	return 0;
 }
+
+static int bfin_resume(struct device *dev)
+{
+	struct bfin_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+
+	bfin_musb_reg_init(musb);
+
+	return 0;
+}
+
+static struct dev_pm_ops bfin_pm_ops = {
+	.suspend	= bfin_suspend,
+	.resume		= bfin_resume,
+};
+
+#define DEV_PM_OPS	&bfin_pm_op,
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver bfin_driver = {
+	.remove		= __exit_p(bfin_remove),
+	.driver		= {
+		.name	= "musb-bfin",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("Blackfin MUSB Glue Layer");
+MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>");
+MODULE_LICENSE("GPL v2");
+
+static int __init bfin_init(void)
+{
+	return platform_driver_probe(&bfin_driver, bfin_probe);
+}
+subsys_initcall(bfin_init);
+
+static void __exit bfin_exit(void)
+{
+	platform_driver_unregister(&bfin_driver);
+}
+module_exit(bfin_exit);
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index f5a65ff..de55a3c 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -1308,7 +1308,7 @@
 	struct cppi		*controller;
 	struct device		*dev = musb->controller;
 	struct platform_device	*pdev = to_platform_device(dev);
-	int			irq = platform_get_irq(pdev, 1);
+	int			irq = platform_get_irq_byname(pdev, "dma");
 
 	controller = kzalloc(sizeof *controller, GFP_KERNEL);
 	if (!controller)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 84427be..69a0da3 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -29,6 +29,8 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/da8xx.h>
 #include <mach/usb.h>
@@ -78,6 +80,12 @@
 
 #define CFGCHIP2	IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG)
 
+struct da8xx_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+
 /*
  * REVISIT (PM): we should be able to keep the PHY in low power mode most
  * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0
@@ -131,9 +139,9 @@
  */
 
 /**
- * musb_platform_enable - enable interrupts
+ * da8xx_musb_enable - enable interrupts
  */
-void musb_platform_enable(struct musb *musb)
+static void da8xx_musb_enable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 mask;
@@ -151,9 +159,9 @@
 }
 
 /**
- * musb_platform_disable - disable HDRC and flush interrupts
+ * da8xx_musb_disable - disable HDRC and flush interrupts
  */
-void musb_platform_disable(struct musb *musb)
+static void da8xx_musb_disable(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 
@@ -170,7 +178,7 @@
 #define portstate(stmt)
 #endif
 
-static void da8xx_set_vbus(struct musb *musb, int is_on)
+static void da8xx_musb_set_vbus(struct musb *musb, int is_on)
 {
 	WARN_ON(is_on && is_peripheral_active(musb));
 }
@@ -252,7 +260,7 @@
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	static unsigned long last_timer;
 
@@ -282,7 +290,7 @@
 	mod_timer(&otg_workaround, timeout);
 }
 
-static irqreturn_t da8xx_interrupt(int irq, void *hci)
+static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
 {
 	struct musb		*musb = hci;
 	void __iomem		*reg_base = musb->ctrl_base;
@@ -380,7 +388,7 @@
 	return ret;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int da8xx_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	u32 cfgchip2 = __raw_readl(CFGCHIP2);
 
@@ -409,15 +417,13 @@
 	return 0;
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static int da8xx_musb_init(struct musb *musb)
 {
 	void __iomem *reg_base = musb->ctrl_base;
 	u32 rev;
 
 	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;
 
-	clk_enable(musb->clock);
-
 	/* Returns zero if e.g. not clocked */
 	rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
 	if (!rev)
@@ -431,8 +437,6 @@
 	if (is_host_enabled(musb))
 		setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
 
-	musb->board_set_vbus = da8xx_set_vbus;
-
 	/* Reset the controller */
 	musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);
 
@@ -446,14 +450,13 @@
 		 rev, __raw_readl(CFGCHIP2),
 		 musb_readb(reg_base, DA8XX_USB_CTRL_REG));
 
-	musb->isr = da8xx_interrupt;
+	musb->isr = da8xx_musb_interrupt;
 	return 0;
 fail:
-	clk_disable(musb->clock);
 	return -ENODEV;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int da8xx_musb_exit(struct musb *musb)
 {
 	if (is_host_enabled(musb))
 		del_timer_sync(&otg_workaround);
@@ -463,7 +466,140 @@
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
-	clk_disable(musb->clock);
+	return 0;
+}
+
+static const struct musb_platform_ops da8xx_ops = {
+	.init		= da8xx_musb_init,
+	.exit		= da8xx_musb_exit,
+
+	.enable		= da8xx_musb_enable,
+	.disable	= da8xx_musb_disable,
+
+	.set_mode	= da8xx_musb_set_mode,
+	.try_idle	= da8xx_musb_try_idle,
+
+	.set_vbus	= da8xx_musb_set_vbus,
+};
+
+static u64 da8xx_dmamask = DMA_BIT_MASK(32);
+
+static int __init da8xx_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct da8xx_glue		*glue;
+
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	clk = clk_get(&pdev->dev, "usb20");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &da8xx_dmamask;
+	musb->dev.coherent_dma_mask	= da8xx_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &da8xx_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit da8xx_remove(struct platform_device *pdev)
+{
+	struct da8xx_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
 
 	return 0;
 }
+
+static struct platform_driver da8xx_driver = {
+	.remove		= __exit_p(da8xx_remove),
+	.driver		= {
+		.name	= "musb-da8xx",
+	},
+};
+
+MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer");
+MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init da8xx_init(void)
+{
+	return platform_driver_probe(&da8xx_driver, da8xx_probe);
+}
+subsys_initcall(da8xx_init);
+
+static void __exit da8xx_exit(void)
+{
+	platform_driver_unregister(&da8xx_driver);
+}
+module_exit(da8xx_exit);
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 6e67629..e6de097 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -30,6 +30,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/hardware.h>
 #include <mach/memory.h>
@@ -51,6 +53,12 @@
 #define USB_PHY_CTRL	IO_ADDRESS(USBPHY_CTL_PADDR)
 #define DM355_DEEPSLEEP	IO_ADDRESS(DM355_DEEPSLEEP_PADDR)
 
+struct davinci_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+
 /* REVISIT (PM) we should be able to keep the PHY in low power mode most
  * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0
  * and, when in host mode, autosuspending idle root ports... PHYPLLON
@@ -83,7 +91,7 @@
 
 static int dma_off = 1;
 
-void musb_platform_enable(struct musb *musb)
+static void davinci_musb_enable(struct musb *musb)
 {
 	u32	tmp, old, val;
 
@@ -116,7 +124,7 @@
 /*
  * Disable the HDRC and flush interrupts
  */
-void musb_platform_disable(struct musb *musb)
+static void davinci_musb_disable(struct musb *musb)
 {
 	/* because we don't set CTRLR.UINT, "important" to:
 	 *  - not read/write INTRUSB/INTRUSBE
@@ -167,7 +175,7 @@
 
 #endif	/* EVM */
 
-static void davinci_source_power(struct musb *musb, int is_on, int immediate)
+static void davinci_musb_source_power(struct musb *musb, int is_on, int immediate)
 {
 #ifdef CONFIG_MACH_DAVINCI_EVM
 	if (is_on)
@@ -190,10 +198,10 @@
 #endif
 }
 
-static void davinci_set_vbus(struct musb *musb, int is_on)
+static void davinci_musb_set_vbus(struct musb *musb, int is_on)
 {
 	WARN_ON(is_on && is_peripheral_active(musb));
-	davinci_source_power(musb, is_on, 0);
+	davinci_musb_source_power(musb, is_on, 0);
 }
 
 
@@ -259,7 +267,7 @@
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-static irqreturn_t davinci_interrupt(int irq, void *__hci)
+static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
 {
 	unsigned long	flags;
 	irqreturn_t	retval = IRQ_NONE;
@@ -345,7 +353,7 @@
 		/* NOTE:  this must complete poweron within 100 msec
 		 * (OTG_TIME_A_WAIT_VRISE) but we don't check for that.
 		 */
-		davinci_source_power(musb, drvvbus, 0);
+		davinci_musb_source_power(musb, drvvbus, 0);
 		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
 				otg_state_string(musb),
@@ -370,13 +378,13 @@
 	return retval;
 }
 
-int musb_platform_set_mode(struct musb *musb, u8 mode)
+static int davinci_musb_set_mode(struct musb *musb, u8 mode)
 {
 	/* EVM can't do this (right?) */
 	return -EIO;
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static int davinci_musb_init(struct musb *musb)
 {
 	void __iomem	*tibase = musb->ctrl_base;
 	u32		revision;
@@ -388,8 +396,6 @@
 
 	musb->mregs += DAVINCI_BASE_OFFSET;
 
-	clk_enable(musb->clock);
-
 	/* returns zero if e.g. not clocked */
 	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
 	if (revision == 0)
@@ -398,8 +404,7 @@
 	if (is_host_enabled(musb))
 		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
 
-	musb->board_set_vbus = davinci_set_vbus;
-	davinci_source_power(musb, 0, 1);
+	davinci_musb_source_power(musb, 0, 1);
 
 	/* dm355 EVM swaps D+/D- for signal integrity, and
 	 * is clocked from the main 24 MHz crystal.
@@ -440,18 +445,16 @@
 		revision, __raw_readl(USB_PHY_CTRL),
 		musb_readb(tibase, DAVINCI_USB_CTRL_REG));
 
-	musb->isr = davinci_interrupt;
+	musb->isr = davinci_musb_interrupt;
 	return 0;
 
 fail:
-	clk_disable(musb->clock);
-
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return -ENODEV;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int davinci_musb_exit(struct musb *musb)
 {
 	if (is_host_enabled(musb))
 		del_timer_sync(&otg_workaround);
@@ -465,7 +468,7 @@
 		__raw_writel(deepsleep, DM355_DEEPSLEEP);
 	}
 
-	davinci_source_power(musb, 0 /*off*/, 1);
+	davinci_musb_source_power(musb, 0 /*off*/, 1);
 
 	/* delay, to avoid problems with module reload */
 	if (is_host_enabled(musb) && musb->xceiv->default_a) {
@@ -495,10 +498,141 @@
 
 	phy_off();
 
-	clk_disable(musb->clock);
-
 	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
 	return 0;
 }
+
+static const struct musb_platform_ops davinci_ops = {
+	.init		= davinci_musb_init,
+	.exit		= davinci_musb_exit,
+
+	.enable		= davinci_musb_enable,
+	.disable	= davinci_musb_disable,
+
+	.set_mode	= davinci_musb_set_mode,
+
+	.set_vbus	= davinci_musb_set_vbus,
+};
+
+static u64 davinci_dmamask = DMA_BIT_MASK(32);
+
+static int __init davinci_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct davinci_glue		*glue;
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	clk = clk_get(&pdev->dev, "usb");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &davinci_dmamask;
+	musb->dev.coherent_dma_mask	= davinci_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &davinci_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit davinci_remove(struct platform_device *pdev)
+{
+	struct davinci_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
+
+	return 0;
+}
+
+static struct platform_driver davinci_driver = {
+	.remove		= __exit_p(davinci_remove),
+	.driver		= {
+		.name	= "musb-davinci",
+	},
+};
+
+MODULE_DESCRIPTION("DaVinci MUSB Glue Layer");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init davinci_init(void)
+{
+	return platform_driver_probe(&davinci_driver, davinci_probe);
+}
+subsys_initcall(davinci_init);
+
+static void __exit davinci_exit(void)
+{
+	platform_driver_unregister(&davinci_driver);
+}
+module_exit(davinci_exit);
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 99beebc..07cf394 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -99,19 +99,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#ifdef	CONFIG_ARM
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <asm/mach-types.h>
-#endif
-
 #include "musb_core.h"
 
-
-#ifdef CONFIG_ARCH_DAVINCI
-#include "davinci.h"
-#endif
-
 #define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
 
 
@@ -126,7 +115,7 @@
 
 #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
 
-#define MUSB_DRIVER_NAME "musb_hdrc"
+#define MUSB_DRIVER_NAME "musb-hdrc"
 const char musb_driver_name[] = MUSB_DRIVER_NAME;
 
 MODULE_DESCRIPTION(DRIVER_INFO);
@@ -230,7 +219,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN)
+#if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN)
 
 /*
  * Load an endpoint's FIFO
@@ -390,7 +379,7 @@
 	case OTG_STATE_A_SUSPEND:
 	case OTG_STATE_A_WAIT_BCON:
 		DBG(1, "HNP: %s timeout\n", otg_state_string(musb));
-		musb_set_vbus(musb, 0);
+		musb_platform_set_vbus(musb, 0);
 		musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 		break;
 	default:
@@ -571,7 +560,7 @@
 		musb->ep0_stage = MUSB_EP0_START;
 		musb->xceiv->state = OTG_STATE_A_IDLE;
 		MUSB_HST_MODE(musb);
-		musb_set_vbus(musb, 1);
+		musb_platform_set_vbus(musb, 1);
 
 		handled = IRQ_HANDLED;
 	}
@@ -642,7 +631,7 @@
 
 		/* go through A_WAIT_VFALL then start a new session */
 		if (!ignore)
-			musb_set_vbus(musb, 0);
+			musb_platform_set_vbus(musb, 0);
 		handled = IRQ_HANDLED;
 	}
 
@@ -1049,8 +1038,6 @@
 	spin_lock_irqsave(&musb->lock, flags);
 	musb_platform_disable(musb);
 	musb_generic_disable(musb);
-	if (musb->clock)
-		clk_put(musb->clock);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	if (!is_otg_enabled(musb) && is_host_enabled(musb))
@@ -1074,10 +1061,11 @@
  * We don't currently use dynamic fifo setup capability to do anything
  * more than selecting one of a bunch of predefined configurations.
  */
-#if defined(CONFIG_USB_TUSB6010) || \
-	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \
-	|| defined(CONFIG_ARCH_OMAP4)
+#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_OMAP2PLUS) \
+	|| defined(CONFIG_USB_MUSB_AM35X)
 static ushort __initdata fifo_mode = 4;
+#elif defined(CONFIG_USB_MUSB_UX500)
+static ushort __initdata fifo_mode = 5;
 #else
 static ushort __initdata fifo_mode = 2;
 #endif
@@ -1501,7 +1489,7 @@
 		struct musb_hw_ep	*hw_ep = musb->endpoints + i;
 
 		hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 		hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
 		hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
 		hw_ep->fifo_sync_va =
@@ -1548,7 +1536,8 @@
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || \
-	defined(CONFIG_ARCH_OMAP4)
+	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \
+	defined(CONFIG_ARCH_U5500)
 
 static irqreturn_t generic_interrupt(int irq, void *__hci)
 {
@@ -1904,6 +1893,7 @@
 	}
 
 	musb->controller = dev;
+
 	return musb;
 }
 
@@ -2000,30 +1990,14 @@
 	spin_lock_init(&musb->lock);
 	musb->board_mode = plat->mode;
 	musb->board_set_power = plat->set_power;
-	musb->set_clock = plat->set_clock;
 	musb->min_power = plat->min_power;
-
-	/* Clock usage is chip-specific ... functional clock (DaVinci,
-	 * OMAP2430), or PHY ref (some TUSB6010 boards).  All this core
-	 * code does is make sure a clock handle is available; platform
-	 * code manages it during start/stop and suspend/resume.
-	 */
-	if (plat->clock) {
-		musb->clock = clk_get(dev, plat->clock);
-		if (IS_ERR(musb->clock)) {
-			status = PTR_ERR(musb->clock);
-			musb->clock = NULL;
-			goto fail1;
-		}
-	}
+	musb->ops = plat->platform_ops;
 
 	/* The musb_platform_init() call:
 	 *   - adjusts musb->mregs and musb->isr if needed,
 	 *   - may initialize an integrated tranceiver
 	 *   - initializes musb->xceiv, usually by otg_get_transceiver()
-	 *   - activates clocks.
 	 *   - stops powering VBUS
-	 *   - assigns musb->board_set_vbus if host mode is enabled
 	 *
 	 * There are various transciever configurations.  Blackfin,
 	 * DaVinci, TUSB60x0, and others integrate them.  OMAP3 uses
@@ -2031,9 +2005,9 @@
 	 * isp1504, non-OTG, etc) mostly hooking up through ULPI.
 	 */
 	musb->isr = generic_interrupt;
-	status = musb_platform_init(musb, plat->board_data);
+	status = musb_platform_init(musb);
 	if (status < 0)
-		goto fail2;
+		goto fail1;
 
 	if (!musb->isr) {
 		status = -ENODEV;
@@ -2186,10 +2160,6 @@
 		device_init_wakeup(dev, 0);
 	musb_platform_exit(musb);
 
-fail2:
-	if (musb->clock)
-		clk_put(musb->clock);
-
 fail1:
 	dev_err(musb->controller,
 		"musb_init_controller failed with status %d\n", status);
@@ -2215,7 +2185,7 @@
 static int __init musb_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
-	int		irq = platform_get_irq(pdev, 0);
+	int		irq = platform_get_irq_byname(pdev, "mc");
 	int		status;
 	struct resource	*iomem;
 	void __iomem	*base;
@@ -2265,144 +2235,138 @@
 
 #ifdef	CONFIG_PM
 
-static struct musb_context_registers musb_context;
-
-void musb_save_context(struct musb *musb)
+static void musb_save_context(struct musb *musb)
 {
 	int i;
 	void __iomem *musb_base = musb->mregs;
 	void __iomem *epio;
 
 	if (is_host_enabled(musb)) {
-		musb_context.frame = musb_readw(musb_base, MUSB_FRAME);
-		musb_context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
-		musb_context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
+		musb->context.frame = musb_readw(musb_base, MUSB_FRAME);
+		musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
+		musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
 	}
-	musb_context.power = musb_readb(musb_base, MUSB_POWER);
-	musb_context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
-	musb_context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
-	musb_context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
-	musb_context.index = musb_readb(musb_base, MUSB_INDEX);
-	musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
+	musb->context.power = musb_readb(musb_base, MUSB_POWER);
+	musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
+	musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
+	musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
+	musb->context.index = musb_readb(musb_base, MUSB_INDEX);
+	musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
 
 	for (i = 0; i < musb->config->num_eps; ++i) {
 		epio = musb->endpoints[i].regs;
-		musb_context.index_regs[i].txmaxp =
+		musb->context.index_regs[i].txmaxp =
 			musb_readw(epio, MUSB_TXMAXP);
-		musb_context.index_regs[i].txcsr =
+		musb->context.index_regs[i].txcsr =
 			musb_readw(epio, MUSB_TXCSR);
-		musb_context.index_regs[i].rxmaxp =
+		musb->context.index_regs[i].rxmaxp =
 			musb_readw(epio, MUSB_RXMAXP);
-		musb_context.index_regs[i].rxcsr =
+		musb->context.index_regs[i].rxcsr =
 			musb_readw(epio, MUSB_RXCSR);
 
 		if (musb->dyn_fifo) {
-			musb_context.index_regs[i].txfifoadd =
+			musb->context.index_regs[i].txfifoadd =
 					musb_read_txfifoadd(musb_base);
-			musb_context.index_regs[i].rxfifoadd =
+			musb->context.index_regs[i].rxfifoadd =
 					musb_read_rxfifoadd(musb_base);
-			musb_context.index_regs[i].txfifosz =
+			musb->context.index_regs[i].txfifosz =
 					musb_read_txfifosz(musb_base);
-			musb_context.index_regs[i].rxfifosz =
+			musb->context.index_regs[i].rxfifosz =
 					musb_read_rxfifosz(musb_base);
 		}
 		if (is_host_enabled(musb)) {
-			musb_context.index_regs[i].txtype =
+			musb->context.index_regs[i].txtype =
 				musb_readb(epio, MUSB_TXTYPE);
-			musb_context.index_regs[i].txinterval =
+			musb->context.index_regs[i].txinterval =
 				musb_readb(epio, MUSB_TXINTERVAL);
-			musb_context.index_regs[i].rxtype =
+			musb->context.index_regs[i].rxtype =
 				musb_readb(epio, MUSB_RXTYPE);
-			musb_context.index_regs[i].rxinterval =
+			musb->context.index_regs[i].rxinterval =
 				musb_readb(epio, MUSB_RXINTERVAL);
 
-			musb_context.index_regs[i].txfunaddr =
+			musb->context.index_regs[i].txfunaddr =
 				musb_read_txfunaddr(musb_base, i);
-			musb_context.index_regs[i].txhubaddr =
+			musb->context.index_regs[i].txhubaddr =
 				musb_read_txhubaddr(musb_base, i);
-			musb_context.index_regs[i].txhubport =
+			musb->context.index_regs[i].txhubport =
 				musb_read_txhubport(musb_base, i);
 
-			musb_context.index_regs[i].rxfunaddr =
+			musb->context.index_regs[i].rxfunaddr =
 				musb_read_rxfunaddr(musb_base, i);
-			musb_context.index_regs[i].rxhubaddr =
+			musb->context.index_regs[i].rxhubaddr =
 				musb_read_rxhubaddr(musb_base, i);
-			musb_context.index_regs[i].rxhubport =
+			musb->context.index_regs[i].rxhubport =
 				musb_read_rxhubport(musb_base, i);
 		}
 	}
-
-	musb_platform_save_context(musb, &musb_context);
 }
 
-void musb_restore_context(struct musb *musb)
+static void musb_restore_context(struct musb *musb)
 {
 	int i;
 	void __iomem *musb_base = musb->mregs;
 	void __iomem *ep_target_regs;
 	void __iomem *epio;
 
-	musb_platform_restore_context(musb, &musb_context);
-
 	if (is_host_enabled(musb)) {
-		musb_writew(musb_base, MUSB_FRAME, musb_context.frame);
-		musb_writeb(musb_base, MUSB_TESTMODE, musb_context.testmode);
-		musb_write_ulpi_buscontrol(musb->mregs, musb_context.busctl);
+		musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
+		musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
+		musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
 	}
-	musb_writeb(musb_base, MUSB_POWER, musb_context.power);
-	musb_writew(musb_base, MUSB_INTRTXE, musb_context.intrtxe);
-	musb_writew(musb_base, MUSB_INTRRXE, musb_context.intrrxe);
-	musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe);
-	musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl);
+	musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+	musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
+	musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+	musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
+	musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
 
 	for (i = 0; i < musb->config->num_eps; ++i) {
 		epio = musb->endpoints[i].regs;
 		musb_writew(epio, MUSB_TXMAXP,
-			musb_context.index_regs[i].txmaxp);
+			musb->context.index_regs[i].txmaxp);
 		musb_writew(epio, MUSB_TXCSR,
-			musb_context.index_regs[i].txcsr);
+			musb->context.index_regs[i].txcsr);
 		musb_writew(epio, MUSB_RXMAXP,
-			musb_context.index_regs[i].rxmaxp);
+			musb->context.index_regs[i].rxmaxp);
 		musb_writew(epio, MUSB_RXCSR,
-			musb_context.index_regs[i].rxcsr);
+			musb->context.index_regs[i].rxcsr);
 
 		if (musb->dyn_fifo) {
 			musb_write_txfifosz(musb_base,
-				musb_context.index_regs[i].txfifosz);
+				musb->context.index_regs[i].txfifosz);
 			musb_write_rxfifosz(musb_base,
-				musb_context.index_regs[i].rxfifosz);
+				musb->context.index_regs[i].rxfifosz);
 			musb_write_txfifoadd(musb_base,
-				musb_context.index_regs[i].txfifoadd);
+				musb->context.index_regs[i].txfifoadd);
 			musb_write_rxfifoadd(musb_base,
-				musb_context.index_regs[i].rxfifoadd);
+				musb->context.index_regs[i].rxfifoadd);
 		}
 
 		if (is_host_enabled(musb)) {
 			musb_writeb(epio, MUSB_TXTYPE,
-				musb_context.index_regs[i].txtype);
+				musb->context.index_regs[i].txtype);
 			musb_writeb(epio, MUSB_TXINTERVAL,
-				musb_context.index_regs[i].txinterval);
+				musb->context.index_regs[i].txinterval);
 			musb_writeb(epio, MUSB_RXTYPE,
-				musb_context.index_regs[i].rxtype);
+				musb->context.index_regs[i].rxtype);
 			musb_writeb(epio, MUSB_RXINTERVAL,
 
-			musb_context.index_regs[i].rxinterval);
+			musb->context.index_regs[i].rxinterval);
 			musb_write_txfunaddr(musb_base, i,
-				musb_context.index_regs[i].txfunaddr);
+				musb->context.index_regs[i].txfunaddr);
 			musb_write_txhubaddr(musb_base, i,
-				musb_context.index_regs[i].txhubaddr);
+				musb->context.index_regs[i].txhubaddr);
 			musb_write_txhubport(musb_base, i,
-				musb_context.index_regs[i].txhubport);
+				musb->context.index_regs[i].txhubport);
 
 			ep_target_regs =
 				musb_read_target_reg_base(i, musb_base);
 
 			musb_write_rxfunaddr(ep_target_regs,
-				musb_context.index_regs[i].rxfunaddr);
+				musb->context.index_regs[i].rxfunaddr);
 			musb_write_rxhubaddr(ep_target_regs,
-				musb_context.index_regs[i].rxhubaddr);
+				musb->context.index_regs[i].rxhubaddr);
 			musb_write_rxhubport(ep_target_regs,
-				musb_context.index_regs[i].rxhubport);
+				musb->context.index_regs[i].rxhubport);
 		}
 	}
 }
@@ -2427,12 +2391,6 @@
 
 	musb_save_context(musb);
 
-	if (musb->clock) {
-		if (musb->set_clock)
-			musb->set_clock(musb->clock, 0);
-		else
-			clk_disable(musb->clock);
-	}
 	spin_unlock_irqrestore(&musb->lock, flags);
 	return 0;
 }
@@ -2442,13 +2400,6 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct musb	*musb = dev_to_musb(&pdev->dev);
 
-	if (musb->clock) {
-		if (musb->set_clock)
-			musb->set_clock(musb->clock, 1);
-		else
-			clk_enable(musb->clock);
-	}
-
 	musb_restore_context(musb);
 
 	/* for static cmos like DaVinci, register values were preserved
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index febaabc..d0c236f 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -222,7 +222,7 @@
 #endif
 
 /* TUSB mapping: "flat" plus ep0 special cases */
-#if	defined(CONFIG_USB_TUSB6010)
+#if	defined(CONFIG_USB_MUSB_TUSB6010)
 #define musb_ep_select(_mbase, _epnum) \
 	musb_writeb((_mbase), MUSB_INDEX, (_epnum))
 #define	MUSB_EP_OFFSET			MUSB_TUSB_OFFSET
@@ -253,6 +253,29 @@
 
 /******************************** TYPES *************************************/
 
+/**
+ * struct musb_platform_ops - Operations passed to musb_core by HW glue layer
+ * @init:	turns on clocks, sets up platform-specific registers, etc
+ * @exit:	undoes @init
+ * @set_mode:	forcefully changes operating mode
+ * @try_ilde:	tries to idle the IP
+ * @vbus_status: returns vbus status if possible
+ * @set_vbus:	forces vbus status
+ */
+struct musb_platform_ops {
+	int	(*init)(struct musb *musb);
+	int	(*exit)(struct musb *musb);
+
+	void	(*enable)(struct musb *musb);
+	void	(*disable)(struct musb *musb);
+
+	int	(*set_mode)(struct musb *musb, u8 mode);
+	void	(*try_idle)(struct musb *musb, unsigned long timeout);
+
+	int	(*vbus_status)(struct musb *musb);
+	void	(*set_vbus)(struct musb *musb, int on);
+};
+
 /*
  * struct musb_hw_ep - endpoint hardware (bidirectional)
  *
@@ -263,7 +286,7 @@
 	void __iomem		*fifo;
 	void __iomem		*regs;
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 	void __iomem		*conf;
 #endif
 
@@ -280,7 +303,7 @@
 	struct dma_channel	*tx_channel;
 	struct dma_channel	*rx_channel;
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 	/* TUSB has "asynchronous" and "synchronous" dma modes */
 	dma_addr_t		fifo_async;
 	dma_addr_t		fifo_sync;
@@ -323,14 +346,43 @@
 #endif
 }
 
+struct musb_csr_regs {
+	/* FIFO registers */
+	u16 txmaxp, txcsr, rxmaxp, rxcsr;
+	u16 rxfifoadd, txfifoadd;
+	u8 txtype, txinterval, rxtype, rxinterval;
+	u8 rxfifosz, txfifosz;
+	u8 txfunaddr, txhubaddr, txhubport;
+	u8 rxfunaddr, rxhubaddr, rxhubport;
+};
+
+struct musb_context_registers {
+
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+    defined(CONFIG_ARCH_OMAP4)
+	u32 otg_sysconfig, otg_forcestandby;
+#endif
+	u8 power;
+	u16 intrtxe, intrrxe;
+	u8 intrusbe;
+	u16 frame;
+	u8 index, testmode;
+
+	u8 devctl, busctl, misc;
+
+	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
+};
+
 /*
  * struct musb - Driver instance data.
  */
 struct musb {
 	/* device lock */
 	spinlock_t		lock;
-	struct clk		*clock;
-	struct clk		*phy_clock;
+
+	const struct musb_platform_ops *ops;
+	struct musb_context_registers context;
+
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
 	u16			hwvers;
@@ -359,11 +411,7 @@
 
 	struct timer_list	otg_timer;
 #endif
-
-	/* called with IRQs blocked; ON/nonzero implies starting a session,
-	 * and waiting at least a_wait_vrise_tmout.
-	 */
-	void			(*board_set_vbus)(struct musb *, int is_on);
+	struct notifier_block	nb;
 
 	struct dma_controller	*dma_controller;
 
@@ -371,7 +419,7 @@
 	void __iomem		*ctrl_base;
 	void __iomem		*mregs;
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 	dma_addr_t		async;
 	dma_addr_t		sync;
 	void __iomem		*sync_va;
@@ -398,8 +446,6 @@
 	u8 board_mode;		/* enum musb_mode */
 	int			(*board_set_power)(int state);
 
-	int			(*set_clock)(struct clk *clk, int is_active);
-
 	u8			min_power;	/* vbus for periph, in mA/2 */
 
 	bool			is_host;
@@ -458,52 +504,6 @@
 #endif
 };
 
-#ifdef CONFIG_PM
-struct musb_csr_regs {
-	/* FIFO registers */
-	u16 txmaxp, txcsr, rxmaxp, rxcsr;
-	u16 rxfifoadd, txfifoadd;
-	u8 txtype, txinterval, rxtype, rxinterval;
-	u8 rxfifosz, txfifosz;
-	u8 txfunaddr, txhubaddr, txhubport;
-	u8 rxfunaddr, rxhubaddr, rxhubport;
-};
-
-struct musb_context_registers {
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-    defined(CONFIG_ARCH_OMAP4)
-	u32 otg_sysconfig, otg_forcestandby;
-#endif
-	u8 power;
-	u16 intrtxe, intrrxe;
-	u8 intrusbe;
-	u16 frame;
-	u8 index, testmode;
-
-	u8 devctl, busctl, misc;
-
-	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
-};
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-    defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_BLACKFIN)
-extern void musb_platform_save_context(struct musb *musb,
-		struct musb_context_registers *musb_context);
-extern void musb_platform_restore_context(struct musb *musb,
-		struct musb_context_registers *musb_context);
-#else
-#define musb_platform_save_context(m, x)	do {} while (0)
-#define musb_platform_restore_context(m, x)	do {} while (0)
-#endif
-
-#endif
-
-static inline void musb_set_vbus(struct musb *musb, int is_on)
-{
-	musb->board_set_vbus(musb, is_on);
-}
-
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
 static inline struct musb *gadget_to_musb(struct usb_gadget *g)
 {
@@ -592,29 +592,63 @@
 
 extern irqreturn_t musb_interrupt(struct musb *);
 
-extern void musb_platform_enable(struct musb *musb);
-extern void musb_platform_disable(struct musb *musb);
-
 extern void musb_hnp_stop(struct musb *musb);
 
-extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode);
+static inline void musb_platform_set_vbus(struct musb *musb, int is_on)
+{
+	if (musb->ops->set_vbus)
+		musb->ops->set_vbus(musb, is_on);
+}
 
-#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \
-	defined(CONFIG_ARCH_DAVINCI_DA8XX) || \
-	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-	defined(CONFIG_ARCH_OMAP4)
-extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
-#else
-#define musb_platform_try_idle(x, y)		do {} while (0)
-#endif
+static inline void musb_platform_enable(struct musb *musb)
+{
+	if (musb->ops->enable)
+		musb->ops->enable(musb);
+}
 
-#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN)
-extern int musb_platform_get_vbus_status(struct musb *musb);
-#else
-#define musb_platform_get_vbus_status(x)	0
-#endif
+static inline void musb_platform_disable(struct musb *musb)
+{
+	if (musb->ops->disable)
+		musb->ops->disable(musb);
+}
 
-extern int __init musb_platform_init(struct musb *musb, void *board_data);
-extern int musb_platform_exit(struct musb *musb);
+static inline int musb_platform_set_mode(struct musb *musb, u8 mode)
+{
+	if (!musb->ops->set_mode)
+		return 0;
+
+	return musb->ops->set_mode(musb, mode);
+}
+
+static inline void musb_platform_try_idle(struct musb *musb,
+		unsigned long timeout)
+{
+	if (musb->ops->try_idle)
+		musb->ops->try_idle(musb, timeout);
+}
+
+static inline int musb_platform_get_vbus_status(struct musb *musb)
+{
+	if (!musb->ops->vbus_status)
+		return 0;
+
+	return musb->ops->vbus_status(musb);
+}
+
+static inline int musb_platform_init(struct musb *musb)
+{
+	if (!musb->ops->init)
+		return -EINVAL;
+
+	return musb->ops->init(musb);
+}
+
+static inline int musb_platform_exit(struct musb *musb)
+{
+	if (!musb->ops->exit)
+		return -EINVAL;
+
+	return musb->ops->exit(musb);
+}
 
 #endif	/* __MUSB_CORE_H__ */
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 9d6ade8..9b162df 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1136,13 +1136,16 @@
 	struct musb_request	*request = NULL;
 
 	request = kzalloc(sizeof *request, gfp_flags);
-	if (request) {
-		INIT_LIST_HEAD(&request->request.list);
-		request->request.dma = DMA_ADDR_INVALID;
-		request->epnum = musb_ep->current_epnum;
-		request->ep = musb_ep;
+	if (!request) {
+		DBG(4, "not enough memory\n");
+		return NULL;
 	}
 
+	INIT_LIST_HEAD(&request->request.list);
+	request->request.dma = DMA_ADDR_INVALID;
+	request->epnum = musb_ep->current_epnum;
+	request->ep = musb_ep;
+
 	return &request->request;
 }
 
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
index b06e9ef..03c6ccd 100644
--- a/drivers/usb/musb/musb_io.h
+++ b/drivers/usb/musb/musb_io.h
@@ -74,7 +74,7 @@
 	{ __raw_writel(data, addr + offset); }
 
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 
 /*
  * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum.
@@ -114,7 +114,7 @@
 static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
 	{ __raw_writeb(data, addr + offset); }
 
-#endif	/* CONFIG_USB_TUSB6010 */
+#endif	/* CONFIG_USB_MUSB_TUSB6010 */
 
 #else
 
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
index 5a727c5..8241070 100644
--- a/drivers/usb/musb/musb_regs.h
+++ b/drivers/usb/musb/musb_regs.h
@@ -234,7 +234,7 @@
 #define MUSB_TESTMODE		0x0F	/* 8 bit */
 
 /* Get offset for a given FIFO from musb->mregs */
-#ifdef	CONFIG_USB_TUSB6010
+#ifdef	CONFIG_USB_MUSB_TUSB6010
 #define MUSB_FIFO_OFFSET(epnum)	(0x200 + ((epnum) * 0x20))
 #else
 #define MUSB_FIFO_OFFSET(epnum)	(0x20 + ((epnum) * 4))
@@ -295,7 +295,7 @@
 #define MUSB_FLAT_OFFSET(_epnum, _offset)	\
 	(0x100 + (0x10*(_epnum)) + (_offset))
 
-#ifdef CONFIG_USB_TUSB6010
+#ifdef CONFIG_USB_MUSB_TUSB6010
 /* TUSB6010 EP0 configuration register is special */
 #define MUSB_TUSB_OFFSET(_epnum, _offset)	\
 	(0x10 + _offset)
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 43233c3..b46d187 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -276,7 +276,7 @@
 			break;
 		case USB_PORT_FEAT_POWER:
 			if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
-				musb_set_vbus(musb, 0);
+				musb_platform_set_vbus(musb, 0);
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
 		case USB_PORT_FEAT_C_ENABLE:
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 563114d..0144a2d 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -377,7 +377,7 @@
 	struct musb_dma_controller *controller;
 	struct device *dev = musb->controller;
 	struct platform_device *pdev = to_platform_device(dev);
-	int irq = platform_get_irq(pdev, 1);
+	int irq = platform_get_irq_byname(pdev, "dma");
 
 	if (irq == 0) {
 		dev_err(dev, "No DMA interrupt line!\n");
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index ed618bd..a3f1233 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -31,10 +31,18 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
 
+struct omap2430_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+#define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
 static struct timer_list musb_idle_timer;
 
@@ -49,12 +57,8 @@
 
 	spin_lock_irqsave(&musb->lock, flags);
 
-	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_WAIT_BCON:
-		devctl &= ~MUSB_DEVCTL_SESSION;
-		musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 		if (devctl & MUSB_DEVCTL_BDEVICE) {
@@ -98,7 +102,7 @@
 }
 
 
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	unsigned long		default_timeout = jiffies + msecs_to_jiffies(3);
 	static unsigned long	last_timer;
@@ -131,15 +135,11 @@
 	mod_timer(&musb_idle_timer, timeout);
 }
 
-void musb_platform_enable(struct musb *musb)
-{
-}
-void musb_platform_disable(struct musb *musb)
-{
-}
-static void omap_set_vbus(struct musb *musb, int is_on)
+static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 {
 	u8		devctl;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	int ret = 1;
 	/* HDRC controls CPEN, but beware current surges during device
 	 * connect.  They can trigger transient overcurrent conditions
 	 * that must be ignored.
@@ -148,12 +148,35 @@
 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
 	if (is_on) {
-		musb->is_active = 1;
-		musb->xceiv->default_a = 1;
-		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
-		devctl |= MUSB_DEVCTL_SESSION;
+		if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+			/* start the session */
+			devctl |= MUSB_DEVCTL_SESSION;
+			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+			/*
+			 * Wait for the musb to set as A device to enable the
+			 * VBUS
+			 */
+			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
 
-		MUSB_HST_MODE(musb);
+				cpu_relax();
+
+				if (time_after(jiffies, timeout)) {
+					dev_err(musb->controller,
+					"configured as A device timeout");
+					ret = -EINVAL;
+					break;
+				}
+			}
+
+			if (ret && musb->xceiv->set_vbus)
+				otg_set_vbus(musb->xceiv, 1);
+		} else {
+			musb->is_active = 1;
+			musb->xceiv->default_a = 1;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+			devctl |= MUSB_DEVCTL_SESSION;
+			MUSB_HST_MODE(musb);
+		}
 	} else {
 		musb->is_active = 0;
 
@@ -175,9 +198,7 @@
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
-static int musb_platform_resume(struct musb *musb);
-
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	u8	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
@@ -187,10 +208,94 @@
 	return 0;
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static inline void omap2430_low_level_exit(struct musb *musb)
 {
 	u32 l;
-	struct omap_musb_board_data *data = board_data;
+
+	/* in any role */
+	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
+	l |= ENABLEFORCE;	/* enable MSTANDBY */
+	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+
+	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
+	l |= ENABLEWAKEUP;	/* enable wakeup */
+	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
+}
+
+static inline void omap2430_low_level_init(struct musb *musb)
+{
+	u32 l;
+
+	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
+	l &= ~ENABLEWAKEUP;	/* disable wakeup */
+	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
+
+	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
+	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
+	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+}
+
+/* blocking notifier support */
+static int musb_otg_notifications(struct notifier_block *nb,
+		unsigned long event, void *unused)
+{
+	struct musb	*musb = container_of(nb, struct musb, nb);
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *pdata = dev->platform_data;
+	struct omap_musb_board_data *data = pdata->board_data;
+
+	switch (event) {
+	case USB_EVENT_ID:
+		DBG(4, "ID GND\n");
+
+		if (is_otg_enabled(musb)) {
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+			if (musb->gadget_driver) {
+				otg_init(musb->xceiv);
+
+				if (data->interface_type ==
+						MUSB_INTERFACE_UTMI)
+					omap2430_musb_set_vbus(musb, 1);
+
+			}
+#endif
+		} else {
+			otg_init(musb->xceiv);
+			if (data->interface_type ==
+					MUSB_INTERFACE_UTMI)
+				omap2430_musb_set_vbus(musb, 1);
+		}
+		break;
+
+	case USB_EVENT_VBUS:
+		DBG(4, "VBUS Connect\n");
+
+		otg_init(musb->xceiv);
+		break;
+
+	case USB_EVENT_NONE:
+		DBG(4, "VBUS Disconnect\n");
+
+		if (data->interface_type == MUSB_INTERFACE_UTMI) {
+			if (musb->xceiv->set_vbus)
+				otg_set_vbus(musb->xceiv, 0);
+		}
+		otg_shutdown(musb->xceiv);
+		break;
+	default:
+		DBG(4, "ID float\n");
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int omap2430_musb_init(struct musb *musb)
+{
+	u32 l, status = 0;
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *plat = dev->platform_data;
+	struct omap_musb_board_data *data = plat->board_data;
 
 	/* We require some kind of external transceiver, hooked
 	 * up through ULPI.  TWL4030-family PMICs include one,
@@ -202,7 +307,7 @@
 		return -ENODEV;
 	}
 
-	musb_platform_resume(musb);
+	omap2430_low_level_init(musb);
 
 	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
 	l &= ~ENABLEWAKEUP;	/* disable wakeup */
@@ -239,87 +344,214 @@
 			musb_readl(musb->mregs, OTG_INTERFSEL),
 			musb_readl(musb->mregs, OTG_SIMENABLE));
 
-	if (is_host_enabled(musb))
-		musb->board_set_vbus = omap_set_vbus;
+	musb->nb.notifier_call = musb_otg_notifications;
+	status = otg_register_notifier(musb->xceiv, &musb->nb);
+
+	if (status)
+		DBG(1, "notification register failed\n");
+
+	/* check whether cable is already connected */
+	if (musb->xceiv->state ==OTG_STATE_B_IDLE)
+		musb_otg_notifications(&musb->nb, 1,
+					musb->xceiv->gadget);
 
 	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
-void musb_platform_save_context(struct musb *musb,
-		struct musb_context_registers *musb_context)
+static int omap2430_musb_exit(struct musb *musb)
 {
-	musb_context->otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	musb_context->otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY);
-}
 
-void musb_platform_restore_context(struct musb *musb,
-		struct musb_context_registers *musb_context)
-{
-	musb_writel(musb->mregs, OTG_SYSCONFIG, musb_context->otg_sysconfig);
-	musb_writel(musb->mregs, OTG_FORCESTDBY, musb_context->otg_forcestandby);
-}
-#endif
-
-static int musb_platform_suspend(struct musb *musb)
-{
-	u32 l;
-
-	if (!musb->clock)
-		return 0;
-
-	/* in any role */
-	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
-	l |= ENABLEFORCE;	/* enable MSTANDBY */
-	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
-
-	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	l |= ENABLEWAKEUP;	/* enable wakeup */
-	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
-
-	otg_set_suspend(musb->xceiv, 1);
-
-	if (musb->set_clock)
-		musb->set_clock(musb->clock, 0);
-	else
-		clk_disable(musb->clock);
+	omap2430_low_level_exit(musb);
+	otg_put_transceiver(musb->xceiv);
 
 	return 0;
 }
 
-static int musb_platform_resume(struct musb *musb)
+static const struct musb_platform_ops omap2430_ops = {
+	.init		= omap2430_musb_init,
+	.exit		= omap2430_musb_exit,
+
+	.set_mode	= omap2430_musb_set_mode,
+	.try_idle	= omap2430_musb_try_idle,
+
+	.set_vbus	= omap2430_musb_set_vbus,
+};
+
+static u64 omap2430_dmamask = DMA_BIT_MASK(32);
+
+static int __init omap2430_probe(struct platform_device *pdev)
 {
-	u32 l;
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct omap2430_glue		*glue;
+	struct clk			*clk;
 
-	if (!musb->clock)
-		return 0;
+	int				ret = -ENOMEM;
 
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	clk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &omap2430_dmamask;
+	musb->dev.coherent_dma_mask	= omap2430_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &omap2430_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit omap2430_remove(struct platform_device *pdev)
+{
+	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static void omap2430_save_context(struct musb *musb)
+{
+	musb->context.otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG);
+	musb->context.otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY);
+}
+
+static void omap2430_restore_context(struct musb *musb)
+{
+	musb_writel(musb->mregs, OTG_SYSCONFIG, musb->context.otg_sysconfig);
+	musb_writel(musb->mregs, OTG_FORCESTDBY, musb->context.otg_forcestandby);
+}
+
+static int omap2430_suspend(struct device *dev)
+{
+	struct omap2430_glue		*glue = dev_get_drvdata(dev);
+	struct musb			*musb = glue_to_musb(glue);
+
+	omap2430_low_level_exit(musb);
+	otg_set_suspend(musb->xceiv, 1);
+	omap2430_save_context(musb);
+	clk_disable(glue->clk);
+
+	return 0;
+}
+
+static int omap2430_resume(struct device *dev)
+{
+	struct omap2430_glue		*glue = dev_get_drvdata(dev);
+	struct musb			*musb = glue_to_musb(glue);
+	int				ret;
+
+	ret = clk_enable(glue->clk);
+	if (ret) {
+		dev_err(dev, "faled to enable clock\n");
+		return ret;
+	}
+
+	omap2430_low_level_init(musb);
+	omap2430_restore_context(musb);
 	otg_set_suspend(musb->xceiv, 0);
 
-	if (musb->set_clock)
-		musb->set_clock(musb->clock, 1);
-	else
-		clk_enable(musb->clock);
-
-	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	l &= ~ENABLEWAKEUP;	/* disable wakeup */
-	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
-
-	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
-	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
-	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
-
 	return 0;
 }
 
+static struct dev_pm_ops omap2430_pm_ops = {
+	.suspend	= omap2430_suspend,
+	.resume		= omap2430_resume,
+};
 
-int musb_platform_exit(struct musb *musb)
+#define DEV_PM_OPS	(&omap2430_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver omap2430_driver = {
+	.remove		= __exit_p(omap2430_remove),
+	.driver		= {
+		.name	= "musb-omap2430",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init omap2430_init(void)
 {
-
-	musb_platform_suspend(musb);
-
-	otg_put_transceiver(musb->xceiv);
-	return 0;
+	return platform_driver_probe(&omap2430_driver, omap2430_probe);
 }
+subsys_initcall(omap2430_init);
+
+static void __exit omap2430_exit(void)
+{
+	platform_driver_unregister(&omap2430_driver);
+}
+module_exit(omap2430_exit);
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index bde40ef..2ba3b07 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -21,10 +21,16 @@
 #include <linux/usb.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 
 #include "musb_core.h"
 
-static void tusb_source_power(struct musb *musb, int is_on);
+struct tusb6010_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+};
+
+static void tusb_musb_set_vbus(struct musb *musb, int is_on);
 
 #define TUSB_REV_MAJOR(reg_val)		((reg_val >> 4) & 0xf)
 #define TUSB_REV_MINOR(reg_val)		(reg_val & 0xf)
@@ -50,7 +56,7 @@
 	return rev;
 }
 
-static int __init tusb_print_revision(struct musb *musb)
+static int tusb_print_revision(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u8		rev;
@@ -275,17 +281,6 @@
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		reg;
 
-	/*
-	 * Keep clock active when enabled. Note that this is not tied to
-	 * drawing VBUS, as with OTG mA can be less than musb->min_power.
-	 */
-	if (musb->set_clock) {
-		if (mA)
-			musb->set_clock(musb->clock, 1);
-		else
-			musb->set_clock(musb->clock, 0);
-	}
-
 	/* tps65030 seems to consume max 100mA, with maybe 60mA available
 	 * (measured on one board) for things other than tps and tusb.
 	 *
@@ -348,7 +343,7 @@
  * USB link is not suspended ... and tells us the relevant wakeup
  * events.  SW_EN for voltage is handled separately.
  */
-void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
+static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		reg;
@@ -385,7 +380,7 @@
 /*
  * Updates cable VBUS status. Caller must take care of locking.
  */
-int musb_platform_get_vbus_status(struct musb *musb)
+static int tusb_musb_vbus_status(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		otg_stat, prcm_mngmt;
@@ -431,7 +426,7 @@
 		}
 		/* FALLTHROUGH */
 	case OTG_STATE_A_IDLE:
-		tusb_source_power(musb, 0);
+		tusb_musb_set_vbus(musb, 0);
 	default:
 		break;
 	}
@@ -475,7 +470,7 @@
  * we don't want to treat that full speed J as a wakeup event.
  * ... peripherals must draw only suspend current after 10 msec.
  */
-void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
 {
 	unsigned long		default_timeout = jiffies + msecs_to_jiffies(3);
 	static unsigned long	last_timer;
@@ -515,7 +510,7 @@
 				| TUSB_DEV_OTG_TIMER_ENABLE) \
 		: 0)
 
-static void tusb_source_power(struct musb *musb, int is_on)
+static void tusb_musb_set_vbus(struct musb *musb, int is_on)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		conf, prcm, timer;
@@ -531,8 +526,6 @@
 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
 	if (is_on) {
-		if (musb->set_clock)
-			musb->set_clock(musb->clock, 1);
 		timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE);
 		musb->xceiv->default_a = 1;
 		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
@@ -571,8 +564,6 @@
 
 		devctl &= ~MUSB_DEVCTL_SESSION;
 		conf &= ~TUSB_DEV_CONF_USB_HOST_MODE;
-		if (musb->set_clock)
-			musb->set_clock(musb->clock, 0);
 	}
 	prcm &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN);
 
@@ -599,7 +590,7 @@
  * and peripheral modes in non-OTG configurations by reconfiguring hardware
  * and then setting musb->board_mode. For now, only support OTG mode.
  */
-int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	u32		otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf;
@@ -677,7 +668,7 @@
 			default_a = is_host_enabled(musb);
 		DBG(2, "Default-%c\n", default_a ? 'A' : 'B');
 		musb->xceiv->default_a = default_a;
-		tusb_source_power(musb, default_a);
+		tusb_musb_set_vbus(musb, default_a);
 
 		/* Don't allow idling immediately */
 		if (default_a)
@@ -722,7 +713,7 @@
 			switch (musb->xceiv->state) {
 			case OTG_STATE_A_IDLE:
 				DBG(2, "Got SRP, turning on VBUS\n");
-				musb_set_vbus(musb, 1);
+				musb_platform_set_vbus(musb, 1);
 
 				/* CONNECT can wake if a_wait_bcon is set */
 				if (musb->a_wait_bcon != 0)
@@ -748,11 +739,11 @@
 				 */
 				if (musb->vbuserr_retry) {
 					musb->vbuserr_retry--;
-					tusb_source_power(musb, 1);
+					tusb_musb_set_vbus(musb, 1);
 				} else {
 					musb->vbuserr_retry
 						= VBUSERR_RETRY_COUNT;
-					tusb_source_power(musb, 0);
+					tusb_musb_set_vbus(musb, 0);
 				}
 				break;
 			default:
@@ -786,7 +777,7 @@
 			} else {
 				/* REVISIT report overcurrent to hub? */
 				ERR("vbus too slow, devctl %02x\n", devctl);
-				tusb_source_power(musb, 0);
+				tusb_musb_set_vbus(musb, 0);
 			}
 			break;
 		case OTG_STATE_A_WAIT_BCON:
@@ -807,7 +798,7 @@
 	return idle_timeout;
 }
 
-static irqreturn_t tusb_interrupt(int irq, void *__hci)
+static irqreturn_t tusb_musb_interrupt(int irq, void *__hci)
 {
 	struct musb	*musb = __hci;
 	void __iomem	*tbase = musb->ctrl_base;
@@ -911,7 +902,7 @@
 	musb_writel(tbase, TUSB_INT_SRC_CLEAR,
 		int_src & ~TUSB_INT_MASK_RESERVED_BITS);
 
-	musb_platform_try_idle(musb, idle_timeout);
+	tusb_musb_try_idle(musb, idle_timeout);
 
 	musb_writel(tbase, TUSB_INT_MASK, int_mask);
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -926,7 +917,7 @@
  * REVISIT:
  * - Check what is unnecessary in MGC_HdrcStart()
  */
-void musb_platform_enable(struct musb *musb)
+static void tusb_musb_enable(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 
@@ -970,7 +961,7 @@
 /*
  * Disables TUSB6010. Caller must take care of locking.
  */
-void musb_platform_disable(struct musb *musb)
+static void tusb_musb_disable(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 
@@ -995,7 +986,7 @@
  * Sets up TUSB6010 CPU interface specific signals and registers
  * Note: Settings optimized for OMAP24xx
  */
-static void __init tusb_setup_cpu_interface(struct musb *musb)
+static void tusb_setup_cpu_interface(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 
@@ -1022,7 +1013,7 @@
 	musb_writel(tbase, TUSB_WAIT_COUNT, 1);
 }
 
-static int __init tusb_start(struct musb *musb)
+static int tusb_musb_start(struct musb *musb)
 {
 	void __iomem	*tbase = musb->ctrl_base;
 	int		ret = 0;
@@ -1091,7 +1082,7 @@
 	return -ENODEV;
 }
 
-int __init musb_platform_init(struct musb *musb, void *board_data)
+static int tusb_musb_init(struct musb *musb)
 {
 	struct platform_device	*pdev;
 	struct resource		*mem;
@@ -1131,16 +1122,14 @@
 	 */
 	musb->mregs += TUSB_BASE_OFFSET;
 
-	ret = tusb_start(musb);
+	ret = tusb_musb_start(musb);
 	if (ret) {
 		printk(KERN_ERR "Could not start tusb6010 (%d)\n",
 				ret);
 		goto done;
 	}
-	musb->isr = tusb_interrupt;
+	musb->isr = tusb_musb_interrupt;
 
-	if (is_host_enabled(musb))
-		musb->board_set_vbus = tusb_source_power;
 	if (is_peripheral_enabled(musb)) {
 		musb->xceiv->set_power = tusb_draw_power;
 		the_musb = musb;
@@ -1159,7 +1148,7 @@
 	return ret;
 }
 
-int musb_platform_exit(struct musb *musb)
+static int tusb_musb_exit(struct musb *musb)
 {
 	del_timer_sync(&musb_idle_timer);
 	the_musb = NULL;
@@ -1173,3 +1162,115 @@
 	usb_nop_xceiv_unregister();
 	return 0;
 }
+
+static const struct musb_platform_ops tusb_ops = {
+	.init		= tusb_musb_init,
+	.exit		= tusb_musb_exit,
+
+	.enable		= tusb_musb_enable,
+	.disable	= tusb_musb_disable,
+
+	.set_mode	= tusb_musb_set_mode,
+	.try_idle	= tusb_musb_try_idle,
+
+	.vbus_status	= tusb_musb_vbus_status,
+	.set_vbus	= tusb_musb_set_vbus,
+};
+
+static u64 tusb_dmamask = DMA_BIT_MASK(32);
+
+static int __init tusb_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct tusb6010_glue		*glue;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &tusb_dmamask;
+	musb->dev.coherent_dma_mask	= tusb_dmamask;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+
+	pdata->platform_ops		= &tusb_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err2;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err2;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err1;
+	}
+
+	return 0;
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit tusb_remove(struct platform_device *pdev)
+{
+	struct tusb6010_glue		*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	kfree(glue);
+
+	return 0;
+}
+
+static struct platform_driver tusb_driver = {
+	.remove		= __exit_p(tusb_remove),
+	.driver		= {
+		.name	= "musb-tusb",
+	},
+};
+
+MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init tusb_init(void)
+{
+	return platform_driver_probe(&tusb_driver, tusb_probe);
+}
+subsys_initcall(tusb_init);
+
+static void __exit tusb_exit(void)
+{
+	platform_driver_unregister(&tusb_driver);
+}
+module_exit(tusb_exit);
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
new file mode 100644
index 0000000..d6384e4
--- /dev/null
+++ b/drivers/usb/musb/ux500.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2010 ST-Ericsson AB
+ * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ *
+ * Based on omap2430.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include "musb_core.h"
+
+struct ux500_glue {
+	struct device		*dev;
+	struct platform_device	*musb;
+	struct clk		*clk;
+};
+#define glue_to_musb(g)	platform_get_drvdata(g->musb)
+
+static int ux500_musb_init(struct musb *musb)
+{
+	musb->xceiv = otg_get_transceiver();
+	if (!musb->xceiv) {
+		pr_err("HS USB OTG: no transceiver configured\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int ux500_musb_exit(struct musb *musb)
+{
+	otg_put_transceiver(musb->xceiv);
+
+	return 0;
+}
+
+static const struct musb_platform_ops ux500_ops = {
+	.init		= ux500_musb_init,
+	.exit		= ux500_musb_exit,
+};
+
+static int __init ux500_probe(struct platform_device *pdev)
+{
+	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
+	struct platform_device		*musb;
+	struct ux500_glue		*glue;
+	struct clk			*clk;
+
+	int				ret = -ENOMEM;
+
+	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	if (!glue) {
+		dev_err(&pdev->dev, "failed to allocate glue context\n");
+		goto err0;
+	}
+
+	musb = platform_device_alloc("musb-hdrc", -1);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
+		goto err1;
+	}
+
+	clk = clk_get(&pdev->dev, "usb");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		ret = PTR_ERR(clk);
+		goto err2;
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		goto err3;
+	}
+
+	musb->dev.parent		= &pdev->dev;
+
+	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
+	glue->clk			= clk;
+
+	pdata->platform_ops		= &ux500_ops;
+
+	platform_set_drvdata(pdev, glue);
+
+	ret = platform_device_add_resources(musb, pdev->resource,
+			pdev->num_resources);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err4;
+	}
+
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err4;
+	}
+
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	clk_disable(clk);
+
+err3:
+	clk_put(clk);
+
+err2:
+	platform_device_put(musb);
+
+err1:
+	kfree(glue);
+
+err0:
+	return ret;
+}
+
+static int __exit ux500_remove(struct platform_device *pdev)
+{
+	struct ux500_glue	*glue = platform_get_drvdata(pdev);
+
+	platform_device_del(glue->musb);
+	platform_device_put(glue->musb);
+	clk_disable(glue->clk);
+	clk_put(glue->clk);
+	kfree(glue);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ux500_suspend(struct device *dev)
+{
+	struct ux500_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+
+	otg_set_suspend(musb->xceiv, 1);
+	clk_disable(glue->clk);
+
+	return 0;
+}
+
+static int ux500_resume(struct device *dev)
+{
+	struct ux500_glue	*glue = dev_get_drvdata(dev);
+	struct musb		*musb = glue_to_musb(glue);
+	int			ret;
+
+	ret = clk_enable(glue->clk);
+	if (ret) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	otg_set_suspend(musb->xceiv, 0);
+
+	return 0;
+}
+
+static const struct dev_pm_ops ux500_pm_ops = {
+	.suspend	= ux500_suspend,
+	.resume		= ux500_resume,
+};
+
+#define DEV_PM_OPS	(&ux500_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
+static struct platform_driver ux500_driver = {
+	.remove		= __exit_p(ux500_remove),
+	.driver		= {
+		.name	= "musb-ux500",
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
+MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init ux500_init(void)
+{
+	return platform_driver_probe(&ux500_driver, ux500_probe);
+}
+subsys_initcall(ux500_init);
+
+static void __exit ux500_exit(void)
+{
+	platform_driver_unregister(&ux500_driver);
+}
+module_exit(ux500_exit);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 5ce0752..9fb875d 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -59,6 +59,18 @@
 	  This transceiver supports high and full speed devices plus,
 	  in host mode, low speed.
 
+config TWL6030_USB
+	tristate "TWL6030 USB Transceiver Driver"
+	depends on TWL4030_CORE
+	select USB_OTG_UTILS
+	help
+	  Enable this to support the USB OTG transceiver on TWL6030
+	  family chips. This TWL6030 transceiver has the VBUS and ID GND
+	  and OTG SRP events capabilities. For all other transceiver functionality
+	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
+	  are hooked to this driver through platform_data structure.
+	  The definition of internal PHY APIs are in the mach-omap2 layer.
+
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
 	select USB_OTG_UTILS
@@ -81,4 +93,24 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called langwell_otg.
 
+config USB_MSM_OTG_72K
+	tristate "OTG support for Qualcomm on-chip USB controller"
+	depends on (USB || USB_GADGET) && ARCH_MSM
+	select USB_OTG_UTILS
+	help
+	  Enable this to support the USB OTG transceiver on MSM chips. It
+	  handles PHY initialization, clock management, and workarounds
+	  required after resetting the hardware and power management.
+	  This driver is required even for peripheral only or host only
+	  mode configurations.
+
+config AB8500_USB
+        tristate "AB8500 USB Transceiver Driver"
+        depends on AB8500_CORE
+        select USB_OTG_UTILS
+        help
+          Enable this to support the USB OTG transceiver in AB8500 chip.
+          This transceiver supports high and full speed devices plus,
+          in host mode, low speed.
+
 endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 66f1b83..a520e71 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -12,6 +12,9 @@
 obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
+obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
 obj-$(CONFIG_USB_LANGWELL_OTG)	+= langwell_otg.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
+obj-$(CONFIG_USB_MSM_OTG_72K)	+= msm72k_otg.o
+obj-$(CONFIG_AB8500_USB)	+= ab8500-usb.o
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
new file mode 100644
index 0000000..d14736b
--- /dev/null
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -0,0 +1,585 @@
+/*
+ * drivers/usb/otg/ab8500_usb.c
+ *
+ * USB transceiver driver for AB8500 chip
+ *
+ * Copyright (C) 2010 ST-Ericsson AB
+ * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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/platform_device.h>
+#include <linux/usb/otg.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500.h>
+
+#define AB8500_MAIN_WD_CTRL_REG 0x01
+#define AB8500_USB_LINE_STAT_REG 0x80
+#define AB8500_USB_PHY_CTRL_REG 0x8A
+
+#define AB8500_BIT_OTG_STAT_ID (1 << 0)
+#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
+#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
+#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
+#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
+
+#define AB8500_V1x_LINK_STAT_WAIT (HZ/10)
+#define AB8500_WD_KICK_DELAY_US 100 /* usec */
+#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
+#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */
+
+/* Usb line status register */
+enum ab8500_usb_link_status {
+	USB_LINK_NOT_CONFIGURED = 0,
+	USB_LINK_STD_HOST_NC,
+	USB_LINK_STD_HOST_C_NS,
+	USB_LINK_STD_HOST_C_S,
+	USB_LINK_HOST_CHG_NM,
+	USB_LINK_HOST_CHG_HS,
+	USB_LINK_HOST_CHG_HS_CHIRP,
+	USB_LINK_DEDICATED_CHG,
+	USB_LINK_ACA_RID_A,
+	USB_LINK_ACA_RID_B,
+	USB_LINK_ACA_RID_C_NM,
+	USB_LINK_ACA_RID_C_HS,
+	USB_LINK_ACA_RID_C_HS_CHIRP,
+	USB_LINK_HM_IDGND,
+	USB_LINK_RESERVED,
+	USB_LINK_NOT_VALID_LINK
+};
+
+struct ab8500_usb {
+	struct otg_transceiver otg;
+	struct device *dev;
+	int irq_num_id_rise;
+	int irq_num_id_fall;
+	int irq_num_vbus_rise;
+	int irq_num_vbus_fall;
+	int irq_num_link_status;
+	unsigned vbus_draw;
+	struct delayed_work dwork;
+	struct work_struct phy_dis_work;
+	unsigned long link_status_wait;
+	int rev;
+};
+
+static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x)
+{
+	return container_of(x, struct ab8500_usb, otg);
+}
+
+static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
+{
+	abx500_set_register_interruptible(ab->dev,
+		AB8500_SYS_CTRL2_BLOCK,
+		AB8500_MAIN_WD_CTRL_REG,
+		AB8500_BIT_WD_CTRL_ENABLE);
+
+	udelay(AB8500_WD_KICK_DELAY_US);
+
+	abx500_set_register_interruptible(ab->dev,
+		AB8500_SYS_CTRL2_BLOCK,
+		AB8500_MAIN_WD_CTRL_REG,
+		(AB8500_BIT_WD_CTRL_ENABLE
+		| AB8500_BIT_WD_CTRL_KICK));
+
+	if (ab->rev > 0x10) /* v1.1 v2.0 */
+		udelay(AB8500_WD_V11_DISABLE_DELAY_US);
+	else /* v1.0 */
+		msleep(AB8500_WD_V10_DISABLE_DELAY_MS);
+
+	abx500_set_register_interruptible(ab->dev,
+		AB8500_SYS_CTRL2_BLOCK,
+		AB8500_MAIN_WD_CTRL_REG,
+		0);
+}
+
+static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host,
+					bool enable)
+{
+	u8 ctrl_reg;
+	abx500_get_register_interruptible(ab->dev,
+				AB8500_USB,
+				AB8500_USB_PHY_CTRL_REG,
+				&ctrl_reg);
+	if (sel_host) {
+		if (enable)
+			ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN;
+		else
+			ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN;
+	} else {
+		if (enable)
+			ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN;
+		else
+			ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN;
+	}
+
+	abx500_set_register_interruptible(ab->dev,
+				AB8500_USB,
+				AB8500_USB_PHY_CTRL_REG,
+				ctrl_reg);
+
+	/* Needed to enable the phy.*/
+	if (enable)
+		ab8500_usb_wd_workaround(ab);
+}
+
+#define ab8500_usb_host_phy_en(ab)	ab8500_usb_phy_ctrl(ab, true, true)
+#define ab8500_usb_host_phy_dis(ab)	ab8500_usb_phy_ctrl(ab, true, false)
+#define ab8500_usb_peri_phy_en(ab)	ab8500_usb_phy_ctrl(ab, false, true)
+#define ab8500_usb_peri_phy_dis(ab)	ab8500_usb_phy_ctrl(ab, false, false)
+
+static int ab8500_usb_link_status_update(struct ab8500_usb *ab)
+{
+	u8 reg;
+	enum ab8500_usb_link_status lsts;
+	void *v = NULL;
+	enum usb_xceiv_events event;
+
+	abx500_get_register_interruptible(ab->dev,
+			AB8500_USB,
+			AB8500_USB_LINE_STAT_REG,
+			&reg);
+
+	lsts = (reg >> 3) & 0x0F;
+
+	switch (lsts) {
+	case USB_LINK_NOT_CONFIGURED:
+	case USB_LINK_RESERVED:
+	case USB_LINK_NOT_VALID_LINK:
+		/* TODO: Disable regulators. */
+		ab8500_usb_host_phy_dis(ab);
+		ab8500_usb_peri_phy_dis(ab);
+		ab->otg.state = OTG_STATE_B_IDLE;
+		ab->otg.default_a = false;
+		ab->vbus_draw = 0;
+		event = USB_EVENT_NONE;
+		break;
+
+	case USB_LINK_STD_HOST_NC:
+	case USB_LINK_STD_HOST_C_NS:
+	case USB_LINK_STD_HOST_C_S:
+	case USB_LINK_HOST_CHG_NM:
+	case USB_LINK_HOST_CHG_HS:
+	case USB_LINK_HOST_CHG_HS_CHIRP:
+		if (ab->otg.gadget) {
+			/* TODO: Enable regulators. */
+			ab8500_usb_peri_phy_en(ab);
+			v = ab->otg.gadget;
+		}
+		event = USB_EVENT_VBUS;
+		break;
+
+	case USB_LINK_HM_IDGND:
+		if (ab->otg.host) {
+			/* TODO: Enable regulators. */
+			ab8500_usb_host_phy_en(ab);
+			v = ab->otg.host;
+		}
+		ab->otg.state = OTG_STATE_A_IDLE;
+		ab->otg.default_a = true;
+		event = USB_EVENT_ID;
+		break;
+
+	case USB_LINK_ACA_RID_A:
+	case USB_LINK_ACA_RID_B:
+		/* TODO */
+	case USB_LINK_ACA_RID_C_NM:
+	case USB_LINK_ACA_RID_C_HS:
+	case USB_LINK_ACA_RID_C_HS_CHIRP:
+	case USB_LINK_DEDICATED_CHG:
+		/* TODO: vbus_draw */
+		event = USB_EVENT_CHARGER;
+		break;
+	}
+
+	blocking_notifier_call_chain(&ab->otg.notifier, event, v);
+
+	return 0;
+}
+
+static void ab8500_usb_delayed_work(struct work_struct *work)
+{
+	struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
+						dwork.work);
+
+	ab8500_usb_link_status_update(ab);
+}
+
+static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data)
+{
+	struct ab8500_usb *ab = (struct ab8500_usb *) data;
+
+	/* Wait for link status to become stable. */
+	schedule_delayed_work(&ab->dwork, ab->link_status_wait);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data)
+{
+	struct ab8500_usb *ab = (struct ab8500_usb *) data;
+
+	/* Link status will not be updated till phy is disabled. */
+	ab8500_usb_peri_phy_dis(ab);
+
+	/* Wait for link status to become stable. */
+	schedule_delayed_work(&ab->dwork, ab->link_status_wait);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ab8500_usb_v20_irq(int irq, void *data)
+{
+	struct ab8500_usb *ab = (struct ab8500_usb *) data;
+
+	ab8500_usb_link_status_update(ab);
+
+	return IRQ_HANDLED;
+}
+
+static void ab8500_usb_phy_disable_work(struct work_struct *work)
+{
+	struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
+						phy_dis_work);
+
+	if (!ab->otg.host)
+		ab8500_usb_host_phy_dis(ab);
+
+	if (!ab->otg.gadget)
+		ab8500_usb_peri_phy_dis(ab);
+}
+
+static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+	struct ab8500_usb *ab;
+
+	if (!otg)
+		return -ENODEV;
+
+	ab = xceiv_to_ab(otg);
+
+	ab->vbus_draw = mA;
+
+	if (mA)
+		blocking_notifier_call_chain(&ab->otg.notifier,
+				USB_EVENT_ENUMERATED, ab->otg.gadget);
+	return 0;
+}
+
+/* TODO: Implement some way for charging or other drivers to read
+ * ab->vbus_draw.
+ */
+
+static int ab8500_usb_set_suspend(struct otg_transceiver *x, int suspend)
+{
+	/* TODO */
+	return 0;
+}
+
+static int ab8500_usb_set_peripheral(struct otg_transceiver *otg,
+		struct usb_gadget *gadget)
+{
+	struct ab8500_usb *ab;
+
+	if (!otg)
+		return -ENODEV;
+
+	ab = xceiv_to_ab(otg);
+
+	/* Some drivers call this function in atomic context.
+	 * Do not update ab8500 registers directly till this
+	 * is fixed.
+	 */
+
+	if (!gadget) {
+		/* TODO: Disable regulators. */
+		ab->otg.gadget = NULL;
+		schedule_work(&ab->phy_dis_work);
+	} else {
+		ab->otg.gadget = gadget;
+		ab->otg.state = OTG_STATE_B_IDLE;
+
+		/* Phy will not be enabled if cable is already
+		 * plugged-in. Schedule to enable phy.
+		 * Use same delay to avoid any race condition.
+		 */
+		schedule_delayed_work(&ab->dwork, ab->link_status_wait);
+	}
+
+	return 0;
+}
+
+static int ab8500_usb_set_host(struct otg_transceiver *otg,
+					struct usb_bus *host)
+{
+	struct ab8500_usb *ab;
+
+	if (!otg)
+		return -ENODEV;
+
+	ab = xceiv_to_ab(otg);
+
+	/* Some drivers call this function in atomic context.
+	 * Do not update ab8500 registers directly till this
+	 * is fixed.
+	 */
+
+	if (!host) {
+		/* TODO: Disable regulators. */
+		ab->otg.host = NULL;
+		schedule_work(&ab->phy_dis_work);
+	} else {
+		ab->otg.host = host;
+		/* Phy will not be enabled if cable is already
+		 * plugged-in. Schedule to enable phy.
+		 * Use same delay to avoid any race condition.
+		 */
+		schedule_delayed_work(&ab->dwork, ab->link_status_wait);
+	}
+
+	return 0;
+}
+
+static void ab8500_usb_irq_free(struct ab8500_usb *ab)
+{
+	if (ab->rev < 0x20) {
+		free_irq(ab->irq_num_id_rise, ab);
+		free_irq(ab->irq_num_id_fall, ab);
+		free_irq(ab->irq_num_vbus_rise, ab);
+		free_irq(ab->irq_num_vbus_fall, ab);
+	} else {
+		free_irq(ab->irq_num_link_status, ab);
+	}
+}
+
+static int ab8500_usb_v1x_res_setup(struct platform_device *pdev,
+				struct ab8500_usb *ab)
+{
+	int err;
+
+	ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R");
+	if (ab->irq_num_id_rise < 0) {
+		dev_err(&pdev->dev, "ID rise irq not found\n");
+		return ab->irq_num_id_rise;
+	}
+	err = request_threaded_irq(ab->irq_num_id_rise, NULL,
+		ab8500_usb_v1x_common_irq,
+		IRQF_NO_SUSPEND | IRQF_SHARED,
+		"usb-id-rise", ab);
+	if (err < 0) {
+		dev_err(ab->dev, "request_irq failed for ID rise irq\n");
+		goto fail0;
+	}
+
+	ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
+	if (ab->irq_num_id_fall < 0) {
+		dev_err(&pdev->dev, "ID fall irq not found\n");
+		return ab->irq_num_id_fall;
+	}
+	err = request_threaded_irq(ab->irq_num_id_fall, NULL,
+		ab8500_usb_v1x_common_irq,
+		IRQF_NO_SUSPEND | IRQF_SHARED,
+		"usb-id-fall", ab);
+	if (err < 0) {
+		dev_err(ab->dev, "request_irq failed for ID fall irq\n");
+		goto fail1;
+	}
+
+	ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R");
+	if (ab->irq_num_vbus_rise < 0) {
+		dev_err(&pdev->dev, "VBUS rise irq not found\n");
+		return ab->irq_num_vbus_rise;
+	}
+	err = request_threaded_irq(ab->irq_num_vbus_rise, NULL,
+		ab8500_usb_v1x_common_irq,
+		IRQF_NO_SUSPEND | IRQF_SHARED,
+		"usb-vbus-rise", ab);
+	if (err < 0) {
+		dev_err(ab->dev, "request_irq failed for Vbus rise irq\n");
+		goto fail2;
+	}
+
+	ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F");
+	if (ab->irq_num_vbus_fall < 0) {
+		dev_err(&pdev->dev, "VBUS fall irq not found\n");
+		return ab->irq_num_vbus_fall;
+	}
+	err = request_threaded_irq(ab->irq_num_vbus_fall, NULL,
+		ab8500_usb_v1x_vbus_fall_irq,
+		IRQF_NO_SUSPEND | IRQF_SHARED,
+		"usb-vbus-fall", ab);
+	if (err < 0) {
+		dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
+		goto fail3;
+	}
+
+	return 0;
+fail3:
+	free_irq(ab->irq_num_vbus_rise, ab);
+fail2:
+	free_irq(ab->irq_num_id_fall, ab);
+fail1:
+	free_irq(ab->irq_num_id_rise, ab);
+fail0:
+	return err;
+}
+
+static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
+				struct ab8500_usb *ab)
+{
+	int err;
+
+	ab->irq_num_link_status = platform_get_irq_byname(pdev,
+						"USB_LINK_STATUS");
+	if (ab->irq_num_link_status < 0) {
+		dev_err(&pdev->dev, "Link status irq not found\n");
+		return ab->irq_num_link_status;
+	}
+
+	err = request_threaded_irq(ab->irq_num_link_status, NULL,
+		ab8500_usb_v20_irq,
+		IRQF_NO_SUSPEND | IRQF_SHARED,
+		"usb-link-status", ab);
+	if (err < 0) {
+		dev_err(ab->dev,
+			"request_irq failed for link status irq\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int __devinit ab8500_usb_probe(struct platform_device *pdev)
+{
+	struct ab8500_usb	*ab;
+	int err;
+	int rev;
+
+	rev = abx500_get_chip_id(&pdev->dev);
+	if (rev < 0) {
+		dev_err(&pdev->dev, "Chip id read failed\n");
+		return rev;
+	} else if (rev < 0x10) {
+		dev_err(&pdev->dev, "Unsupported AB8500 chip\n");
+		return -ENODEV;
+	}
+
+	ab = kzalloc(sizeof *ab, GFP_KERNEL);
+	if (!ab)
+		return -ENOMEM;
+
+	ab->dev			= &pdev->dev;
+	ab->rev			= rev;
+	ab->otg.dev		= ab->dev;
+	ab->otg.label		= "ab8500";
+	ab->otg.state		= OTG_STATE_UNDEFINED;
+	ab->otg.set_host	= ab8500_usb_set_host;
+	ab->otg.set_peripheral	= ab8500_usb_set_peripheral;
+	ab->otg.set_suspend	= ab8500_usb_set_suspend;
+	ab->otg.set_power	= ab8500_usb_set_power;
+
+	platform_set_drvdata(pdev, ab);
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&ab->otg.notifier);
+
+	/* v1: Wait for link status to become stable.
+	 * all: Updates form set_host and set_peripheral as they are atomic.
+	 */
+	INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work);
+
+	/* all: Disable phy when called from set_host and set_peripheral */
+	INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
+
+	if (ab->rev < 0x20) {
+		err = ab8500_usb_v1x_res_setup(pdev, ab);
+		ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT;
+	} else {
+		err = ab8500_usb_v2_res_setup(pdev, ab);
+	}
+
+	if (err < 0)
+		goto fail0;
+
+	err = otg_set_transceiver(&ab->otg);
+	if (err) {
+		dev_err(&pdev->dev, "Can't register transceiver\n");
+		goto fail1;
+	}
+
+	dev_info(&pdev->dev, "AB8500 usb driver initialized\n");
+
+	return 0;
+fail1:
+	ab8500_usb_irq_free(ab);
+fail0:
+	kfree(ab);
+	return err;
+}
+
+static int __devexit ab8500_usb_remove(struct platform_device *pdev)
+{
+	struct ab8500_usb *ab = platform_get_drvdata(pdev);
+
+	ab8500_usb_irq_free(ab);
+
+	cancel_delayed_work_sync(&ab->dwork);
+
+	cancel_work_sync(&ab->phy_dis_work);
+
+	otg_set_transceiver(NULL);
+
+	ab8500_usb_host_phy_dis(ab);
+	ab8500_usb_peri_phy_dis(ab);
+
+	platform_set_drvdata(pdev, NULL);
+
+	kfree(ab);
+
+	return 0;
+}
+
+static struct platform_driver ab8500_usb_driver = {
+	.probe		= ab8500_usb_probe,
+	.remove		= __devexit_p(ab8500_usb_remove),
+	.driver		= {
+		.name	= "ab8500-usb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ab8500_usb_init(void)
+{
+	return platform_driver_register(&ab8500_usb_driver);
+}
+subsys_initcall(ab8500_usb_init);
+
+static void __exit ab8500_usb_exit(void)
+{
+	platform_driver_unregister(&ab8500_usb_driver);
+}
+module_exit(ab8500_usb_exit);
+
+MODULE_ALIAS("platform:ab8500_usb");
+MODULE_AUTHOR("ST-Ericsson AB");
+MODULE_DESCRIPTION("AB8500 usb transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index 4569694..e00fa1b 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1247,7 +1247,7 @@
 	isp->timer.data = 0;
 	set_bit(WORK_STOP, &isp->todo);
 	del_timer_sync(&isp->timer);
-	flush_scheduled_work();
+	flush_work_sync(&isp->work);
 
 	put_device(&i2c->dev);
 	the_transceiver = NULL;
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
new file mode 100644
index 0000000..1cd52ed
--- /dev/null
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -0,0 +1,1125 @@
+/* Copyright (c) 2009-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/device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/msm_hsusb.h>
+#include <linux/usb/msm_hsusb_hw.h>
+
+#include <mach/clk.h>
+
+#define MSM_USB_BASE	(motg->regs)
+#define DRIVER_NAME	"msm_otg"
+
+#define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
+static int ulpi_read(struct otg_transceiver *otg, u32 reg)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	int cnt = 0;
+
+	/* initiate read operation */
+	writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
+	       USB_ULPI_VIEWPORT);
+
+	/* wait for completion */
+	while (cnt < ULPI_IO_TIMEOUT_USEC) {
+		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+		dev_err(otg->dev, "ulpi_read: timeout %08x\n",
+			readl(USB_ULPI_VIEWPORT));
+		return -ETIMEDOUT;
+	}
+	return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
+}
+
+static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	int cnt = 0;
+
+	/* initiate write operation */
+	writel(ULPI_RUN | ULPI_WRITE |
+	       ULPI_ADDR(reg) | ULPI_DATA(val),
+	       USB_ULPI_VIEWPORT);
+
+	/* wait for completion */
+	while (cnt < ULPI_IO_TIMEOUT_USEC) {
+		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+		dev_err(otg->dev, "ulpi_write: timeout\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static struct otg_io_access_ops msm_otg_io_ops = {
+	.read = ulpi_read,
+	.write = ulpi_write,
+};
+
+static void ulpi_init(struct msm_otg *motg)
+{
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	int *seq = pdata->phy_init_seq;
+
+	if (!seq)
+		return;
+
+	while (seq[0] >= 0) {
+		dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
+				seq[0], seq[1]);
+		ulpi_write(&motg->otg, seq[0], seq[1]);
+		seq += 2;
+	}
+}
+
+static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
+{
+	int ret;
+
+	if (assert) {
+		ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
+		if (ret)
+			dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
+	} else {
+		ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
+		if (ret)
+			dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
+	}
+	return ret;
+}
+
+static int msm_otg_phy_clk_reset(struct msm_otg *motg)
+{
+	int ret;
+
+	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
+	if (ret) {
+		dev_err(motg->otg.dev, "usb phy clk assert failed\n");
+		return ret;
+	}
+	usleep_range(10000, 12000);
+	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
+	if (ret)
+		dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
+	return ret;
+}
+
+static int msm_otg_phy_reset(struct msm_otg *motg)
+{
+	u32 val;
+	int ret;
+	int retries;
+
+	ret = msm_otg_link_clk_reset(motg, 1);
+	if (ret)
+		return ret;
+	ret = msm_otg_phy_clk_reset(motg);
+	if (ret)
+		return ret;
+	ret = msm_otg_link_clk_reset(motg, 0);
+	if (ret)
+		return ret;
+
+	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
+	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
+
+	for (retries = 3; retries > 0; retries--) {
+		ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
+				ULPI_CLR(ULPI_FUNC_CTRL));
+		if (!ret)
+			break;
+		ret = msm_otg_phy_clk_reset(motg);
+		if (ret)
+			return ret;
+	}
+	if (!retries)
+		return -ETIMEDOUT;
+
+	/* This reset calibrates the phy, if the above write succeeded */
+	ret = msm_otg_phy_clk_reset(motg);
+	if (ret)
+		return ret;
+
+	for (retries = 3; retries > 0; retries--) {
+		ret = ulpi_read(&motg->otg, ULPI_DEBUG);
+		if (ret != -ETIMEDOUT)
+			break;
+		ret = msm_otg_phy_clk_reset(motg);
+		if (ret)
+			return ret;
+	}
+	if (!retries)
+		return -ETIMEDOUT;
+
+	dev_info(motg->otg.dev, "phy_reset: success\n");
+	return 0;
+}
+
+#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
+static int msm_otg_reset(struct otg_transceiver *otg)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	int cnt = 0;
+	int ret;
+	u32 val = 0;
+	u32 ulpi_val = 0;
+
+	ret = msm_otg_phy_reset(motg);
+	if (ret) {
+		dev_err(otg->dev, "phy_reset failed\n");
+		return ret;
+	}
+
+	ulpi_init(motg);
+
+	writel(USBCMD_RESET, USB_USBCMD);
+	while (cnt < LINK_RESET_TIMEOUT_USEC) {
+		if (!(readl(USB_USBCMD) & USBCMD_RESET))
+			break;
+		udelay(1);
+		cnt++;
+	}
+	if (cnt >= LINK_RESET_TIMEOUT_USEC)
+		return -ETIMEDOUT;
+
+	/* select ULPI phy */
+	writel(0x80000000, USB_PORTSC);
+
+	msleep(100);
+
+	writel(0x0, USB_AHBBURST);
+	writel(0x00, USB_AHBMODE);
+
+	if (pdata->otg_control == OTG_PHY_CONTROL) {
+		val = readl(USB_OTGSC);
+		if (pdata->mode == USB_OTG) {
+			ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
+			val |= OTGSC_IDIE | OTGSC_BSVIE;
+		} else if (pdata->mode == USB_PERIPHERAL) {
+			ulpi_val = ULPI_INT_SESS_VALID;
+			val |= OTGSC_BSVIE;
+		}
+		writel(val, USB_OTGSC);
+		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
+		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
+	}
+
+	return 0;
+}
+
+#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
+static int msm_otg_suspend(struct msm_otg *motg)
+{
+	struct otg_transceiver *otg = &motg->otg;
+	struct usb_bus *bus = otg->host;
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	int cnt = 0;
+
+	if (atomic_read(&motg->in_lpm))
+		return 0;
+
+	disable_irq(motg->irq);
+	/*
+	 * Interrupt Latch Register auto-clear feature is not present
+	 * in all PHY versions. Latch register is clear on read type.
+	 * Clear latch register to avoid spurious wakeup from
+	 * low power mode (LPM).
+	 */
+	ulpi_read(otg, 0x14);
+
+	/*
+	 * PHY comparators are disabled when PHY enters into low power
+	 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
+	 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
+	 * PHY comparators. This save significant amount of power.
+	 */
+	if (pdata->otg_control == OTG_PHY_CONTROL)
+		ulpi_write(otg, 0x01, 0x30);
+
+	/*
+	 * PLL is not turned off when PHY enters into low power mode (LPM).
+	 * Disable PLL for maximum power savings.
+	 */
+	ulpi_write(otg, 0x08, 0x09);
+
+	/*
+	 * PHY may take some time or even fail to enter into low power
+	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
+	 * in failure case.
+	 */
+	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
+	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
+		if (readl(USB_PORTSC) & PORTSC_PHCD)
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
+		dev_err(otg->dev, "Unable to suspend PHY\n");
+		msm_otg_reset(otg);
+		enable_irq(motg->irq);
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * PHY has capability to generate interrupt asynchronously in low
+	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
+	 * line must be disabled till async interrupt enable bit is cleared
+	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
+	 * block data communication from PHY.
+	 */
+	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+	if (motg->core_clk)
+		clk_disable(motg->core_clk);
+
+	if (device_may_wakeup(otg->dev))
+		enable_irq_wake(motg->irq);
+	if (bus)
+		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
+
+	atomic_set(&motg->in_lpm, 1);
+	enable_irq(motg->irq);
+
+	dev_info(otg->dev, "USB in low power mode\n");
+
+	return 0;
+}
+
+#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
+static int msm_otg_resume(struct msm_otg *motg)
+{
+	struct otg_transceiver *otg = &motg->otg;
+	struct usb_bus *bus = otg->host;
+	int cnt = 0;
+	unsigned temp;
+
+	if (!atomic_read(&motg->in_lpm))
+		return 0;
+
+	clk_enable(motg->pclk);
+	clk_enable(motg->clk);
+	if (motg->core_clk)
+		clk_enable(motg->core_clk);
+
+	temp = readl(USB_USBCMD);
+	temp &= ~ASYNC_INTR_CTRL;
+	temp &= ~ULPI_STP_CTRL;
+	writel(temp, USB_USBCMD);
+
+	/*
+	 * PHY comes out of low power mode (LPM) in case of wakeup
+	 * from asynchronous interrupt.
+	 */
+	if (!(readl(USB_PORTSC) & PORTSC_PHCD))
+		goto skip_phy_resume;
+
+	writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
+	while (cnt < PHY_RESUME_TIMEOUT_USEC) {
+		if (!(readl(USB_PORTSC) & PORTSC_PHCD))
+			break;
+		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
+		/*
+		 * This is a fatal error. Reset the link and
+		 * PHY. USB state can not be restored. Re-insertion
+		 * of USB cable is the only way to get USB working.
+		 */
+		dev_err(otg->dev, "Unable to resume USB."
+				"Re-plugin the cable\n");
+		msm_otg_reset(otg);
+	}
+
+skip_phy_resume:
+	if (device_may_wakeup(otg->dev))
+		disable_irq_wake(motg->irq);
+	if (bus)
+		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
+
+	if (motg->async_int) {
+		motg->async_int = 0;
+		pm_runtime_put(otg->dev);
+		enable_irq(motg->irq);
+	}
+
+	atomic_set(&motg->in_lpm, 0);
+
+	dev_info(otg->dev, "USB exited from low power mode\n");
+
+	return 0;
+}
+
+static void msm_otg_start_host(struct otg_transceiver *otg, int on)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	struct usb_hcd *hcd;
+
+	if (!otg->host)
+		return;
+
+	hcd = bus_to_hcd(otg->host);
+
+	if (on) {
+		dev_dbg(otg->dev, "host on\n");
+
+		if (pdata->vbus_power)
+			pdata->vbus_power(1);
+		/*
+		 * Some boards have a switch cotrolled by gpio
+		 * to enable/disable internal HUB. Enable internal
+		 * HUB before kicking the host.
+		 */
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_A_HOST);
+#ifdef CONFIG_USB
+		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+#endif
+	} else {
+		dev_dbg(otg->dev, "host off\n");
+
+#ifdef CONFIG_USB
+		usb_remove_hcd(hcd);
+#endif
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_UNDEFINED);
+		if (pdata->vbus_power)
+			pdata->vbus_power(0);
+	}
+}
+
+static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct usb_hcd *hcd;
+
+	/*
+	 * Fail host registration if this board can support
+	 * only peripheral configuration.
+	 */
+	if (motg->pdata->mode == USB_PERIPHERAL) {
+		dev_info(otg->dev, "Host mode is not supported\n");
+		return -ENODEV;
+	}
+
+	if (!host) {
+		if (otg->state == OTG_STATE_A_HOST) {
+			pm_runtime_get_sync(otg->dev);
+			msm_otg_start_host(otg, 0);
+			otg->host = NULL;
+			otg->state = OTG_STATE_UNDEFINED;
+			schedule_work(&motg->sm_work);
+		} else {
+			otg->host = NULL;
+		}
+
+		return 0;
+	}
+
+	hcd = bus_to_hcd(host);
+	hcd->power_budget = motg->pdata->power_budget;
+
+	otg->host = host;
+	dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
+
+	/*
+	 * Kick the state machine work, if peripheral is not supported
+	 * or peripheral is already registered with us.
+	 */
+	if (motg->pdata->mode == USB_HOST || otg->gadget) {
+		pm_runtime_get_sync(otg->dev);
+		schedule_work(&motg->sm_work);
+	}
+
+	return 0;
+}
+
+static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	if (!otg->gadget)
+		return;
+
+	if (on) {
+		dev_dbg(otg->dev, "gadget on\n");
+		/*
+		 * Some boards have a switch cotrolled by gpio
+		 * to enable/disable internal HUB. Disable internal
+		 * HUB before kicking the gadget.
+		 */
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
+		usb_gadget_vbus_connect(otg->gadget);
+	} else {
+		dev_dbg(otg->dev, "gadget off\n");
+		usb_gadget_vbus_disconnect(otg->gadget);
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_UNDEFINED);
+	}
+
+}
+
+static int msm_otg_set_peripheral(struct otg_transceiver *otg,
+			struct usb_gadget *gadget)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+	/*
+	 * Fail peripheral registration if this board can support
+	 * only host configuration.
+	 */
+	if (motg->pdata->mode == USB_HOST) {
+		dev_info(otg->dev, "Peripheral mode is not supported\n");
+		return -ENODEV;
+	}
+
+	if (!gadget) {
+		if (otg->state == OTG_STATE_B_PERIPHERAL) {
+			pm_runtime_get_sync(otg->dev);
+			msm_otg_start_peripheral(otg, 0);
+			otg->gadget = NULL;
+			otg->state = OTG_STATE_UNDEFINED;
+			schedule_work(&motg->sm_work);
+		} else {
+			otg->gadget = NULL;
+		}
+
+		return 0;
+	}
+	otg->gadget = gadget;
+	dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
+
+	/*
+	 * Kick the state machine work, if host is not supported
+	 * or host is already registered with us.
+	 */
+	if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
+		pm_runtime_get_sync(otg->dev);
+		schedule_work(&motg->sm_work);
+	}
+
+	return 0;
+}
+
+/*
+ * We support OTG, Peripheral only and Host only configurations. In case
+ * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
+ * via Id pin status or user request (debugfs). Id/BSV interrupts are not
+ * enabled when switch is controlled by user and default mode is supplied
+ * by board file, which can be changed by userspace later.
+ */
+static void msm_otg_init_sm(struct msm_otg *motg)
+{
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	u32 otgsc = readl(USB_OTGSC);
+
+	switch (pdata->mode) {
+	case USB_OTG:
+		if (pdata->otg_control == OTG_PHY_CONTROL) {
+			if (otgsc & OTGSC_ID)
+				set_bit(ID, &motg->inputs);
+			else
+				clear_bit(ID, &motg->inputs);
+
+			if (otgsc & OTGSC_BSV)
+				set_bit(B_SESS_VLD, &motg->inputs);
+			else
+				clear_bit(B_SESS_VLD, &motg->inputs);
+		} else if (pdata->otg_control == OTG_USER_CONTROL) {
+			if (pdata->default_mode == USB_HOST) {
+				clear_bit(ID, &motg->inputs);
+			} else if (pdata->default_mode == USB_PERIPHERAL) {
+				set_bit(ID, &motg->inputs);
+				set_bit(B_SESS_VLD, &motg->inputs);
+			} else {
+				set_bit(ID, &motg->inputs);
+				clear_bit(B_SESS_VLD, &motg->inputs);
+			}
+		}
+		break;
+	case USB_HOST:
+		clear_bit(ID, &motg->inputs);
+		break;
+	case USB_PERIPHERAL:
+		set_bit(ID, &motg->inputs);
+		if (otgsc & OTGSC_BSV)
+			set_bit(B_SESS_VLD, &motg->inputs);
+		else
+			clear_bit(B_SESS_VLD, &motg->inputs);
+		break;
+	default:
+		break;
+	}
+}
+
+static void msm_otg_sm_work(struct work_struct *w)
+{
+	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
+	struct otg_transceiver *otg = &motg->otg;
+
+	switch (otg->state) {
+	case OTG_STATE_UNDEFINED:
+		dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
+		msm_otg_reset(otg);
+		msm_otg_init_sm(motg);
+		otg->state = OTG_STATE_B_IDLE;
+		/* FALL THROUGH */
+	case OTG_STATE_B_IDLE:
+		dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
+		if (!test_bit(ID, &motg->inputs) && otg->host) {
+			/* disable BSV bit */
+			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
+			msm_otg_start_host(otg, 1);
+			otg->state = OTG_STATE_A_HOST;
+		} else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
+			msm_otg_start_peripheral(otg, 1);
+			otg->state = OTG_STATE_B_PERIPHERAL;
+		}
+		pm_runtime_put_sync(otg->dev);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
+		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
+				!test_bit(ID, &motg->inputs)) {
+			msm_otg_start_peripheral(otg, 0);
+			otg->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg);
+			schedule_work(w);
+		}
+		break;
+	case OTG_STATE_A_HOST:
+		dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
+		if (test_bit(ID, &motg->inputs)) {
+			msm_otg_start_host(otg, 0);
+			otg->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg);
+			schedule_work(w);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static irqreturn_t msm_otg_irq(int irq, void *data)
+{
+	struct msm_otg *motg = data;
+	struct otg_transceiver *otg = &motg->otg;
+	u32 otgsc = 0;
+
+	if (atomic_read(&motg->in_lpm)) {
+		disable_irq_nosync(irq);
+		motg->async_int = 1;
+		pm_runtime_get(otg->dev);
+		return IRQ_HANDLED;
+	}
+
+	otgsc = readl(USB_OTGSC);
+	if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
+		return IRQ_NONE;
+
+	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
+		if (otgsc & OTGSC_ID)
+			set_bit(ID, &motg->inputs);
+		else
+			clear_bit(ID, &motg->inputs);
+		dev_dbg(otg->dev, "ID set/clear\n");
+		pm_runtime_get_noresume(otg->dev);
+	} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
+		if (otgsc & OTGSC_BSV)
+			set_bit(B_SESS_VLD, &motg->inputs);
+		else
+			clear_bit(B_SESS_VLD, &motg->inputs);
+		dev_dbg(otg->dev, "BSV set/clear\n");
+		pm_runtime_get_noresume(otg->dev);
+	}
+
+	writel(otgsc, USB_OTGSC);
+	schedule_work(&motg->sm_work);
+	return IRQ_HANDLED;
+}
+
+static int msm_otg_mode_show(struct seq_file *s, void *unused)
+{
+	struct msm_otg *motg = s->private;
+	struct otg_transceiver *otg = &motg->otg;
+
+	switch (otg->state) {
+	case OTG_STATE_A_HOST:
+		seq_printf(s, "host\n");
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		seq_printf(s, "peripheral\n");
+		break;
+	default:
+		seq_printf(s, "none\n");
+		break;
+	}
+
+	return 0;
+}
+
+static int msm_otg_mode_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, msm_otg_mode_show, inode->i_private);
+}
+
+static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
+				size_t count, loff_t *ppos)
+{
+	struct msm_otg *motg = file->private_data;
+	char buf[16];
+	struct otg_transceiver *otg = &motg->otg;
+	int status = count;
+	enum usb_mode_type req_mode;
+
+	memset(buf, 0x00, sizeof(buf));
+
+	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
+		status = -EFAULT;
+		goto out;
+	}
+
+	if (!strncmp(buf, "host", 4)) {
+		req_mode = USB_HOST;
+	} else if (!strncmp(buf, "peripheral", 10)) {
+		req_mode = USB_PERIPHERAL;
+	} else if (!strncmp(buf, "none", 4)) {
+		req_mode = USB_NONE;
+	} else {
+		status = -EINVAL;
+		goto out;
+	}
+
+	switch (req_mode) {
+	case USB_NONE:
+		switch (otg->state) {
+		case OTG_STATE_A_HOST:
+		case OTG_STATE_B_PERIPHERAL:
+			set_bit(ID, &motg->inputs);
+			clear_bit(B_SESS_VLD, &motg->inputs);
+			break;
+		default:
+			goto out;
+		}
+		break;
+	case USB_PERIPHERAL:
+		switch (otg->state) {
+		case OTG_STATE_B_IDLE:
+		case OTG_STATE_A_HOST:
+			set_bit(ID, &motg->inputs);
+			set_bit(B_SESS_VLD, &motg->inputs);
+			break;
+		default:
+			goto out;
+		}
+		break;
+	case USB_HOST:
+		switch (otg->state) {
+		case OTG_STATE_B_IDLE:
+		case OTG_STATE_B_PERIPHERAL:
+			clear_bit(ID, &motg->inputs);
+			break;
+		default:
+			goto out;
+		}
+		break;
+	default:
+		goto out;
+	}
+
+	pm_runtime_get_sync(otg->dev);
+	schedule_work(&motg->sm_work);
+out:
+	return status;
+}
+
+const struct file_operations msm_otg_mode_fops = {
+	.open = msm_otg_mode_open,
+	.read = seq_read,
+	.write = msm_otg_mode_write,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static struct dentry *msm_otg_dbg_root;
+static struct dentry *msm_otg_dbg_mode;
+
+static int msm_otg_debugfs_init(struct msm_otg *motg)
+{
+	msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
+
+	if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
+		return -ENODEV;
+
+	msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR,
+				msm_otg_dbg_root, motg, &msm_otg_mode_fops);
+	if (!msm_otg_dbg_mode) {
+		debugfs_remove(msm_otg_dbg_root);
+		msm_otg_dbg_root = NULL;
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void msm_otg_debugfs_cleanup(void)
+{
+	debugfs_remove(msm_otg_dbg_mode);
+	debugfs_remove(msm_otg_dbg_root);
+}
+
+static int __init msm_otg_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct resource *res;
+	struct msm_otg *motg;
+	struct otg_transceiver *otg;
+
+	dev_info(&pdev->dev, "msm_otg probe\n");
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
+		return -ENODEV;
+	}
+
+	motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
+	if (!motg) {
+		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
+		return -ENOMEM;
+	}
+
+	motg->pdata = pdev->dev.platform_data;
+	otg = &motg->otg;
+	otg->dev = &pdev->dev;
+
+	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
+	if (IS_ERR(motg->phy_reset_clk)) {
+		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
+		ret = PTR_ERR(motg->phy_reset_clk);
+		goto free_motg;
+	}
+
+	motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
+	if (IS_ERR(motg->clk)) {
+		dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
+		ret = PTR_ERR(motg->clk);
+		goto put_phy_reset_clk;
+	}
+
+	motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
+	if (IS_ERR(motg->pclk)) {
+		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
+		ret = PTR_ERR(motg->pclk);
+		goto put_clk;
+	}
+
+	/*
+	 * USB core clock is not present on all MSM chips. This
+	 * clock is introduced to remove the dependency on AXI
+	 * bus frequency.
+	 */
+	motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
+	if (IS_ERR(motg->core_clk))
+		motg->core_clk = NULL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get platform resource mem\n");
+		ret = -ENODEV;
+		goto put_core_clk;
+	}
+
+	motg->regs = ioremap(res->start, resource_size(res));
+	if (!motg->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto put_core_clk;
+	}
+	dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
+
+	motg->irq = platform_get_irq(pdev, 0);
+	if (!motg->irq) {
+		dev_err(&pdev->dev, "platform_get_irq failed\n");
+		ret = -ENODEV;
+		goto free_regs;
+	}
+
+	clk_enable(motg->clk);
+	clk_enable(motg->pclk);
+	if (motg->core_clk)
+		clk_enable(motg->core_clk);
+
+	writel(0, USB_USBINTR);
+	writel(0, USB_OTGSC);
+
+	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
+					"msm_otg", motg);
+	if (ret) {
+		dev_err(&pdev->dev, "request irq failed\n");
+		goto disable_clks;
+	}
+
+	otg->init = msm_otg_reset;
+	otg->set_host = msm_otg_set_host;
+	otg->set_peripheral = msm_otg_set_peripheral;
+
+	otg->io_ops = &msm_otg_io_ops;
+
+	ret = otg_set_transceiver(&motg->otg);
+	if (ret) {
+		dev_err(&pdev->dev, "otg_set_transceiver failed\n");
+		goto free_irq;
+	}
+
+	platform_set_drvdata(pdev, motg);
+	device_init_wakeup(&pdev->dev, 1);
+
+	if (motg->pdata->mode == USB_OTG &&
+			motg->pdata->otg_control == OTG_USER_CONTROL) {
+		ret = msm_otg_debugfs_init(motg);
+		if (ret)
+			dev_dbg(&pdev->dev, "mode debugfs file is"
+					"not available\n");
+	}
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+free_irq:
+	free_irq(motg->irq, motg);
+disable_clks:
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+free_regs:
+	iounmap(motg->regs);
+put_core_clk:
+	if (motg->core_clk)
+		clk_put(motg->core_clk);
+	clk_put(motg->pclk);
+put_clk:
+	clk_put(motg->clk);
+put_phy_reset_clk:
+	clk_put(motg->phy_reset_clk);
+free_motg:
+	kfree(motg);
+	return ret;
+}
+
+static int __devexit msm_otg_remove(struct platform_device *pdev)
+{
+	struct msm_otg *motg = platform_get_drvdata(pdev);
+	struct otg_transceiver *otg = &motg->otg;
+	int cnt = 0;
+
+	if (otg->host || otg->gadget)
+		return -EBUSY;
+
+	msm_otg_debugfs_cleanup();
+	cancel_work_sync(&motg->sm_work);
+
+	msm_otg_resume(motg);
+
+	device_init_wakeup(&pdev->dev, 0);
+	pm_runtime_disable(&pdev->dev);
+
+	otg_set_transceiver(NULL);
+	free_irq(motg->irq, motg);
+
+	/*
+	 * Put PHY in low power mode.
+	 */
+	ulpi_read(otg, 0x14);
+	ulpi_write(otg, 0x08, 0x09);
+
+	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
+	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
+		if (readl(USB_PORTSC) & PORTSC_PHCD)
+			break;
+		udelay(1);
+		cnt++;
+	}
+	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
+		dev_err(otg->dev, "Unable to suspend PHY\n");
+
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+	if (motg->core_clk)
+		clk_disable(motg->core_clk);
+
+	iounmap(motg->regs);
+	pm_runtime_set_suspended(&pdev->dev);
+
+	clk_put(motg->phy_reset_clk);
+	clk_put(motg->pclk);
+	clk_put(motg->clk);
+	if (motg->core_clk)
+		clk_put(motg->core_clk);
+
+	kfree(motg);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_otg_runtime_idle(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+	struct otg_transceiver *otg = &motg->otg;
+
+	dev_dbg(dev, "OTG runtime idle\n");
+
+	/*
+	 * It is observed some times that a spurious interrupt
+	 * comes when PHY is put into LPM immediately after PHY reset.
+	 * This 1 sec delay also prevents entering into LPM immediately
+	 * after asynchronous interrupt.
+	 */
+	if (otg->state != OTG_STATE_UNDEFINED)
+		pm_schedule_suspend(dev, 1000);
+
+	return -EAGAIN;
+}
+
+static int msm_otg_runtime_suspend(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "OTG runtime suspend\n");
+	return msm_otg_suspend(motg);
+}
+
+static int msm_otg_runtime_resume(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "OTG runtime resume\n");
+	return msm_otg_resume(motg);
+}
+#else
+#define msm_otg_runtime_idle	NULL
+#define msm_otg_runtime_suspend	NULL
+#define msm_otg_runtime_resume	NULL
+#endif
+
+#ifdef CONFIG_PM
+static int msm_otg_pm_suspend(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "OTG PM suspend\n");
+	return msm_otg_suspend(motg);
+}
+
+static int msm_otg_pm_resume(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+	int ret;
+
+	dev_dbg(dev, "OTG PM resume\n");
+
+	ret = msm_otg_resume(motg);
+	if (ret)
+		return ret;
+
+	/*
+	 * Runtime PM Documentation recommends bringing the
+	 * device to full powered state upon resume.
+	 */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+#else
+#define msm_otg_pm_suspend	NULL
+#define msm_otg_pm_resume	NULL
+#endif
+
+static const struct dev_pm_ops msm_otg_dev_pm_ops = {
+	.runtime_suspend = msm_otg_runtime_suspend,
+	.runtime_resume  = msm_otg_runtime_resume,
+	.runtime_idle    = msm_otg_runtime_idle,
+	.suspend         = msm_otg_pm_suspend,
+	.resume          = msm_otg_pm_resume,
+};
+
+static struct platform_driver msm_otg_driver = {
+	.remove = __devexit_p(msm_otg_remove),
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm = &msm_otg_dev_pm_ops,
+	},
+};
+
+static int __init msm_otg_init(void)
+{
+	return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
+}
+
+static void __exit msm_otg_exit(void)
+{
+	platform_driver_unregister(&msm_otg_driver);
+}
+
+module_init(msm_otg_init);
+module_exit(msm_otg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM USB transceiver driver");
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index d335f48..6ca505f 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -678,7 +678,8 @@
 	/* disable complete OTG block */
 	twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
 
-	twl4030_phy_power(twl, 0);
+	if (!twl->asleep)
+		twl4030_phy_power(twl, 0);
 	regulator_put(twl->usb1v5);
 	regulator_put(twl->usb1v8);
 	regulator_put(twl->usb3v1);
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
new file mode 100644
index 0000000..28f7701
--- /dev/null
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -0,0 +1,493 @@
+/*
+ * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+
+/* usb register definitions */
+#define USB_VENDOR_ID_LSB		0x00
+#define USB_VENDOR_ID_MSB		0x01
+#define USB_PRODUCT_ID_LSB		0x02
+#define USB_PRODUCT_ID_MSB		0x03
+#define USB_VBUS_CTRL_SET		0x04
+#define USB_VBUS_CTRL_CLR		0x05
+#define USB_ID_CTRL_SET			0x06
+#define USB_ID_CTRL_CLR			0x07
+#define USB_VBUS_INT_SRC		0x08
+#define USB_VBUS_INT_LATCH_SET		0x09
+#define USB_VBUS_INT_LATCH_CLR		0x0A
+#define USB_VBUS_INT_EN_LO_SET		0x0B
+#define USB_VBUS_INT_EN_LO_CLR		0x0C
+#define USB_VBUS_INT_EN_HI_SET		0x0D
+#define USB_VBUS_INT_EN_HI_CLR		0x0E
+#define USB_ID_INT_SRC			0x0F
+#define USB_ID_INT_LATCH_SET		0x10
+#define USB_ID_INT_LATCH_CLR		0x11
+
+#define USB_ID_INT_EN_LO_SET		0x12
+#define USB_ID_INT_EN_LO_CLR		0x13
+#define USB_ID_INT_EN_HI_SET		0x14
+#define USB_ID_INT_EN_HI_CLR		0x15
+#define USB_OTG_ADP_CTRL		0x16
+#define USB_OTG_ADP_HIGH		0x17
+#define USB_OTG_ADP_LOW			0x18
+#define USB_OTG_ADP_RISE		0x19
+#define USB_OTG_REVISION		0x1A
+
+/* to be moved to LDO */
+#define TWL6030_MISC2			0xE5
+#define TWL6030_CFG_LDO_PD2		0xF5
+#define TWL6030_BACKUP_REG		0xFA
+
+#define STS_HW_CONDITIONS		0x21
+
+/* In module TWL6030_MODULE_PM_MASTER */
+#define STS_HW_CONDITIONS		0x21
+#define STS_USB_ID			BIT(2)
+
+/* In module TWL6030_MODULE_PM_RECEIVER */
+#define VUSB_CFG_TRANS			0x71
+#define VUSB_CFG_STATE			0x72
+#define VUSB_CFG_VOLTAGE		0x73
+
+/* in module TWL6030_MODULE_MAIN_CHARGE */
+
+#define CHARGERUSB_CTRL1		0x8
+
+#define CONTROLLER_STAT1		0x03
+#define	VBUS_DET			BIT(2)
+
+struct twl6030_usb {
+	struct otg_transceiver	otg;
+	struct device		*dev;
+
+	/* for vbus reporting with irqs disabled */
+	spinlock_t		lock;
+
+	struct regulator		*usb3v3;
+
+	int			irq1;
+	int			irq2;
+	u8			linkstat;
+	u8			asleep;
+	bool			irq_enabled;
+};
+
+#define xceiv_to_twl(x)		container_of((x), struct twl6030_usb, otg);
+
+/*-------------------------------------------------------------------------*/
+
+static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
+						u8 data, u8 address)
+{
+	int ret = 0;
+
+	ret = twl_i2c_write_u8(module, data, address);
+	if (ret < 0)
+		dev_err(twl->dev,
+			"Write[0x%x] Error %d\n", address, ret);
+	return ret;
+}
+
+static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
+{
+	u8 data, ret = 0;
+
+	ret = twl_i2c_read_u8(module, &data, address);
+	if (ret >= 0)
+		ret = data;
+	else
+		dev_err(twl->dev,
+			"readb[0x%x,0x%x] Error %d\n",
+					module, address, ret);
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static int twl6030_set_phy_clk(struct otg_transceiver *x, int on)
+{
+	struct twl6030_usb *twl;
+	struct device *dev;
+	struct twl4030_usb_data *pdata;
+
+	twl = xceiv_to_twl(x);
+	dev  = twl->dev;
+	pdata = dev->platform_data;
+
+	pdata->phy_set_clock(twl->dev, on);
+
+	return 0;
+}
+
+static int twl6030_phy_init(struct otg_transceiver *x)
+{
+	u8 hw_state;
+	struct twl6030_usb *twl;
+	struct device *dev;
+	struct twl4030_usb_data *pdata;
+
+	twl = xceiv_to_twl(x);
+	dev  = twl->dev;
+	pdata = dev->platform_data;
+
+	regulator_enable(twl->usb3v3);
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	if (hw_state & STS_USB_ID)
+		pdata->phy_power(twl->dev, 1, 1);
+	else
+		pdata->phy_power(twl->dev, 0, 1);
+
+	return 0;
+}
+
+static void twl6030_phy_shutdown(struct otg_transceiver *x)
+{
+	struct twl6030_usb *twl;
+	struct device *dev;
+	struct twl4030_usb_data *pdata;
+
+	twl = xceiv_to_twl(x);
+	dev  = twl->dev;
+	pdata = dev->platform_data;
+	pdata->phy_power(twl->dev, 0, 0);
+	regulator_disable(twl->usb3v3);
+}
+
+static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
+{
+
+	/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
+
+	/* Program CFG_LDO_PD2 register and set VUSB bit */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2);
+
+	/* Program MISC2 register and set bit VUSB_IN_VBAT */
+	twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
+
+	twl->usb3v3 = regulator_get(twl->dev, "vusb");
+	if (IS_ERR(twl->usb3v3))
+		return -ENODEV;
+
+	regulator_enable(twl->usb3v3);
+
+	/* Program the VUSB_CFG_TRANS for ACTIVE state. */
+	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x3F,
+						VUSB_CFG_TRANS);
+
+	/* Program the VUSB_CFG_STATE register to ON on all groups. */
+	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0xE1,
+						VUSB_CFG_STATE);
+
+	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
+
+	/*
+	 * Program the USB_ID_CTRL_SET register to enable GND drive
+	 * and the ID comparators
+	 */
+	twl6030_writeb(twl, TWL_MODULE_USB, 0x14, USB_ID_CTRL_SET);
+
+	return 0;
+}
+
+static ssize_t twl6030_usb_vbus_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct twl6030_usb *twl = dev_get_drvdata(dev);
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&twl->lock, flags);
+
+	switch (twl->linkstat) {
+	case USB_EVENT_VBUS:
+	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
+	       break;
+	case USB_EVENT_ID:
+	       ret = snprintf(buf, PAGE_SIZE, "id\n");
+	       break;
+	case USB_EVENT_NONE:
+	       ret = snprintf(buf, PAGE_SIZE, "none\n");
+	       break;
+	default:
+	       ret = snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
+	}
+	spin_unlock_irqrestore(&twl->lock, flags);
+
+	return ret;
+}
+static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
+
+static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
+{
+	struct twl6030_usb *twl = _twl;
+	int status;
+	u8 vbus_state, hw_state;
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE,
+						CONTROLLER_STAT1);
+	if (!(hw_state & STS_USB_ID)) {
+		if (vbus_state & VBUS_DET) {
+			status = USB_EVENT_VBUS;
+			twl->otg.default_a = false;
+			twl->otg.state = OTG_STATE_B_IDLE;
+		} else {
+			status = USB_EVENT_NONE;
+		}
+		if (status >= 0) {
+			twl->linkstat = status;
+			blocking_notifier_call_chain(&twl->otg.notifier,
+						status, twl->otg.gadget);
+		}
+	}
+	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
+{
+	struct twl6030_usb *twl = _twl;
+	int status = USB_EVENT_NONE;
+	u8 hw_state;
+
+	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
+
+	if (hw_state & STS_USB_ID) {
+
+		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
+		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
+								0x10);
+		status = USB_EVENT_ID;
+		twl->otg.default_a = true;
+		twl->otg.state = OTG_STATE_A_IDLE;
+		blocking_notifier_call_chain(&twl->otg.notifier, status,
+							twl->otg.gadget);
+	} else  {
+		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
+								0x10);
+		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
+								0x1);
+	}
+	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);
+	twl->linkstat = status;
+
+	return IRQ_HANDLED;
+}
+
+static int twl6030_set_peripheral(struct otg_transceiver *x,
+		struct usb_gadget *gadget)
+{
+	struct twl6030_usb *twl;
+
+	if (!x)
+		return -ENODEV;
+
+	twl = xceiv_to_twl(x);
+	twl->otg.gadget = gadget;
+	if (!gadget)
+		twl->otg.state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int twl6030_enable_irq(struct otg_transceiver *x)
+{
+	struct twl6030_usb *twl = xceiv_to_twl(x);
+
+	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
+	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
+	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
+
+	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
+				REG_INT_MSK_LINE_C);
+	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
+				REG_INT_MSK_STS_C);
+	twl6030_usb_irq(twl->irq2, twl);
+	twl6030_usbotg_irq(twl->irq1, twl);
+
+	return 0;
+}
+
+static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
+{
+	struct twl6030_usb *twl = xceiv_to_twl(x);
+
+	/*
+	 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
+	 * register. This enables boost mode.
+	 */
+	if (enabled)
+		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
+						CHARGERUSB_CTRL1);
+	 else
+		twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
+						CHARGERUSB_CTRL1);
+	return 0;
+}
+
+static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host)
+{
+	struct twl6030_usb *twl;
+
+	if (!x)
+		return -ENODEV;
+
+	twl = xceiv_to_twl(x);
+	twl->otg.host = host;
+	if (!host)
+		twl->otg.state = OTG_STATE_UNDEFINED;
+	return 0;
+}
+
+static int __devinit twl6030_usb_probe(struct platform_device *pdev)
+{
+	struct twl6030_usb	*twl;
+	int			status, err;
+	struct twl4030_usb_data *pdata;
+	struct device *dev = &pdev->dev;
+	pdata = dev->platform_data;
+
+	twl = kzalloc(sizeof *twl, GFP_KERNEL);
+	if (!twl)
+		return -ENOMEM;
+
+	twl->dev		= &pdev->dev;
+	twl->irq1		= platform_get_irq(pdev, 0);
+	twl->irq2		= platform_get_irq(pdev, 1);
+	twl->otg.dev		= twl->dev;
+	twl->otg.label		= "twl6030";
+	twl->otg.set_host	= twl6030_set_host;
+	twl->otg.set_peripheral	= twl6030_set_peripheral;
+	twl->otg.set_vbus	= twl6030_set_vbus;
+	twl->otg.init		= twl6030_phy_init;
+	twl->otg.shutdown	= twl6030_phy_shutdown;
+
+	/* init spinlock for workqueue */
+	spin_lock_init(&twl->lock);
+
+	err = twl6030_usb_ldo_init(twl);
+	if (err) {
+		dev_err(&pdev->dev, "ldo init failed\n");
+		kfree(twl);
+		return err;
+	}
+	otg_set_transceiver(&twl->otg);
+
+	platform_set_drvdata(pdev, twl);
+	if (device_create_file(&pdev->dev, &dev_attr_vbus))
+		dev_warn(&pdev->dev, "could not create sysfs file\n");
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
+
+	twl->irq_enabled = true;
+	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"twl6030_usb", twl);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+			twl->irq1, status);
+		device_remove_file(twl->dev, &dev_attr_vbus);
+		kfree(twl);
+		return status;
+	}
+
+	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"twl6030_usb", twl);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+			twl->irq2, status);
+		free_irq(twl->irq1, twl);
+		device_remove_file(twl->dev, &dev_attr_vbus);
+		kfree(twl);
+		return status;
+	}
+
+	pdata->phy_init(dev);
+	twl6030_enable_irq(&twl->otg);
+	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
+
+	return 0;
+}
+
+static int __exit twl6030_usb_remove(struct platform_device *pdev)
+{
+	struct twl6030_usb *twl = platform_get_drvdata(pdev);
+
+	struct twl4030_usb_data *pdata;
+	struct device *dev = &pdev->dev;
+	pdata = dev->platform_data;
+
+	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
+		REG_INT_MSK_LINE_C);
+	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
+			REG_INT_MSK_STS_C);
+	free_irq(twl->irq1, twl);
+	free_irq(twl->irq2, twl);
+	regulator_put(twl->usb3v3);
+	pdata->phy_exit(twl->dev);
+	device_remove_file(twl->dev, &dev_attr_vbus);
+	kfree(twl);
+
+	return 0;
+}
+
+static struct platform_driver twl6030_usb_driver = {
+	.probe		= twl6030_usb_probe,
+	.remove		= __exit_p(twl6030_usb_remove),
+	.driver		= {
+		.name	= "twl6030_usb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init twl6030_usb_init(void)
+{
+	return platform_driver_register(&twl6030_usb_driver);
+}
+subsys_initcall(twl6030_usb_init);
+
+static void __exit twl6030_usb_exit(void)
+{
+	platform_driver_unregister(&twl6030_usb_driver);
+}
+module_exit(twl6030_usb_exit);
+
+MODULE_ALIAS("platform:twl6030_usb");
+MODULE_AUTHOR("Hema HK <hemahk@ti.com>");
+MODULE_DESCRIPTION("TWL6030 USB transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 2dec500..a2668d0 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -75,6 +75,7 @@
 	unsigned long last_dtr_rts;	/* saved modem control outputs */
 	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
 	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
+	char transmit_empty;	/* If transmitter is empty or not */
 	struct usb_serial_port *port;
 	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface
 				   (0 for FT232/245) */
@@ -1323,6 +1324,23 @@
 	return 0;
 }
 
+static int get_lsr_info(struct usb_serial_port *port,
+			struct serial_struct __user *retinfo)
+{
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	unsigned int result = 0;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	if (priv->transmit_empty)
+		result = TIOCSER_TEMT;
+
+	if (copy_to_user(retinfo, &result, sizeof(unsigned int)))
+		return -EFAULT;
+	return 0;
+}
+
 
 /* Determine type of FTDI chip based on USB config and descriptor. */
 static void ftdi_determine_type(struct usb_serial_port *port)
@@ -1872,6 +1890,12 @@
 			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 	}
 
+	/* save if the transmitter is empty or not */
+	if (packet[1] & FTDI_RS_TEMT)
+		priv->transmit_empty = 1;
+	else
+		priv->transmit_empty = 0;
+
 	len -= 2;
 	if (!len)
 		return 0;	/* status only */
@@ -2235,6 +2259,9 @@
 			}
 		}
 		return 0;
+	case TIOCSERGETLSR:
+		return get_lsr_info(port, (struct serial_struct __user *)arg);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index ef2977d..cdfb186 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -989,6 +989,7 @@
 	.set_termios       = usb_wwan_set_termios,
 	.tiocmget          = usb_wwan_tiocmget,
 	.tiocmset          = usb_wwan_tiocmset,
+	.ioctl             = usb_wwan_ioctl,
 	.attach            = usb_wwan_startup,
 	.disconnect        = usb_wwan_disconnect,
 	.release           = usb_wwan_release,
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index e199b0f..5be866b 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -613,9 +613,8 @@
 	dbg("%s(): after buf_clear()", __func__);
 
 	/* cancel scheduled setup */
-	cancel_delayed_work(&priv->delayed_setup_work);
-	cancel_delayed_work(&priv->delayed_write_work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&priv->delayed_setup_work);
+	cancel_delayed_work_sync(&priv->delayed_write_work);
 
 	/* shutdown our urbs */
 	dbg("%s(): shutting down urbs", __func__);
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index f5312dd333..8359ec7 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -79,7 +79,6 @@
 	u8 shadowLSR;
 	u8 shadowMSR;
 	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
-	unsigned short max_packet_size;
 	struct async_icount icount;
 };
 
@@ -464,36 +463,6 @@
 	return -ENOIOCTLCMD;
 }
 
-static void ssu100_set_max_packet_size(struct usb_serial_port *port)
-{
-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-	struct usb_serial *serial = port->serial;
-	struct usb_device *udev = serial->dev;
-
-	struct usb_interface *interface = serial->interface;
-	struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
-
-	unsigned num_endpoints;
-	int i;
-	unsigned long flags;
-
-	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
-	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
-
-	for (i = 0; i < num_endpoints; i++) {
-		dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
-			interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
-		ep_desc = &interface->cur_altsetting->endpoint[i].desc;
-	}
-
-	/* set max packet size based on descriptor */
-	spin_lock_irqsave(&priv->status_lock, flags);
-	priv->max_packet_size = ep_desc->wMaxPacketSize;
-	spin_unlock_irqrestore(&priv->status_lock, flags);
-
-	dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
-}
-
 static int ssu100_attach(struct usb_serial *serial)
 {
 	struct ssu100_port_private *priv;
@@ -511,7 +480,6 @@
 	spin_lock_init(&priv->status_lock);
 	init_waitqueue_head(&priv->delta_msr_wait);
 	usb_set_serial_port_data(port, priv);
-	ssu100_set_max_packet_size(port);
 
 	return ssu100_initdevice(serial->dev);
 }
@@ -641,13 +609,14 @@
 
 }
 
-static int ssu100_process_packet(struct tty_struct *tty,
-				 struct usb_serial_port *port,
-				 struct ssu100_port_private *priv,
-				 char *packet, int len)
+static int ssu100_process_packet(struct urb *urb,
+				 struct tty_struct *tty)
 {
-	int i;
+	struct usb_serial_port *port = urb->context;
+	char *packet = (char *)urb->transfer_buffer;
 	char flag = TTY_NORMAL;
+	u32 len = urb->actual_length;
+	int i;
 	char *ch;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -685,12 +654,8 @@
 static void ssu100_process_read_urb(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-	char *data = (char *)urb->transfer_buffer;
 	struct tty_struct *tty;
-	int count = 0;
-	int i;
-	int len;
+	int count;
 
 	dbg("%s", __func__);
 
@@ -698,10 +663,7 @@
 	if (!tty)
 		return;
 
-	for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
-		len = min_t(int, urb->actual_length - i, priv->max_packet_size);
-		count += ssu100_process_packet(tty, port, priv, &data[i], len);
-	}
+	count = ssu100_process_packet(urb, tty);
 
 	if (count)
 		tty_flip_buffer_push(tty);
@@ -717,8 +679,6 @@
 	.id_table	     = id_table,
 	.usb_driver	     = &ssu100_driver,
 	.num_ports	     = 1,
-	.bulk_in_size        = 256,
-	.bulk_out_size       = 256,
 	.open		     = ssu100_open,
 	.close		     = ssu100_close,
 	.attach              = ssu100_attach,
diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
index 2be298a..3ab77c5 100644
--- a/drivers/usb/serial/usb-wwan.h
+++ b/drivers/usb/serial/usb-wwan.h
@@ -18,6 +18,8 @@
 extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file);
 extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
 			     unsigned int set, unsigned int clear);
+extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
+			  unsigned int cmd, unsigned long arg);
 extern int usb_wwan_send_setup(struct usb_serial_port *port);
 extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
 			  const unsigned char *buf, int count);
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index fbc9467..b004b2a 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -31,8 +31,10 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/serial.h>
 #include "usb-wwan.h"
 
 static int debug;
@@ -123,6 +125,83 @@
 }
 EXPORT_SYMBOL(usb_wwan_tiocmset);
 
+static int get_serial_info(struct usb_serial_port *port,
+			   struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.line            = port->serial->minor;
+	tmp.port            = port->number;
+	tmp.baud_base       = tty_get_baud_rate(port->port.tty);
+	tmp.close_delay	    = port->port.close_delay / 10;
+	tmp.closing_wait    = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+				 ASYNC_CLOSING_WAIT_NONE :
+				 port->port.closing_wait / 10;
+
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_serial_info(struct usb_serial_port *port,
+			   struct serial_struct __user *newinfo)
+{
+	struct serial_struct new_serial;
+	unsigned int closing_wait, close_delay;
+	int retval = 0;
+
+	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+		return -EFAULT;
+
+	close_delay = new_serial.close_delay * 10;
+	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+			ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
+
+	mutex_lock(&port->port.mutex);
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((close_delay != port->port.close_delay) ||
+		    (closing_wait != port->port.closing_wait))
+			retval = -EPERM;
+		else
+			retval = -EOPNOTSUPP;
+	} else {
+		port->port.close_delay  = close_delay;
+		port->port.closing_wait = closing_wait;
+	}
+
+	mutex_unlock(&port->port.mutex);
+	return retval;
+}
+
+int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
+		   unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial_port *port = tty->driver_data;
+
+	dbg("%s cmd 0x%04x", __func__, cmd);
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		return get_serial_info(port,
+				       (struct serial_struct __user *) arg);
+	case TIOCSSERIAL:
+		return set_serial_info(port,
+				       (struct serial_struct __user *) arg);
+	default:
+		break;
+	}
+
+	dbg("%s arg not supported", __func__);
+
+	return -ENOIOCTLCMD;
+}
+EXPORT_SYMBOL(usb_wwan_ioctl);
+
 /* Write */
 int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
 		   const unsigned char *buf, int count)
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 339fac3..23f0dd9 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -49,14 +49,17 @@
 	__u8 cdb[16];	/* XXX: Overflow-checking tools may misunderstand */
 };
 
+/*
+ * Also used for the Read Ready and Write Ready IUs since they have the
+ * same first four bytes
+ */
 struct sense_iu {
 	__u8 iu_id;
 	__u8 rsvd1;
 	__be16 tag;
 	__be16 status_qual;
 	__u8 status;
-	__u8 service_response;
-	__u8 rsvd8[6];
+	__u8 rsvd7[7];
 	__be16 len;
 	__u8 sense[SCSI_SENSE_BUFFERSIZE];
 };
@@ -97,8 +100,8 @@
 };
 
 enum {
-	ALLOC_SENSE_URB		= (1 << 0),
-	SUBMIT_SENSE_URB	= (1 << 1),
+	ALLOC_STATUS_URB	= (1 << 0),
+	SUBMIT_STATUS_URB	= (1 << 1),
 	ALLOC_DATA_IN_URB	= (1 << 2),
 	SUBMIT_DATA_IN_URB	= (1 << 3),
 	ALLOC_DATA_OUT_URB	= (1 << 4),
@@ -112,7 +115,7 @@
 	unsigned int state;
 	unsigned int stream;
 	struct urb *cmd_urb;
-	struct urb *sense_urb;
+	struct urb *status_urb;
 	struct urb *data_in_urb;
 	struct urb *data_out_urb;
 	struct list_head list;
@@ -138,7 +141,7 @@
 		struct scsi_pointer *scp = (void *)cmdinfo;
 		struct scsi_cmnd *cmnd = container_of(scp,
 							struct scsi_cmnd, SCp);
-		uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_KERNEL);
+		uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
 	}
 }
 
@@ -204,7 +207,7 @@
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 	int err;
 
-	cmdinfo->state = direction | SUBMIT_SENSE_URB;
+	cmdinfo->state = direction | SUBMIT_STATUS_URB;
 	err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
 	if (err) {
 		spin_lock(&uas_work_lock);
@@ -294,7 +297,7 @@
 	if (!urb)
 		goto out;
 
-	iu = kmalloc(sizeof(*iu), gfp);
+	iu = kzalloc(sizeof(*iu), gfp);
 	if (!iu)
 		goto free;
 
@@ -325,7 +328,7 @@
 	if (len < 0)
 		len = 0;
 	len = ALIGN(len, 4);
-	iu = kmalloc(sizeof(*iu) + len, gfp);
+	iu = kzalloc(sizeof(*iu) + len, gfp);
 	if (!iu)
 		goto free;
 
@@ -357,21 +360,21 @@
 {
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
-	if (cmdinfo->state & ALLOC_SENSE_URB) {
-		cmdinfo->sense_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
-							cmdinfo->stream);
-		if (!cmdinfo->sense_urb)
+	if (cmdinfo->state & ALLOC_STATUS_URB) {
+		cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
+							  cmdinfo->stream);
+		if (!cmdinfo->status_urb)
 			return SCSI_MLQUEUE_DEVICE_BUSY;
-		cmdinfo->state &= ~ALLOC_SENSE_URB;
+		cmdinfo->state &= ~ALLOC_STATUS_URB;
 	}
 
-	if (cmdinfo->state & SUBMIT_SENSE_URB) {
-		if (usb_submit_urb(cmdinfo->sense_urb, gfp)) {
+	if (cmdinfo->state & SUBMIT_STATUS_URB) {
+		if (usb_submit_urb(cmdinfo->status_urb, gfp)) {
 			scmd_printk(KERN_INFO, cmnd,
 					"sense urb submission failure\n");
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		}
-		cmdinfo->state &= ~SUBMIT_SENSE_URB;
+		cmdinfo->state &= ~SUBMIT_STATUS_URB;
 	}
 
 	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
@@ -440,7 +443,7 @@
 
 	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
-	if (!cmdinfo->sense_urb && sdev->current_cmnd)
+	if (!cmdinfo->status_urb && sdev->current_cmnd)
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 
 	if (blk_rq_tagged(cmnd->request)) {
@@ -452,7 +455,7 @@
 
 	cmnd->scsi_done = done;
 
-	cmdinfo->state = ALLOC_SENSE_URB | SUBMIT_SENSE_URB |
+	cmdinfo->state = ALLOC_STATUS_URB | SUBMIT_STATUS_URB |
 			ALLOC_CMD_URB | SUBMIT_CMD_URB;
 
 	switch (cmnd->sc_data_direction) {
@@ -475,8 +478,8 @@
 	err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
 	if (err) {
 		/* If we did nothing, give up now */
-		if (cmdinfo->state & SUBMIT_SENSE_URB) {
-			usb_free_urb(cmdinfo->sense_urb);
+		if (cmdinfo->state & SUBMIT_STATUS_URB) {
+			usb_free_urb(cmdinfo->status_urb);
 			return SCSI_MLQUEUE_DEVICE_BUSY;
 		}
 		spin_lock(&uas_work_lock);
@@ -578,6 +581,34 @@
 };
 MODULE_DEVICE_TABLE(usb, uas_usb_ids);
 
+static int uas_is_interface(struct usb_host_interface *intf)
+{
+	return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE &&
+		intf->desc.bInterfaceSubClass == USB_SC_SCSI &&
+		intf->desc.bInterfaceProtocol == USB_PR_UAS);
+}
+
+static int uas_switch_interface(struct usb_device *udev,
+						struct usb_interface *intf)
+{
+	int i;
+
+	if (uas_is_interface(intf->cur_altsetting))
+		return 0;
+
+	for (i = 0; i < intf->num_altsetting; i++) {
+		struct usb_host_interface *alt = &intf->altsetting[i];
+		if (alt == intf->cur_altsetting)
+			continue;
+		if (uas_is_interface(alt))
+			return usb_set_interface(udev,
+						alt->desc.bInterfaceNumber,
+						alt->desc.bAlternateSetting);
+	}
+
+	return -ENODEV;
+}
+
 static void uas_configure_endpoints(struct uas_dev_info *devinfo)
 {
 	struct usb_host_endpoint *eps[4] = { };
@@ -651,13 +682,8 @@
 	struct uas_dev_info *devinfo;
 	struct usb_device *udev = interface_to_usbdev(intf);
 
-	if (id->bInterfaceProtocol == 0x50) {
-		int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-/* XXX: Shouldn't assume that 1 is the alternative we want */
-		int ret = usb_set_interface(udev, ifnum, 1);
-		if (ret)
-			return -ENODEV;
-	}
+	if (uas_switch_interface(udev, intf))
+		return -ENODEV;
 
 	devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
 	if (!devinfo)
diff --git a/drivers/uwb/i1480/i1480-est.c b/drivers/uwb/i1480/i1480-est.c
index f2eb4d8..d5de5e1 100644
--- a/drivers/uwb/i1480/i1480-est.c
+++ b/drivers/uwb/i1480/i1480-est.c
@@ -91,7 +91,7 @@
  *
  * [so we are loaded when this kind device is connected]
  */
-static struct usb_device_id i1480_est_id_table[] = {
+static struct usb_device_id __used i1480_est_id_table[] = {
 	{ USB_DEVICE(0x8086, 0xdf3b), },
 	{ USB_DEVICE(0x8086, 0x0c3b), },
 	{ },
diff --git a/drivers/uwb/umc-dev.c b/drivers/uwb/umc-dev.c
index 43ea998..ccd2184 100644
--- a/drivers/uwb/umc-dev.c
+++ b/drivers/uwb/umc-dev.c
@@ -54,11 +54,8 @@
 
 	err = request_resource(umc->resource.parent, &umc->resource);
 	if (err < 0) {
-		dev_err(&umc->dev, "can't allocate resource range "
-			"%016Lx to %016Lx: %d\n",
-			(unsigned long long)umc->resource.start,
-			(unsigned long long)umc->resource.end,
-			err);
+		dev_err(&umc->dev, "can't allocate resource range %pR: %d\n",
+			&umc->resource, err);
 		goto error_request_resource;
 	}
 
diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c
index 7349558..70a004a 100644
--- a/drivers/uwb/whc-rc.c
+++ b/drivers/uwb/whc-rc.c
@@ -449,7 +449,7 @@
 }
 
 /* PCI device ID's that we handle [so it gets loaded] */
-static struct pci_device_id whcrc_id_table[] = {
+static struct pci_device_id __used whcrc_id_table[] = {
 	{ PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) },
 	{ /* empty last entry */ }
 };
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 27c1fb4..55dc6fb 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -186,6 +186,14 @@
        depends on FB
        default n
 
+config FB_WMT_GE_ROPS
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include functions for accelerated rectangle filling and area
+	  copying using WonderMedia Graphics Engine operations.
+
 config FB_DEFERRED_IO
 	bool
 	depends on FB
@@ -635,6 +643,72 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called bfin-lq035q1-fb.
 
+config FB_BF537_LQ035
+	tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
+	depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select BFIN_GPTIMERS
+	help
+	  This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
+	  attached to a BF537.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bf537-lq035.
+
+config FB_BFIN_7393
+	tristate "Blackfin ADV7393 Video encoder"
+	depends on FB && BLACKFIN
+	select I2C
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the framebuffer device for a ADV7393 video encoder
+	  attached to a Blackfin on the PPI port.
+	  If your Blackfin board has a ADV7393 select Y.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bfin_adv7393fb.
+
+choice
+	prompt  "Video mode support"
+	depends on FB_BFIN_7393
+	default NTSC
+
+config NTSC
+	bool 'NTSC 720x480'
+
+config PAL
+	bool 'PAL 720x576'
+
+config NTSC_640x480
+	bool 'NTSC 640x480 (Experimental)'
+
+config PAL_640x480
+	bool 'PAL 640x480 (Experimental)'
+
+config NTSC_YCBCR
+	bool 'NTSC 720x480 YCbCR input'
+
+config PAL_YCBCR
+	bool 'PAL 720x576 YCbCR input'
+
+endchoice
+
+choice
+	prompt  "Size of ADV7393 frame buffer memory Single/Double Size"
+	depends on (FB_BFIN_7393)
+	default ADV7393_1XMEM
+
+config ADV7393_1XMEM
+	bool 'Single'
+
+config ADV7393_2XMEM
+	bool 'Double'
+endchoice
+
 config FB_STI
 	tristate "HP STI frame buffer device support"
 	depends on FB && PARISC
@@ -750,24 +824,14 @@
 config FB_HGA
 	tristate "Hercules mono graphics support"
 	depends on FB && X86
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
 	help
 	  Say Y here if you have a Hercules mono graphics card.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called hgafb.
 
-	  As this card technology is 15 years old, most people will answer N
-	  here.
-
-config FB_HGA_ACCEL
-	bool "Hercules mono Acceleration functions (EXPERIMENTAL)"
-	depends on FB_HGA && EXPERIMENTAL
-	---help---
-	This will compile the Hercules mono graphics with
-	acceleration functions.
+	  As this card technology is at least 25 years old,
+	  most people will answer N here.
 
 config FB_SGIVW
 	tristate "SGI Visual Workstation framebuffer support"
@@ -1722,6 +1786,24 @@
 	  various panels and CRTs by passing in kernel cmd line option
 	  au1200fb:panel=<name>.
 
+config FB_VT8500
+	bool "VT8500 LCD Driver"
+	depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_VT8500
+	select FB_WMT_GE_ROPS
+	select FB_SYS_IMAGEBLIT
+	help
+	  This is the framebuffer driver for VIA VT8500 integrated LCD
+	  controller.
+
+config FB_WM8505
+	bool "WM8505 frame buffer support"
+	depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_WM8505
+	select FB_WMT_GE_ROPS
+	select FB_SYS_IMAGEBLIT
+	help
+	  This is the framebuffer driver for WonderMedia WM8505
+	  integrated LCD controller.
+
 source "drivers/video/geode/Kconfig"
 
 config FB_HIT
@@ -1850,6 +1932,16 @@
 
 	  <file:Documentation/fb/pxafb.txt> describes the available parameters.
 
+config PXA3XX_GCU
+	tristate "PXA3xx 2D graphics accelerator driver"
+	depends on FB_PXA
+	help
+	  Kernelspace driver for the 2D graphics controller unit (GCU)
+	  found on PXA3xx processors. There is a counterpart driver in the
+	  DirectFB suite, see http://www.directfb.org/
+
+	  If you compile this as a module, it will be called pxa3xx_gcu.
+
 config FB_MBX
 	tristate "2700G LCD framebuffer support"
 	depends on FB && ARCH_PXA
@@ -2034,6 +2126,20 @@
 
 	  If unsure, say N.
 
+config FB_UDL
+	tristate "Displaylink USB Framebuffer support"
+	depends on FB && USB
+	select FB_MODE_HELPERS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	---help---
+	  This is a kernel framebuffer driver for DisplayLink USB devices.
+	  Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
+	  mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
+	  To compile as a module, choose M here: the module name is udlfb.
 
 config FB_PNX4008_DUM
 	tristate "Display Update Module support on Philips PNX4008 board"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 485e8ed..8c8fabd 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -26,6 +26,7 @@
 obj-$(CONFIG_FB_MACMODES)      += macmodes.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
 obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
+obj-$(CONFIG_FB_WMT_GE_ROPS)   += wmt_ge_rops.o
 
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
@@ -100,10 +101,13 @@
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
 obj-$(CONFIG_FB_PXA)		  += pxafb.o
 obj-$(CONFIG_FB_PXA168)		  += pxa168fb.o
+obj-$(CONFIG_PXA3XX_GCU)	  += pxa3xx-gcu.o
 obj-$(CONFIG_FB_W100)		  += w100fb.o
 obj-$(CONFIG_FB_TMIO)		  += tmiofb.o
 obj-$(CONFIG_FB_AU1100)		  += au1100fb.o
 obj-$(CONFIG_FB_AU1200)		  += au1200fb.o
+obj-$(CONFIG_FB_VT8500)		  += vt8500lcdfb.o
+obj-$(CONFIG_FB_WM8505)		  += wm8505fb.o
 obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o
 obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o
 obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o
@@ -122,6 +126,7 @@
 obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
 obj-$(CONFIG_FB_PS3)		  += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
+obj-$(CONFIG_FB_UDL)		  += udlfb.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
 obj-$(CONFIG_SH_MIPI_DSI)	  += sh_mipi_dsi.o
 obj-$(CONFIG_FB_SH_MOBILE_HDMI)	  += sh_mobile_hdmi.o
@@ -141,9 +146,11 @@
 obj-$(CONFIG_FB_EFI)              += efifb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_OF)               += offb.o
+obj-$(CONFIG_FB_BF537_LQ035)      += bf537-lq035.o
 obj-$(CONFIG_FB_BF54X_LQ043)	  += bf54x-lq043fb.o
 obj-$(CONFIG_FB_BFIN_LQ035Q1)     += bfin-lq035q1-fb.o
 obj-$(CONFIG_FB_BFIN_T350MCQB)	  += bfin-t350mcqb-fb.o
+obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
 obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
 
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 5bf9123..5a3ce3a 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2969,10 +2969,8 @@
 {
 	struct atyfb_par *par = info->par;
 	struct device_node *dp;
-	char prop[128];
-	phandle node;
-	int len, i, j, ret;
 	u32 mem, chip_id;
+	int i, j, ret;
 
 	/*
 	 * Map memory-mapped registers.
@@ -3088,23 +3086,8 @@
 		aty_st_le32(MEM_CNTL, mem, par);
 	}
 
-	/*
-	 * If this is the console device, we will set default video
-	 * settings to what the PROM left us with.
-	 */
-	node = prom_getchild(prom_root_node);
-	node = prom_searchsiblings(node, "aliases");
-	if (node) {
-		len = prom_getproperty(node, "screen", prop, sizeof(prop));
-		if (len > 0) {
-			prop[len] = '\0';
-			node = prom_finddevice(prop);
-		} else
-			node = 0;
-	}
-
 	dp = pci_device_to_OF_node(pdev);
-	if (node == dp->phandle) {
+	if (dp == of_console_device) {
 		struct fb_var_screeninfo *var = &default_var;
 		unsigned int N, P, Q, M, T, R;
 		u32 v_total, h_total;
@@ -3112,9 +3095,9 @@
 		u8 pll_regs[16];
 		u8 clock_cntl;
 
-		crtc.vxres = prom_getintdefault(node, "width", 1024);
-		crtc.vyres = prom_getintdefault(node, "height", 768);
-		var->bits_per_pixel = prom_getintdefault(node, "depth", 8);
+		crtc.vxres = of_getintprop_default(dp, "width", 1024);
+		crtc.vyres = of_getintprop_default(dp, "height", 768);
+		var->bits_per_pixel = of_getintprop_default(dp, "depth", 8);
 		var->xoffset = var->yoffset = 0;
 		crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
 		crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
new file mode 100644
index 0000000..18c5078
--- /dev/null
+++ b/drivers/video/bf537-lq035.c
@@ -0,0 +1,914 @@
+/*
+ * Analog Devices Blackfin(BF537 STAMP) + SHARP TFT LCD.
+ * http://docs.blackfin.uclinux.org/doku.php?id=hw:cards:tft-lcd
+ *
+ * Copyright 2006-2010 Analog Devices Inc.
+ * Licensed under the GPL-2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/i2c.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dpmc.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define NO_BL 1
+
+#define MAX_BRIGHENESS	95
+#define MIN_BRIGHENESS	5
+#define NBR_PALETTE	256
+
+static const unsigned short ppi_pins[] = {
+	P_PPI0_CLK, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 0
+};
+
+static unsigned char *fb_buffer;          /* RGB Buffer */
+static unsigned long *dma_desc_table;
+static int t_conf_done, lq035_open_cnt;
+static DEFINE_SPINLOCK(bfin_lq035_lock);
+
+static int landscape;
+module_param(landscape, int, 0);
+MODULE_PARM_DESC(landscape,
+	"LANDSCAPE use 320x240 instead of Native 240x320 Resolution");
+
+static int bgr;
+module_param(bgr, int, 0);
+MODULE_PARM_DESC(bgr,
+	"BGR use 16-bit BGR-565 instead of RGB-565");
+
+static int nocursor = 1;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+static unsigned long current_brightness;  /* backlight */
+
+/* AD5280 vcomm */
+static unsigned char vcomm_value = 150;
+static struct i2c_client *ad5280_client;
+
+static void set_vcomm(void)
+{
+	int nr;
+
+	if (!ad5280_client)
+		return;
+
+	nr = i2c_smbus_write_byte_data(ad5280_client, 0x00, vcomm_value);
+	if (nr)
+		pr_err("i2c_smbus_write_byte_data fail: %d\n", nr);
+}
+
+static int __devinit ad5280_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	int ret;
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+		return -EIO;
+	}
+
+	ret = i2c_smbus_write_byte_data(client, 0x00, vcomm_value);
+	if (ret) {
+		dev_err(&client->dev, "write fail: %d\n", ret);
+		return ret;
+	}
+
+	ad5280_client = client;
+
+	return 0;
+}
+
+static int __devexit ad5280_remove(struct i2c_client *client)
+{
+	ad5280_client = NULL;
+	return 0;
+}
+
+static const struct i2c_device_id ad5280_id[] = {
+	{"bf537-lq035-ad5280", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad5280_id);
+
+static struct i2c_driver ad5280_driver = {
+	.driver = {
+		.name = "bf537-lq035-ad5280",
+	},
+	.probe = ad5280_probe,
+	.remove = __devexit_p(ad5280_remove),
+	.id_table = ad5280_id,
+};
+
+#ifdef CONFIG_PNAV10
+#define MOD GPIO_PH13
+
+#define bfin_write_TIMER_LP_CONFIG	bfin_write_TIMER0_CONFIG
+#define bfin_write_TIMER_LP_WIDTH	bfin_write_TIMER0_WIDTH
+#define bfin_write_TIMER_LP_PERIOD	bfin_write_TIMER0_PERIOD
+#define bfin_read_TIMER_LP_COUNTER	bfin_read_TIMER0_COUNTER
+#define TIMDIS_LP			TIMDIS0
+#define TIMEN_LP			TIMEN0
+
+#define bfin_write_TIMER_SPS_CONFIG	bfin_write_TIMER1_CONFIG
+#define bfin_write_TIMER_SPS_WIDTH	bfin_write_TIMER1_WIDTH
+#define bfin_write_TIMER_SPS_PERIOD	bfin_write_TIMER1_PERIOD
+#define TIMDIS_SPS			TIMDIS1
+#define TIMEN_SPS			TIMEN1
+
+#define bfin_write_TIMER_SP_CONFIG	bfin_write_TIMER5_CONFIG
+#define bfin_write_TIMER_SP_WIDTH	bfin_write_TIMER5_WIDTH
+#define bfin_write_TIMER_SP_PERIOD	bfin_write_TIMER5_PERIOD
+#define TIMDIS_SP			TIMDIS5
+#define TIMEN_SP			TIMEN5
+
+#define bfin_write_TIMER_PS_CLS_CONFIG	bfin_write_TIMER2_CONFIG
+#define bfin_write_TIMER_PS_CLS_WIDTH	bfin_write_TIMER2_WIDTH
+#define bfin_write_TIMER_PS_CLS_PERIOD	bfin_write_TIMER2_PERIOD
+#define TIMDIS_PS_CLS			TIMDIS2
+#define TIMEN_PS_CLS			TIMEN2
+
+#define bfin_write_TIMER_REV_CONFIG	bfin_write_TIMER3_CONFIG
+#define bfin_write_TIMER_REV_WIDTH	bfin_write_TIMER3_WIDTH
+#define bfin_write_TIMER_REV_PERIOD	bfin_write_TIMER3_PERIOD
+#define TIMDIS_REV			TIMDIS3
+#define TIMEN_REV			TIMEN3
+#define bfin_read_TIMER_REV_COUNTER	bfin_read_TIMER3_COUNTER
+
+#define	FREQ_PPI_CLK         (5*1024*1024)  /* PPI_CLK 5MHz */
+
+#define TIMERS {P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR5, 0}
+
+#else
+
+#define UD      GPIO_PF13	/* Up / Down */
+#define MOD     GPIO_PF10
+#define LBR     GPIO_PF14	/* Left Right */
+
+#define bfin_write_TIMER_LP_CONFIG	bfin_write_TIMER6_CONFIG
+#define bfin_write_TIMER_LP_WIDTH	bfin_write_TIMER6_WIDTH
+#define bfin_write_TIMER_LP_PERIOD	bfin_write_TIMER6_PERIOD
+#define bfin_read_TIMER_LP_COUNTER	bfin_read_TIMER6_COUNTER
+#define TIMDIS_LP			TIMDIS6
+#define TIMEN_LP			TIMEN6
+
+#define bfin_write_TIMER_SPS_CONFIG	bfin_write_TIMER1_CONFIG
+#define bfin_write_TIMER_SPS_WIDTH	bfin_write_TIMER1_WIDTH
+#define bfin_write_TIMER_SPS_PERIOD	bfin_write_TIMER1_PERIOD
+#define TIMDIS_SPS			TIMDIS1
+#define TIMEN_SPS			TIMEN1
+
+#define bfin_write_TIMER_SP_CONFIG	bfin_write_TIMER0_CONFIG
+#define bfin_write_TIMER_SP_WIDTH	bfin_write_TIMER0_WIDTH
+#define bfin_write_TIMER_SP_PERIOD	bfin_write_TIMER0_PERIOD
+#define TIMDIS_SP			TIMDIS0
+#define TIMEN_SP			TIMEN0
+
+#define bfin_write_TIMER_PS_CLS_CONFIG	bfin_write_TIMER7_CONFIG
+#define bfin_write_TIMER_PS_CLS_WIDTH	bfin_write_TIMER7_WIDTH
+#define bfin_write_TIMER_PS_CLS_PERIOD	bfin_write_TIMER7_PERIOD
+#define TIMDIS_PS_CLS			TIMDIS7
+#define TIMEN_PS_CLS			TIMEN7
+
+#define bfin_write_TIMER_REV_CONFIG	bfin_write_TIMER5_CONFIG
+#define bfin_write_TIMER_REV_WIDTH	bfin_write_TIMER5_WIDTH
+#define bfin_write_TIMER_REV_PERIOD	bfin_write_TIMER5_PERIOD
+#define TIMDIS_REV			TIMDIS5
+#define TIMEN_REV			TIMEN5
+#define bfin_read_TIMER_REV_COUNTER	bfin_read_TIMER5_COUNTER
+
+#define	FREQ_PPI_CLK         (6*1000*1000)  /* PPI_CLK 6MHz */
+#define TIMERS {P_TMR0, P_TMR1, P_TMR5, P_TMR6, P_TMR7, 0}
+
+#endif
+
+#define LCD_X_RES			240 /* Horizontal Resolution */
+#define LCD_Y_RES			320 /* Vertical Resolution */
+
+#define LCD_BBP				16  /* Bit Per Pixel */
+
+/* the LCD and the DMA start counting differently;
+ * since one starts at 0 and the other starts at 1,
+ * we have a difference of 1 between START_LINES
+ * and U_LINES.
+ */
+#define START_LINES       8   /* lines for field flyback or field blanking signal */
+#define U_LINES           9   /* number of undisplayed blanking lines */
+
+#define FRAMES_PER_SEC    (60)
+
+#define DCLKS_PER_FRAME   (FREQ_PPI_CLK/FRAMES_PER_SEC)
+#define DCLKS_PER_LINE    (DCLKS_PER_FRAME/(LCD_Y_RES+U_LINES))
+
+#define PPI_CONFIG_VALUE  (PORT_DIR|XFR_TYPE|DLEN_16|POLS)
+#define PPI_DELAY_VALUE   (0)
+#define TIMER_CONFIG      (PWM_OUT|PERIOD_CNT|TIN_SEL|CLK_SEL)
+
+#define ACTIVE_VIDEO_MEM_OFFSET	(LCD_X_RES*START_LINES*(LCD_BBP/8))
+#define ACTIVE_VIDEO_MEM_SIZE	(LCD_Y_RES*LCD_X_RES*(LCD_BBP/8))
+#define TOTAL_VIDEO_MEM_SIZE	((LCD_Y_RES+U_LINES)*LCD_X_RES*(LCD_BBP/8))
+#define TOTAL_DMA_DESC_SIZE	(2 * sizeof(u32) * (LCD_Y_RES + U_LINES))
+
+static void start_timers(void) /* CHECK with HW */
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	bfin_write_TIMER_ENABLE(TIMEN_REV);
+	SSYNC();
+
+	while (bfin_read_TIMER_REV_COUNTER() <= 11)
+		continue;
+	bfin_write_TIMER_ENABLE(TIMEN_LP);
+	SSYNC();
+
+	while (bfin_read_TIMER_LP_COUNTER() < 3)
+		continue;
+	bfin_write_TIMER_ENABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS);
+	SSYNC();
+	t_conf_done = 1;
+	local_irq_restore(flags);
+}
+
+static void config_timers(void)
+{
+	/* Stop timers */
+	bfin_write_TIMER_DISABLE(TIMDIS_SP|TIMDIS_SPS|TIMDIS_REV|
+				 TIMDIS_LP|TIMDIS_PS_CLS);
+	SSYNC();
+
+	/* LP, timer 6 */
+	bfin_write_TIMER_LP_CONFIG(TIMER_CONFIG|PULSE_HI);
+	bfin_write_TIMER_LP_WIDTH(1);
+
+	bfin_write_TIMER_LP_PERIOD(DCLKS_PER_LINE);
+	SSYNC();
+
+	/* SPS, timer 1 */
+	bfin_write_TIMER_SPS_CONFIG(TIMER_CONFIG|PULSE_HI);
+	bfin_write_TIMER_SPS_WIDTH(DCLKS_PER_LINE*2);
+	bfin_write_TIMER_SPS_PERIOD((DCLKS_PER_LINE * (LCD_Y_RES+U_LINES)));
+	SSYNC();
+
+	/* SP, timer 0 */
+	bfin_write_TIMER_SP_CONFIG(TIMER_CONFIG|PULSE_HI);
+	bfin_write_TIMER_SP_WIDTH(1);
+	bfin_write_TIMER_SP_PERIOD(DCLKS_PER_LINE);
+	SSYNC();
+
+	/* PS & CLS, timer 7 */
+	bfin_write_TIMER_PS_CLS_CONFIG(TIMER_CONFIG);
+	bfin_write_TIMER_PS_CLS_WIDTH(LCD_X_RES + START_LINES);
+	bfin_write_TIMER_PS_CLS_PERIOD(DCLKS_PER_LINE);
+
+	SSYNC();
+
+#ifdef NO_BL
+	/* REV, timer 5 */
+	bfin_write_TIMER_REV_CONFIG(TIMER_CONFIG|PULSE_HI);
+
+	bfin_write_TIMER_REV_WIDTH(DCLKS_PER_LINE);
+	bfin_write_TIMER_REV_PERIOD(DCLKS_PER_LINE*2);
+
+	SSYNC();
+#endif
+}
+
+static void config_ppi(void)
+{
+	bfin_write_PPI_DELAY(PPI_DELAY_VALUE);
+	bfin_write_PPI_COUNT(LCD_X_RES-1);
+	/* 0x10 -> PORT_CFG -> 2 or 3 frame syncs */
+	bfin_write_PPI_CONTROL((PPI_CONFIG_VALUE|0x10) & (~POLS));
+}
+
+static int config_dma(void)
+{
+	u32 i;
+
+	if (landscape) {
+
+		for (i = 0; i < U_LINES; ++i) {
+			/* blanking lines point to first line of fb_buffer */
+			dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
+			dma_desc_table[2*i+1] = (unsigned long)fb_buffer;
+		}
+
+		for (i = U_LINES; i < U_LINES + LCD_Y_RES; ++i) {
+			/* visible lines */
+			dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
+			dma_desc_table[2*i+1] = (unsigned long)fb_buffer +
+						(LCD_Y_RES+U_LINES-1-i)*2;
+		}
+
+		/* last descriptor points to first */
+		dma_desc_table[2*(LCD_Y_RES+U_LINES-1)] = (unsigned long)&dma_desc_table[0];
+
+		set_dma_x_count(CH_PPI, LCD_X_RES);
+		set_dma_x_modify(CH_PPI, LCD_Y_RES * (LCD_BBP / 8));
+		set_dma_y_count(CH_PPI, 0);
+		set_dma_y_modify(CH_PPI, 0);
+		set_dma_next_desc_addr(CH_PPI, (void *)dma_desc_table[0]);
+		set_dma_config(CH_PPI, DMAFLOW_LARGE | NDSIZE_4 | WDSIZE_16);
+
+	} else {
+
+		set_dma_config(CH_PPI, set_bfin_dma_config(DIR_READ,
+				DMA_FLOW_AUTO,
+				INTR_DISABLE,
+				DIMENSION_2D,
+				DATA_SIZE_16,
+				DMA_NOSYNC_KEEP_DMA_BUF));
+		set_dma_x_count(CH_PPI, LCD_X_RES);
+		set_dma_x_modify(CH_PPI, LCD_BBP / 8);
+		set_dma_y_count(CH_PPI, LCD_Y_RES+U_LINES);
+		set_dma_y_modify(CH_PPI, LCD_BBP / 8);
+		set_dma_start_addr(CH_PPI, (unsigned long) fb_buffer);
+	}
+
+	return 0;
+}
+
+static int __devinit request_ports(void)
+{
+	u16 tmr_req[] = TIMERS;
+
+	/*
+		UD:      PF13
+		MOD:     PF10
+		LBR:     PF14
+		PPI_CLK: PF15
+	*/
+
+	if (peripheral_request_list(ppi_pins, KBUILD_MODNAME)) {
+		pr_err("requesting PPI peripheral failed\n");
+		return -EBUSY;
+	}
+
+	if (peripheral_request_list(tmr_req, KBUILD_MODNAME)) {
+		peripheral_free_list(ppi_pins);
+		pr_err("requesting timer peripheral failed\n");
+		return -EBUSY;
+	}
+
+#if (defined(UD) && defined(LBR))
+	if (gpio_request(UD, KBUILD_MODNAME)) {
+		pr_err("requesting GPIO %d failed\n", UD);
+		return -EBUSY;
+	}
+
+	if (gpio_request(LBR, KBUILD_MODNAME)) {
+		pr_err("requesting GPIO %d failed\n", LBR);
+		gpio_free(UD);
+		return -EBUSY;
+	}
+
+	gpio_direction_output(UD, 0);
+	gpio_direction_output(LBR, 1);
+
+#endif
+
+	if (gpio_request(MOD, KBUILD_MODNAME)) {
+		pr_err("requesting GPIO %d failed\n", MOD);
+#if (defined(UD) && defined(LBR))
+		gpio_free(LBR);
+		gpio_free(UD);
+#endif
+		return -EBUSY;
+	}
+
+	gpio_direction_output(MOD, 1);
+
+	SSYNC();
+	return 0;
+}
+
+static void free_ports(void)
+{
+	u16 tmr_req[] = TIMERS;
+
+	peripheral_free_list(ppi_pins);
+	peripheral_free_list(tmr_req);
+
+#if defined(UD) && defined(LBR)
+	gpio_free(LBR);
+	gpio_free(UD);
+#endif
+	gpio_free(MOD);
+}
+
+static struct fb_info bfin_lq035_fb;
+
+static struct fb_var_screeninfo bfin_lq035_fb_defined = {
+	.bits_per_pixel		= LCD_BBP,
+	.activate		= FB_ACTIVATE_TEST,
+	.xres			= LCD_X_RES,	/*default portrait mode RGB*/
+	.yres			= LCD_Y_RES,
+	.xres_virtual		= LCD_X_RES,
+	.yres_virtual		= LCD_Y_RES,
+	.height			= -1,
+	.width			= -1,
+	.left_margin		= 0,
+	.right_margin		= 0,
+	.upper_margin		= 0,
+	.lower_margin		= 0,
+	.red			= {11, 5, 0},
+	.green			= {5, 6, 0},
+	.blue			= {0, 5, 0},
+	.transp		= {0, 0, 0},
+};
+
+static struct fb_fix_screeninfo bfin_lq035_fb_fix __devinitdata = {
+	.id		= KBUILD_MODNAME,
+	.smem_len	= ACTIVE_VIDEO_MEM_SIZE,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.line_length	= LCD_X_RES*(LCD_BBP/8),
+	.accel		= FB_ACCEL_NONE,
+};
+
+
+static int bfin_lq035_fb_open(struct fb_info *info, int user)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bfin_lq035_lock, flags);
+	lq035_open_cnt++;
+	spin_unlock_irqrestore(&bfin_lq035_lock, flags);
+
+	if (lq035_open_cnt <= 1) {
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+
+		set_vcomm();
+		config_dma();
+		config_ppi();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		SSYNC();
+		bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+		SSYNC();
+
+		if (!t_conf_done) {
+			config_timers();
+			start_timers();
+		}
+		/* gpio_set_value(MOD,1); */
+	}
+
+	return 0;
+}
+
+static int bfin_lq035_fb_release(struct fb_info *info, int user)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bfin_lq035_lock, flags);
+	lq035_open_cnt--;
+	spin_unlock_irqrestore(&bfin_lq035_lock, flags);
+
+
+	if (lq035_open_cnt <= 0) {
+
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+
+		disable_dma(CH_PPI);
+	}
+
+	return 0;
+}
+
+
+static int bfin_lq035_fb_check_var(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
+{
+	switch (var->bits_per_pixel) {
+	case 16:/* DIRECTCOLOUR, 64k */
+		var->red.offset = info->var.red.offset;
+		var->green.offset = info->var.green.offset;
+		var->blue.offset = info->var.blue.offset;
+		var->red.length = info->var.red.length;
+		var->green.length = info->var.green.length;
+		var->blue.length = info->var.blue.length;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		break;
+	default:
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres ||
+	    info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u\n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/* fb_rotate
+ * Rotate the display of this angle. This doesn't seems to be used by the core,
+ * but as our hardware supports it, so why not implementing it...
+ */
+static void bfin_lq035_fb_rotate(struct fb_info *fbi, int angle)
+{
+	pr_debug("%s: %p %d", __func__, fbi, angle);
+#if (defined(UD) && defined(LBR))
+	switch (angle) {
+
+	case 180:
+		gpio_set_value(LBR, 0);
+		gpio_set_value(UD, 1);
+		break;
+	default:
+		gpio_set_value(LBR, 1);
+		gpio_set_value(UD, 0);
+		break;
+	}
+#endif
+}
+
+static int bfin_lq035_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_lq035_fb_setcolreg(u_int regno, u_int red, u_int green,
+				   u_int blue, u_int transp,
+				   struct fb_info *info)
+{
+	if (regno >= NBR_PALETTE)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red   >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue  >>= (16 - info->var.blue.length);
+
+		value = (red   << info->var.red.offset) |
+			(green << info->var.green.offset)|
+			(blue  << info->var.blue.offset);
+		value &= 0xFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+
+	}
+
+	return 0;
+}
+
+static struct fb_ops bfin_lq035_fb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_open		= bfin_lq035_fb_open,
+	.fb_release		= bfin_lq035_fb_release,
+	.fb_check_var		= bfin_lq035_fb_check_var,
+	.fb_rotate		= bfin_lq035_fb_rotate,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_cursor		= bfin_lq035_fb_cursor,
+	.fb_setcolreg		= bfin_lq035_fb_setcolreg,
+};
+
+static int bl_get_brightness(struct backlight_device *bd)
+{
+	return current_brightness;
+}
+
+static const struct backlight_ops bfin_lq035fb_bl_ops = {
+	.get_brightness	= bl_get_brightness,
+};
+
+static struct backlight_device *bl_dev;
+
+static int bfin_lcd_get_power(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_power(struct lcd_device *dev, int power)
+{
+	return 0;
+}
+
+static int bfin_lcd_get_contrast(struct lcd_device *dev)
+{
+	return (int)vcomm_value;
+}
+
+static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
+{
+	if (contrast > 255)
+		contrast = 255;
+	if (contrast < 0)
+		contrast = 0;
+
+	vcomm_value = (unsigned char)contrast;
+	set_vcomm();
+	return 0;
+}
+
+static int bfin_lcd_check_fb(struct lcd_device *lcd, struct fb_info *fi)
+{
+	if (!fi || (fi == &bfin_lq035_fb))
+		return 1;
+	return 0;
+}
+
+static struct lcd_ops bfin_lcd_ops = {
+	.get_power	= bfin_lcd_get_power,
+	.set_power	= bfin_lcd_set_power,
+	.get_contrast	= bfin_lcd_get_contrast,
+	.set_contrast	= bfin_lcd_set_contrast,
+	.check_fb	= bfin_lcd_check_fb,
+};
+
+static struct lcd_device *lcd_dev;
+
+static int __devinit bfin_lq035_probe(struct platform_device *pdev)
+{
+	struct backlight_properties props;
+	dma_addr_t dma_handle;
+
+	if (request_dma(CH_PPI, KBUILD_MODNAME)) {
+		pr_err("couldn't request PPI DMA\n");
+		return -EFAULT;
+	}
+
+	if (request_ports()) {
+		pr_err("couldn't request gpio port\n");
+		free_dma(CH_PPI);
+		return -EFAULT;
+	}
+
+	fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE,
+				       &dma_handle, GFP_KERNEL);
+	if (fb_buffer == NULL) {
+		pr_err("couldn't allocate dma buffer\n");
+		free_dma(CH_PPI);
+		free_ports();
+		return -ENOMEM;
+	}
+
+	if (L1_DATA_A_LENGTH)
+		dma_desc_table = l1_data_sram_zalloc(TOTAL_DMA_DESC_SIZE);
+	else
+		dma_desc_table = dma_alloc_coherent(NULL, TOTAL_DMA_DESC_SIZE,
+						    &dma_handle, 0);
+
+	if (dma_desc_table == NULL) {
+		pr_err("couldn't allocate dma descriptor\n");
+		free_dma(CH_PPI);
+		free_ports();
+		dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+		return -ENOMEM;
+	}
+
+	bfin_lq035_fb.screen_base = (void *)fb_buffer;
+	bfin_lq035_fb_fix.smem_start = (int)fb_buffer;
+	if (landscape) {
+		bfin_lq035_fb_defined.xres = LCD_Y_RES;
+		bfin_lq035_fb_defined.yres = LCD_X_RES;
+		bfin_lq035_fb_defined.xres_virtual = LCD_Y_RES;
+		bfin_lq035_fb_defined.yres_virtual = LCD_X_RES;
+
+		bfin_lq035_fb_fix.line_length = LCD_Y_RES*(LCD_BBP/8);
+	} else {
+		bfin_lq035_fb.screen_base += ACTIVE_VIDEO_MEM_OFFSET;
+		bfin_lq035_fb_fix.smem_start += ACTIVE_VIDEO_MEM_OFFSET;
+	}
+
+	bfin_lq035_fb_defined.green.msb_right = 0;
+	bfin_lq035_fb_defined.red.msb_right   = 0;
+	bfin_lq035_fb_defined.blue.msb_right  = 0;
+	bfin_lq035_fb_defined.green.offset    = 5;
+	bfin_lq035_fb_defined.green.length    = 6;
+	bfin_lq035_fb_defined.red.length      = 5;
+	bfin_lq035_fb_defined.blue.length     = 5;
+
+	if (bgr) {
+		bfin_lq035_fb_defined.red.offset  = 0;
+		bfin_lq035_fb_defined.blue.offset = 11;
+	} else {
+		bfin_lq035_fb_defined.red.offset  = 11;
+		bfin_lq035_fb_defined.blue.offset = 0;
+	}
+
+	bfin_lq035_fb.fbops = &bfin_lq035_fb_ops;
+	bfin_lq035_fb.var = bfin_lq035_fb_defined;
+
+	bfin_lq035_fb.fix = bfin_lq035_fb_fix;
+	bfin_lq035_fb.flags = FBINFO_DEFAULT;
+
+
+	bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
+	if (bfin_lq035_fb.pseudo_palette == NULL) {
+		pr_err("failed to allocate pseudo_palette\n");
+		free_dma(CH_PPI);
+		free_ports();
+		dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+		return -ENOMEM;
+	}
+
+	if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
+		pr_err("failed to allocate colormap (%d entries)\n",
+			NBR_PALETTE);
+		free_dma(CH_PPI);
+		free_ports();
+		dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+		kfree(bfin_lq035_fb.pseudo_palette);
+		return -EFAULT;
+	}
+
+	if (register_framebuffer(&bfin_lq035_fb) < 0) {
+		pr_err("unable to register framebuffer\n");
+		free_dma(CH_PPI);
+		free_ports();
+		dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+		fb_buffer = NULL;
+		kfree(bfin_lq035_fb.pseudo_palette);
+		fb_dealloc_cmap(&bfin_lq035_fb.cmap);
+		return -EINVAL;
+	}
+
+	i2c_add_driver(&ad5280_driver);
+
+	memset(&props, 0, sizeof(props));
+	props.max_brightness = MAX_BRIGHENESS;
+	bl_dev = backlight_device_register("bf537-bl", NULL, NULL,
+					   &bfin_lq035fb_bl_ops, &props);
+
+	lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL,
+				      &bfin_lcd_ops);
+	lcd_dev->props.max_contrast = 255,
+
+	pr_info("initialized");
+
+	return 0;
+}
+
+static int __devexit bfin_lq035_remove(struct platform_device *pdev)
+{
+	if (fb_buffer != NULL)
+		dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
+
+	if (L1_DATA_A_LENGTH)
+		l1_data_sram_free(dma_desc_table);
+	else
+		dma_free_coherent(NULL, TOTAL_DMA_DESC_SIZE, NULL, 0);
+
+	bfin_write_TIMER_DISABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS|
+				 TIMEN_LP|TIMEN_REV);
+	t_conf_done = 0;
+
+	free_dma(CH_PPI);
+
+
+	kfree(bfin_lq035_fb.pseudo_palette);
+	fb_dealloc_cmap(&bfin_lq035_fb.cmap);
+
+
+	lcd_device_unregister(lcd_dev);
+	backlight_device_unregister(bl_dev);
+
+	unregister_framebuffer(&bfin_lq035_fb);
+	i2c_del_driver(&ad5280_driver);
+
+	free_ports();
+
+	pr_info("unregistered LCD driver\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_lq035_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (lq035_open_cnt > 0) {
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+		disable_dma(CH_PPI);
+	}
+
+	return 0;
+}
+
+static int bfin_lq035_resume(struct platform_device *pdev)
+{
+	if (lq035_open_cnt > 0) {
+		bfin_write_PPI_CONTROL(0);
+		SSYNC();
+
+		config_dma();
+		config_ppi();
+
+		enable_dma(CH_PPI);
+		bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+		SSYNC();
+
+		config_timers();
+		start_timers();
+	} else {
+		t_conf_done = 0;
+	}
+
+	return 0;
+}
+#else
+# define bfin_lq035_suspend	NULL
+# define bfin_lq035_resume	NULL
+#endif
+
+static struct platform_driver bfin_lq035_driver = {
+	.probe = bfin_lq035_probe,
+	.remove = __devexit_p(bfin_lq035_remove),
+	.suspend = bfin_lq035_suspend,
+	.resume = bfin_lq035_resume,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init bfin_lq035_driver_init(void)
+{
+	request_module("i2c-bfin-twi");
+	return platform_driver_register(&bfin_lq035_driver);
+}
+module_init(bfin_lq035_driver_init);
+
+static void __exit bfin_lq035_driver_cleanup(void)
+{
+	platform_driver_unregister(&bfin_lq035_driver);
+}
+module_exit(bfin_lq035_driver_cleanup);
+
+MODULE_DESCRIPTION("SHARP LQ035Q7DB03 TFT LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
new file mode 100644
index 0000000..8486f54
--- /dev/null
+++ b/drivers/video/bfin_adv7393fb.c
@@ -0,0 +1,832 @@
+/*
+ * Frame buffer driver for ADV7393/2 video encoder
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or late.
+ */
+
+/*
+ * TODO: Remove Globals
+ * TODO: Code Cleanup
+ */
+
+#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <asm/portmux.h>
+
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#include "bfin_adv7393fb.h"
+
+static int mode = VMODE;
+static int mem = VMEM;
+static int nocursor = 1;
+
+static const unsigned short ppi_pins[] = {
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+	0
+};
+
+/*
+ * card parameters
+ */
+
+static struct bfin_adv7393_fb_par {
+	/* structure holding blackfin / adv7393 paramters when
+	   screen is blanked */
+	struct {
+		u8 Mode;	/* ntsc/pal/? */
+	} vga_state;
+	atomic_t ref_count;
+} bfin_par;
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo bfin_adv7393_fb_defined = {
+	.xres = 720,
+	.yres = 480,
+	.xres_virtual = 720,
+	.yres_virtual = 480,
+	.bits_per_pixel = 16,
+	.activate = FB_ACTIVATE_TEST,
+	.height = -1,
+	.width = -1,
+	.left_margin = 0,
+	.right_margin = 0,
+	.upper_margin = 0,
+	.lower_margin = 0,
+	.vmode = FB_VMODE_INTERLACED,
+	.red = {11, 5, 0},
+	.green = {5, 6, 0},
+	.blue = {0, 5, 0},
+	.transp = {0, 0, 0},
+};
+
+static struct fb_fix_screeninfo bfin_adv7393_fb_fix __devinitdata = {
+	.id = "BFIN ADV7393",
+	.smem_len = 720 * 480 * 2,
+	.type = FB_TYPE_PACKED_PIXELS,
+	.visual = FB_VISUAL_TRUECOLOR,
+	.xpanstep = 0,
+	.ypanstep = 0,
+	.line_length = 720 * 2,
+	.accel = FB_ACCEL_NONE
+};
+
+static struct fb_ops bfin_adv7393_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = bfin_adv7393_fb_open,
+	.fb_release = bfin_adv7393_fb_release,
+	.fb_check_var = bfin_adv7393_fb_check_var,
+	.fb_pan_display = bfin_adv7393_fb_pan_display,
+	.fb_blank = bfin_adv7393_fb_blank,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = bfin_adv7393_fb_cursor,
+	.fb_setcolreg = bfin_adv7393_fb_setcolreg,
+};
+
+static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg)
+{
+	if (arg == BUILD) {	/* Build */
+		fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->vb1 == NULL)
+			goto error;
+
+		fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->av1 == NULL)
+			goto error;
+
+		fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->vb2 == NULL)
+			goto error;
+
+		fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg));
+		if (fbdev->av2 == NULL)
+			goto error;
+
+		/* Build linked DMA descriptor list */
+		fbdev->vb1->next_desc_addr = fbdev->av1;
+		fbdev->av1->next_desc_addr = fbdev->vb2;
+		fbdev->vb2->next_desc_addr = fbdev->av2;
+		fbdev->av2->next_desc_addr = fbdev->vb1;
+
+		/* Save list head */
+		fbdev->descriptor_list_head = fbdev->av2;
+
+		/* Vertical Blanking Field 1 */
+		fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE;
+		fbdev->vb1->cfg = DMA_CFG_VAL;
+
+		fbdev->vb1->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+		fbdev->vb1->x_modify = 0;
+		fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines;
+		fbdev->vb1->y_modify = 0;
+
+		/* Active Video Field 1 */
+
+		fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem;
+		fbdev->av1->cfg = DMA_CFG_VAL;
+		fbdev->av1->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+		fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8;
+		fbdev->av1->y_count = fbdev->modes[mode].a_lines;
+		fbdev->av1->y_modify =
+		    (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
+		     1) * (fbdev->modes[mode].bpp / 8);
+
+		/* Vertical Blanking Field 2 */
+
+		fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE;
+		fbdev->vb2->cfg = DMA_CFG_VAL;
+		fbdev->vb2->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+		fbdev->vb2->x_modify = 0;
+		fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines;
+		fbdev->vb2->y_modify = 0;
+
+		/* Active Video Field 2 */
+
+		fbdev->av2->start_addr =
+		    (unsigned long)fbdev->fb_mem + fbdev->line_len;
+
+		fbdev->av2->cfg = DMA_CFG_VAL;
+
+		fbdev->av2->x_count =
+		    fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
+
+		fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8);
+		fbdev->av2->y_count = fbdev->modes[mode].a_lines;
+
+		fbdev->av2->y_modify =
+		    (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
+		     1) * (fbdev->modes[mode].bpp / 8);
+
+		return 1;
+	}
+
+error:
+	l1_data_sram_free(fbdev->vb1);
+	l1_data_sram_free(fbdev->av1);
+	l1_data_sram_free(fbdev->vb2);
+	l1_data_sram_free(fbdev->av2);
+
+	return 0;
+}
+
+static int bfin_config_dma(struct adv7393fb_device *fbdev)
+{
+	BUG_ON(!(fbdev->fb_mem));
+
+	set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count);
+	set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify);
+	set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count);
+	set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify);
+	set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr);
+	set_dma_next_desc_addr(CH_PPI,
+			       fbdev->descriptor_list_head->next_desc_addr);
+	set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg);
+
+	return 1;
+}
+
+static void bfin_disable_dma(void)
+{
+	bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN);
+}
+
+static void bfin_config_ppi(struct adv7393fb_device *fbdev)
+{
+	if (ANOMALY_05000183) {
+		bfin_write_TIMER2_CONFIG(WDTH_CAP);
+		bfin_write_TIMER_ENABLE(TIMEN2);
+	}
+
+	bfin_write_PPI_CONTROL(0x381E);
+	bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines);
+	bfin_write_PPI_COUNT(fbdev->modes[mode].xres +
+			     fbdev->modes[mode].boeft_blank - 1);
+	bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1);
+}
+
+static void bfin_enable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+}
+
+static void bfin_disable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
+}
+
+static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static inline int adv7393_read(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int
+adv7393_write_block(struct i2c_client *client,
+		    const u8 *data, unsigned int len)
+{
+	int ret = -1;
+	u8 reg;
+
+	while (len >= 2) {
+		reg = *data++;
+		ret = adv7393_write(client, reg, *data++);
+		if (ret < 0)
+			break;
+		len -= 2;
+	}
+
+	return ret;
+}
+
+static int adv7393_mode(struct i2c_client *client, u16 mode)
+{
+	switch (mode) {
+	case POWER_ON:		/* ADV7393 Sleep mode OFF */
+		adv7393_write(client, 0x00, 0x1E);
+		break;
+	case POWER_DOWN:	/* ADV7393 Sleep mode ON */
+		adv7393_write(client, 0x00, 0x1F);
+		break;
+	case BLANK_OFF:		/* Pixel Data Valid */
+		adv7393_write(client, 0x82, 0xCB);
+		break;
+	case BLANK_ON:		/* Pixel Data Invalid */
+		adv7393_write(client, 0x82, 0x8B);
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+static irqreturn_t ppi_irq_error(int irq, void *dev_id)
+{
+
+	struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id;
+
+	u16 status = bfin_read_PPI_STATUS();
+
+	pr_debug("%s: PPI Status = 0x%X\n", __func__, status);
+
+	if (status) {
+		bfin_disable_dma();	/* TODO: Check Sequence */
+		bfin_disable_ppi();
+		bfin_clear_PPI_STATUS();
+		bfin_config_dma(fbdev);
+		bfin_enable_ppi();
+	}
+
+	return IRQ_HANDLED;
+
+}
+
+static int proc_output(char *buf)
+{
+	char *p = buf;
+
+	p += sprintf(p,
+		"Usage:\n"
+		"echo 0x[REG][Value] > adv7393\n"
+		"example: echo 0x1234 >adv7393\n"
+		"writes 0x34 into Register 0x12\n");
+
+	return p - buf;
+}
+
+static int
+adv7393_read_proc(char *page, char **start, off_t off,
+		  int count, int *eof, void *data)
+{
+	int len;
+
+	len = proc_output(page);
+	if (len <= off + count)
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+	return len;
+}
+
+static int
+adv7393_write_proc(struct file *file, const char __user * buffer,
+		   unsigned long count, void *data)
+{
+	struct adv7393fb_device *fbdev = data;
+	char line[8];
+	unsigned int val;
+	int ret;
+
+	ret = copy_from_user(line, buffer, count);
+	if (ret)
+		return -EFAULT;
+
+	val = simple_strtoul(line, NULL, 0);
+	adv7393_write(fbdev->client, val >> 8, val & 0xff);
+
+	return count;
+}
+
+static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
+					   const struct i2c_device_id *id)
+{
+	int ret = 0;
+	struct proc_dir_entry *entry;
+	int num_modes = ARRAY_SIZE(known_modes);
+
+	struct adv7393fb_device *fbdev = NULL;
+
+	if (mem > 2) {
+		dev_err(&client->dev, "mem out of allowed range [1;2]\n");
+		return -EINVAL;
+	}
+
+	if (mode > num_modes) {
+		dev_err(&client->dev, "mode %d: not supported", mode);
+		return -EFAULT;
+	}
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev) {
+		dev_err(&client->dev, "failed to allocate device private record");
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(client, fbdev);
+
+	fbdev->modes = known_modes;
+	fbdev->client = client;
+
+	fbdev->fb_len =
+	    mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres *
+	    (fbdev->modes[mode].bpp / 8);
+
+	fbdev->line_len =
+	    fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8);
+
+	/* Workaround "PPI Does Not Start Properly In Specific Mode" */
+	if (ANOMALY_05000400) {
+		if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) {
+			dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
+			ret = -EBUSY;
+			goto out_8;
+		}
+		gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
+	}
+
+	if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
+		dev_err(&client->dev, "requesting PPI peripheral failed\n");
+		ret = -EFAULT;
+		goto out_8;
+	}
+
+	fbdev->fb_mem =
+	    dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle,
+			       GFP_KERNEL);
+
+	if (NULL == fbdev->fb_mem) {
+		dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n",
+		       (u32) fbdev->fb_len);
+		ret = -ENOMEM;
+		goto out_7;
+	}
+
+	fbdev->info.screen_base = (void *)fbdev->fb_mem;
+	bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem;
+
+	bfin_adv7393_fb_fix.smem_len = fbdev->fb_len;
+	bfin_adv7393_fb_fix.line_length = fbdev->line_len;
+
+	if (mem > 1)
+		bfin_adv7393_fb_fix.ypanstep = 1;
+
+	bfin_adv7393_fb_defined.red.length = 5;
+	bfin_adv7393_fb_defined.green.length = 6;
+	bfin_adv7393_fb_defined.blue.length = 5;
+
+	bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres;
+	bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres;
+	bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres;
+	bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres;
+	bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp;
+
+	fbdev->info.fbops = &bfin_adv7393_fb_ops;
+	fbdev->info.var = bfin_adv7393_fb_defined;
+	fbdev->info.fix = bfin_adv7393_fb_fix;
+	fbdev->info.par = &bfin_par;
+	fbdev->info.flags = FBINFO_DEFAULT;
+
+	fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
+	if (!fbdev->info.pseudo_palette) {
+		dev_err(&client->dev, "failed to allocate pseudo_palette\n");
+		ret = -ENOMEM;
+		goto out_6;
+	}
+
+	if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+		dev_err(&client->dev, "failed to allocate colormap (%d entries)\n",
+			   BFIN_LCD_NBR_PALETTE_ENTRIES);
+		ret = -EFAULT;
+		goto out_5;
+	}
+
+	if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) {
+		dev_err(&client->dev, "unable to request PPI DMA\n");
+		ret = -EFAULT;
+		goto out_4;
+	}
+
+	if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED,
+			"PPI ERROR", fbdev) < 0) {
+		dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
+		ret = -EFAULT;
+		goto out_3;
+	}
+
+	fbdev->open = 0;
+
+	ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd,
+				fbdev->modes[mode].adv7393_i2c_initd_len);
+
+	if (ret) {
+		dev_err(&client->dev, "i2c attach: init error\n");
+		goto out_1;
+	}
+
+
+	if (register_framebuffer(&fbdev->info) < 0) {
+		dev_err(&client->dev, "unable to register framebuffer\n");
+		ret = -EFAULT;
+		goto out_1;
+	}
+
+	dev_info(&client->dev, "fb%d: %s frame buffer device\n",
+	       fbdev->info.node, fbdev->info.fix.id);
+	dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
+
+	entry = create_proc_entry("driver/adv7393", 0, NULL);
+	if (!entry) {
+		dev_err(&client->dev, "unable to create /proc entry\n");
+		ret = -EFAULT;
+		goto out_0;
+	}
+
+	entry->read_proc = adv7393_read_proc;
+	entry->write_proc = adv7393_write_proc;
+	entry->data = fbdev;
+
+	return 0;
+
+ out_0:
+	unregister_framebuffer(&fbdev->info);
+ out_1:
+	free_irq(IRQ_PPI_ERROR, fbdev);
+ out_3:
+	free_dma(CH_PPI);
+ out_4:
+	dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem,
+			  fbdev->dma_handle);
+ out_5:
+	fb_dealloc_cmap(&fbdev->info.cmap);
+ out_6:
+	kfree(fbdev->info.pseudo_palette);
+ out_7:
+	peripheral_free_list(ppi_pins);
+ out_8:
+	kfree(fbdev);
+
+	return ret;
+}
+
+static int bfin_adv7393_fb_open(struct fb_info *info, int user)
+{
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	fbdev->info.screen_base = (void *)fbdev->fb_mem;
+	if (!fbdev->info.screen_base) {
+		dev_err(&fbdev->client->dev, "unable to map device\n");
+		return -ENOMEM;
+	}
+
+	fbdev->open = 1;
+	dma_desc_list(fbdev, BUILD);
+	adv7393_mode(fbdev->client, BLANK_OFF);
+	bfin_config_ppi(fbdev);
+	bfin_config_dma(fbdev);
+	bfin_enable_ppi();
+
+	return 0;
+}
+
+static int bfin_adv7393_fb_release(struct fb_info *info, int user)
+{
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	adv7393_mode(fbdev->client, BLANK_ON);
+	bfin_disable_dma();
+	bfin_disable_ppi();
+	dma_desc_list(fbdev, DESTRUCT);
+	fbdev->open = 0;
+	return 0;
+}
+
+static int
+bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+
+	switch (var->bits_per_pixel) {
+	case 16:/* DIRECTCOLOUR, 64k */
+		var->red.offset = info->var.red.offset;
+		var->green.offset = info->var.green.offset;
+		var->blue.offset = info->var.blue.offset;
+		var->red.length = info->var.red.length;
+		var->green.length = info->var.green.length;
+		var->blue.length = info->var.blue.length;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		break;
+	default:
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres ||
+	    info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u\n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int
+bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int dy;
+	u32 dmaaddr;
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	if (!var || !info)
+		return -EINVAL;
+
+	if (var->xoffset - info->var.xoffset) {
+		/* No support for X panning for now! */
+		return -EINVAL;
+	}
+	dy = var->yoffset - info->var.yoffset;
+
+	if (dy) {
+		pr_debug("%s: Panning screen of %d lines\n", __func__, dy);
+
+		dmaaddr = fbdev->av1->start_addr;
+		dmaaddr += (info->fix.line_length * dy);
+		/* TODO: Wait for current frame to finished */
+
+		fbdev->av1->start_addr = (unsigned long)dmaaddr;
+		fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len;
+	}
+
+	return 0;
+
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+static int bfin_adv7393_fb_blank(int blank, struct fb_info *info)
+{
+	struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
+
+	switch (blank) {
+
+	case VESA_NO_BLANKING:
+		/* Turn on panel */
+		adv7393_mode(fbdev->client, BLANK_OFF);
+		break;
+
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+	case VESA_POWERDOWN:
+		/* Turn off panel */
+		adv7393_mode(fbdev->client, BLANK_ON);
+		break;
+
+	default:
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green,
+				     u_int blue, u_int transp,
+				     struct fb_info *info)
+{
+	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red   >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue  >>= (16 - info->var.blue.length);
+
+		value = (red   << info->var.red.offset) |
+			(green << info->var.green.offset)|
+			(blue  << info->var.blue.offset);
+		value &= 0xFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+	}
+
+	return 0;
+}
+
+static int __devexit bfin_adv7393_fb_remove(struct i2c_client *client)
+{
+	struct adv7393fb_device *fbdev = i2c_get_clientdata(client);
+
+	adv7393_mode(client, POWER_DOWN);
+
+	if (fbdev->fb_mem)
+		dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle);
+	free_dma(CH_PPI);
+	free_irq(IRQ_PPI_ERROR, fbdev);
+	unregister_framebuffer(&fbdev->info);
+	remove_proc_entry("driver/adv7393", NULL);
+	fb_dealloc_cmap(&fbdev->info.cmap);
+	kfree(fbdev->info.pseudo_palette);
+
+	if (ANOMALY_05000400)
+		gpio_free(P_IDENT(P_PPI0_FS3));	/* FS3 */
+	peripheral_free_list(ppi_pins);
+	kfree(fbdev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_adv7393_fb_suspend(struct device *dev)
+{
+	struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
+
+	if (fbdev->open) {
+		bfin_disable_dma();
+		bfin_disable_ppi();
+		dma_desc_list(fbdev, DESTRUCT);
+	}
+	adv7393_mode(fbdev->client, POWER_DOWN);
+
+	return 0;
+}
+
+static int bfin_adv7393_fb_resume(struct device *dev)
+{
+	struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
+
+	adv7393_mode(fbdev->client, POWER_ON);
+
+	if (fbdev->open) {
+		dma_desc_list(fbdev, BUILD);
+		bfin_config_ppi(fbdev);
+		bfin_config_dma(fbdev);
+		bfin_enable_ppi();
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = {
+	.suspend = bfin_adv7393_fb_suspend,
+	.resume  = bfin_adv7393_fb_resume,
+};
+#endif
+
+static const struct i2c_device_id bfin_adv7393_id[] = {
+	{DRIVER_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id);
+
+static struct i2c_driver bfin_adv7393_fb_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+#ifdef CONFIG_PM
+		.pm   = &bfin_adv7393_dev_pm_ops,
+#endif
+	},
+	.probe = bfin_adv7393_fb_probe,
+	.remove = __devexit_p(bfin_adv7393_fb_remove),
+	.id_table = bfin_adv7393_id,
+};
+
+static int __init bfin_adv7393_fb_driver_init(void)
+{
+#if  defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+	request_module("i2c-bfin-twi");
+#else
+	request_module("i2c-gpio");
+#endif
+
+	return i2c_add_driver(&bfin_adv7393_fb_driver);
+}
+module_init(bfin_adv7393_fb_driver_init);
+
+static void __exit bfin_adv7393_fb_driver_cleanup(void)
+{
+	i2c_del_driver(&bfin_adv7393_fb_driver);
+}
+module_exit(bfin_adv7393_fb_driver_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder");
+
+module_param(mode, int, 0);
+MODULE_PARM_DESC(mode,
+	"Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)");
+
+module_param(mem, int, 0);
+MODULE_PARM_DESC(mem,
+	"Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)");
+
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/bfin_adv7393fb.h
new file mode 100644
index 0000000..8c7f9e4
--- /dev/null
+++ b/drivers/video/bfin_adv7393fb.h
@@ -0,0 +1,321 @@
+/*
+ * Frame buffer driver for ADV7393/2 video encoder
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or late.
+ */
+
+#ifndef __BFIN_ADV7393FB_H__
+#define __BFIN_ADV7393FB_H__
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
+
+#ifdef CONFIG_NTSC
+# define VMODE 0
+#endif
+#ifdef CONFIG_PAL
+# define VMODE 1
+#endif
+#ifdef CONFIG_NTSC_640x480
+# define VMODE 2
+#endif
+#ifdef CONFIG_PAL_640x480
+# define VMODE 3
+#endif
+#ifdef CONFIG_NTSC_YCBCR
+# define VMODE 4
+#endif
+#ifdef CONFIG_PAL_YCBCR
+# define VMODE 5
+#endif
+
+#ifndef VMODE
+# define VMODE 1
+#endif
+
+#ifdef CONFIG_ADV7393_2XMEM
+# define VMEM 2
+#else
+# define VMEM 1
+#endif
+
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
+# define DMA_CFG_VAL	0x7935	/* Set Sync Bit */
+# define VB_DUMMY_MEMORY_SOURCE	L1_DATA_B_START
+#else
+# define DMA_CFG_VAL	0x7915
+# define VB_DUMMY_MEMORY_SOURCE	BOOT_ROM_START
+#endif
+
+enum {
+	DESTRUCT,
+	BUILD,
+};
+
+enum {
+	POWER_ON,
+	POWER_DOWN,
+	BLANK_ON,
+	BLANK_OFF,
+};
+
+#define DRIVER_NAME "bfin-adv7393"
+
+struct adv7393fb_modes {
+	const s8 name[25];	/* Full name */
+	u16 xres;		/* Active Horizonzal Pixels  */
+	u16 yres;		/* Active Vertical Pixels  */
+	u16 bpp;
+	u16 vmode;
+	u16 a_lines;		/* Active Lines per Field */
+	u16 vb1_lines;		/* Vertical Blanking Field 1 Lines */
+	u16 vb2_lines;		/* Vertical Blanking Field 2 Lines */
+	u16 tot_lines;		/* Total Lines per Frame */
+	u16 boeft_blank;	/* Before Odd/Even Field Transition No. of Blank Pixels */
+	u16 aoeft_blank;	/* After Odd/Even Field Transition No. of Blank Pixels */
+	const s8 *adv7393_i2c_initd;
+	u16 adv7393_i2c_initd_len;
+};
+
+static const u8 init_NTSC_TESTPATTERN[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x10,	/* SSAF Luma Filter Enabled, NTSC Mode */
+	0x82, 0xCB,	/* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x84, 0x40,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+};
+
+static const u8 init_NTSC[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0xC3, 0x26,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xC5, 0x12,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xBD, 0x19,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xBF, 0x42,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
+	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
+	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
+	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x20,
+	0x8A, 0x0d,
+};
+
+static const u8 init_PAL[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0xC3, 0x26,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xC5, 0x12,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xBD, 0x19,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0xBF, 0x42,	/* Program RGB->YCrCb Color Space convertion matrix */
+	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
+	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
+	0x8E, 0x09,	/* PAL Subcarrier Frequency */
+	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x20,
+	0x8A, 0x0d,
+};
+
+static const u8 init_NTSC_YCbCr[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
+	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
+	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
+	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x08,
+	0x8A, 0x0d,
+};
+
+static const u8 init_PAL_YCbCr[] = {
+	0x00, 0x1E,	/* Power up all DACs and PLL */
+	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
+	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
+	0x8E, 0x09,	/* PAL Subcarrier Frequency */
+	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
+	0x01, 0x00,	/* SD-Only Mode */
+	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
+	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
+	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
+	0x86, 0x82,
+	0x8B, 0x11,
+	0x88, 0x08,
+	0x8A, 0x0d,
+};
+
+static struct adv7393fb_modes known_modes[] = {
+	/* NTSC 720x480 CRT */
+	{
+		.name = "NTSC 720x480",
+		.xres = 720,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 240,
+		.vb1_lines = 22,
+		.vb2_lines = 23,
+		.tot_lines = 525,
+		.boeft_blank = 16,
+		.aoeft_blank = 122,
+		.adv7393_i2c_initd = init_NTSC,
+		.adv7393_i2c_initd_len = sizeof(init_NTSC)
+	},
+	/* PAL 720x480 CRT */
+	{
+		.name = "PAL 720x576",
+		.xres = 720,
+		.yres = 576,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 288,
+		.vb1_lines = 24,
+		.vb2_lines = 25,
+		.tot_lines = 625,
+		.boeft_blank = 12,
+		.aoeft_blank = 132,
+		.adv7393_i2c_initd = init_PAL,
+		.adv7393_i2c_initd_len = sizeof(init_PAL)
+	},
+	/* NTSC 640x480 CRT Experimental */
+	{
+		.name = "NTSC 640x480",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 240,
+		.vb1_lines = 22,
+		.vb2_lines = 23,
+		.tot_lines = 525,
+		.boeft_blank = 16 + 40,
+		.aoeft_blank = 122 + 40,
+		.adv7393_i2c_initd = init_NTSC,
+		.adv7393_i2c_initd_len = sizeof(init_NTSC)
+	},
+	/* PAL 640x480 CRT Experimental */
+	{
+		.name = "PAL 640x480",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 288 - 20,
+		.vb1_lines = 24 + 20,
+		.vb2_lines = 25 + 20,
+		.tot_lines = 625,
+		.boeft_blank = 12 + 40,
+		.aoeft_blank = 132 + 40,
+		.adv7393_i2c_initd = init_PAL,
+		.adv7393_i2c_initd_len = sizeof(init_PAL)
+	},
+	/* NTSC 720x480 YCbCR */
+	{
+		.name = "NTSC 720x480 YCbCR",
+		.xres = 720,
+		.yres = 480,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 240,
+		.vb1_lines = 22,
+		.vb2_lines = 23,
+		.tot_lines = 525,
+		.boeft_blank = 16,
+		.aoeft_blank = 122,
+		.adv7393_i2c_initd = init_NTSC_YCbCr,
+		.adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr)
+	},
+	/* PAL 720x480 CRT */
+	{
+		.name = "PAL 720x576 YCbCR",
+		.xres = 720,
+		.yres = 576,
+		.bpp = 16,
+		.vmode = FB_VMODE_INTERLACED,
+		.a_lines = 288,
+		.vb1_lines = 24,
+		.vb2_lines = 25,
+		.tot_lines = 625,
+		.boeft_blank = 12,
+		.aoeft_blank = 132,
+		.adv7393_i2c_initd = init_PAL_YCbCr,
+		.adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr)
+	}
+};
+
+struct adv7393fb_regs {
+
+};
+
+struct adv7393fb_device {
+	struct fb_info info;	/* FB driver info record */
+
+	struct i2c_client *client;
+
+	struct dmasg *descriptor_list_head;
+	struct dmasg *vb1;
+	struct dmasg *av1;
+	struct dmasg *vb2;
+	struct dmasg *av2;
+
+	dma_addr_t dma_handle;
+
+	struct fb_info bfin_adv7393_fb;
+
+	struct adv7393fb_modes *modes;
+
+	struct adv7393fb_regs *regs;	/* Registers memory map */
+	size_t regs_len;
+	size_t fb_len;
+	size_t line_len;
+	u16 open;
+	u16 *fb_mem;		/* RGB Buffer */
+
+};
+
+#define to_adv7393fb_device(_info) \
+	  (_info ? container_of(_info, struct adv7393fb_device, info) : NULL);
+
+static int bfin_adv7393_fb_open(struct fb_info *info, int user);
+static int bfin_adv7393_fb_release(struct fb_info *info, int user);
+static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var,
+				     struct fb_info *info);
+
+static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var,
+				       struct fb_info *info);
+
+static int bfin_adv7393_fb_blank(int blank, struct fb_info *info);
+
+static void bfin_config_ppi(struct adv7393fb_device *fbdev);
+static int bfin_config_dma(struct adv7393fb_device *fbdev);
+static void bfin_disable_dma(void);
+static void bfin_enable_ppi(void);
+static void bfin_disable_ppi(void);
+
+static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value);
+static inline int adv7393_read(struct i2c_client *client, u8 reg);
+static int adv7393_write_block(struct i2c_client *client, const u8 *data,
+			       unsigned int len);
+
+int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int,
+				     u_int, struct fb_info *info);
+
+#endif
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
index 6b19136..caaa27d 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/carminefb.c
@@ -654,7 +654,7 @@
 		printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
 				"are required.", carminefb_fix.smem_len,
 				CARMINE_TOTAL_DIPLAY_MEM);
-		goto err_free_reg_mmio;
+		goto err_unmap_vregs;
 	}
 
 	if (!request_mem_region(carminefb_fix.smem_start,
@@ -667,8 +667,6 @@
 			carminefb_fix.smem_len);
 	if (!hw->screen_mem) {
 		printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
-		release_mem_region(carminefb_fix.smem_start,
-				carminefb_fix.smem_len);
 		goto err_reg_smem;
 	}
 
@@ -710,7 +708,7 @@
 err_unmap_screen:
 	iounmap(hw->screen_mem);
 err_reg_smem:
-	release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+	release_mem_region(carminefb_fix.smem_start, carminefb_fix.smem_len);
 err_unmap_vregs:
 	iounmap(hw->v_regs);
 err_free_reg_mmio:
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 6b93ef9..8040001 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -75,7 +75,7 @@
 		return 0;
 
 	/* Kill off the delayed work */
-	cancel_rearming_delayed_work(&info->deferred_work);
+	cancel_delayed_work_sync(&info->deferred_work);
 
 	/* Run it immediately */
 	return schedule_delayed_work(&info->deferred_work, 0);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 0e6aa3d..4ac1201 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1458,7 +1458,7 @@
 	if (gen->base == hw->base)
 		return true;
 	/* is the generic aperture base inside the hw base->hw base+size */
-	if (gen->base > hw->base && gen->base <= hw->base + hw->size)
+	if (gen->base > hw->base && gen->base < hw->base + hw->size)
 		return true;
 	return false;
 }
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 563a98b..4f57485 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -973,6 +973,90 @@
 	DPRINTK("========================================\n");
 }
 
+/**
+ * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
+ * @edid:	128 byte array with an E-EDID block
+ * @spacs:	monitor specs to be extended
+ */
+void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+	unsigned char *block;
+	struct fb_videomode *m;
+	int num = 0, i;
+	u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
+	u8 pos = 4, svd_n = 0;
+
+	if (!edid)
+		return;
+
+	if (!edid_checksum(edid))
+		return;
+
+	if (edid[0] != 0x2 ||
+	    edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
+		return;
+
+	DPRINTK("  Short Video Descriptors\n");
+
+	while (pos < edid[2]) {
+		u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
+		pr_debug("Data block %u of %u bytes\n", type, len);
+		if (type == 2)
+			for (i = pos; i < pos + len; i++) {
+				u8 idx = edid[pos + i] & 0x7f;
+				svd[svd_n++] = idx;
+				pr_debug("N%sative mode #%d\n",
+					 edid[pos + i] & 0x80 ? "" : "on-n", idx);
+			}
+		pos += len + 1;
+	}
+
+	block = edid + edid[2];
+
+	DPRINTK("  Extended Detailed Timings\n");
+
+	for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
+	     i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
+		if (PIXEL_CLOCK)
+			edt[num++] = block - edid;
+
+	/* Yikes, EDID data is totally useless */
+	if (!(num + svd_n))
+		return;
+
+	m = kzalloc((specs->modedb_len + num + svd_n) *
+		       sizeof(struct fb_videomode), GFP_KERNEL);
+
+	if (!m)
+		return;
+
+	memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
+
+	for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
+		get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
+		if (i == specs->modedb_len)
+			m[i].flag |= FB_MODE_IS_FIRST;
+		pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
+	}
+
+	for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
+		int idx = svd[i - specs->modedb_len - num];
+		if (!idx || idx > 63) {
+			pr_warning("Reserved SVD code %d\n", idx);
+		} else if (idx > ARRAY_SIZE(cea_modes) || !cea_modes[idx].xres) {
+			pr_warning("Unimplemented SVD code %d\n", idx);
+		} else {
+			memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
+			pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
+				 m[i].xres, m[i].yres, m[i].refresh);
+		}
+	}
+
+	kfree(specs->modedb);
+	specs->modedb = m;
+	specs->modedb_len = specs->modedb_len + num + svd_n;
+}
+
 /*
  * VESA Generalized Timing Formula (GTF)
  */
@@ -1289,6 +1373,9 @@
 {
 	specs = NULL;
 }
+void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+}
 void fb_destroy_modedb(struct fb_videomode *modedb)
 {
 }
@@ -1396,6 +1483,7 @@
 
 EXPORT_SYMBOL(fb_parse_edid);
 EXPORT_SYMBOL(fb_edid_to_monspecs);
+EXPORT_SYMBOL(fb_edid_add_monspecs);
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
 EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index af8f0f2..4052718 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -454,7 +454,6 @@
 /*
  * Accel functions
  */
-#ifdef CONFIG_FB_HGA_ACCEL
 static void hgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	u_int rows, y;
@@ -466,7 +465,7 @@
 		dest = rowaddr(info, y) + (rect->dx >> 3);
 		switch (rect->rop) {
 		case ROP_COPY:
-			//fb_memset(dest, rect->color, (rect->width >> 3));
+			memset_io(dest, rect->color, (rect->width >> 3));
 			break;
 		case ROP_XOR:
 			fb_writeb(~(fb_readb(dest)), dest);
@@ -488,7 +487,7 @@
 		for (rows = area->height; rows--; ) {
 			src = rowaddr(info, y1) + (area->sx >> 3);
 			dest = rowaddr(info, y2) + (area->dx >> 3);
-			//fb_memmove(dest, src, (area->width >> 3));
+			memmove(dest, src, (area->width >> 3));
 			y1++;
 			y2++;
 		}
@@ -499,7 +498,7 @@
 		for (rows = area->height; rows--;) {
 			src = rowaddr(info, y1) + (area->sx >> 3);
 			dest = rowaddr(info, y2) + (area->dx >> 3);
-			//fb_memmove(dest, src, (area->width >> 3));
+			memmove(dest, src, (area->width >> 3));
 			y1--;
 			y2--;
 		}
@@ -511,20 +510,17 @@
 	u8 __iomem *dest;
 	u8 *cdat = (u8 *) image->data;
 	u_int rows, y = image->dy;
+	u_int x;
 	u8 d;
 
 	for (rows = image->height; rows--; y++) {
-		d = *cdat++;
-		dest = rowaddr(info, y) + (image->dx >> 3);
-		fb_writeb(d, dest);
+		for (x = 0; x < image->width; x+= 8) {
+			d = *cdat++;
+			dest = rowaddr(info, y) + ((image->dx + x)>> 3);
+			fb_writeb(d, dest);
+		}
 	}
 }
-#else /* !CONFIG_FB_HGA_ACCEL */
-#define hgafb_fillrect cfb_fillrect
-#define hgafb_copyarea cfb_copyarea
-#define hgafb_imageblit cfb_imageblit
-#endif /* CONFIG_FB_HGA_ACCEL */
-
 
 static struct fb_ops hgafb_ops = {
 	.owner		= THIS_MODULE,
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index cd2c728..7db17d0 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -45,8 +45,10 @@
         struct i810fb_par         *par = chan->par;
 	u8                        __iomem *mmio = par->mmio_start_virtual;
 
-	i810_writel(mmio, chan->ddc_base, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
-		    SCL_DIR_MASK | SCL_VAL_MASK);
+	if (state)
+		i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK);
+	else
+		i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
 	i810_readl(mmio, chan->ddc_base);	/* flush posted write */
 }
 
@@ -56,8 +58,10 @@
         struct i810fb_par         *par = chan->par;
 	u8                        __iomem *mmio = par->mmio_start_virtual;
 
- 	i810_writel(mmio, chan->ddc_base, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
-		    SDA_DIR_MASK | SDA_VAL_MASK);
+	if (state)
+		i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK);
+	else
+		i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
 	i810_readl(mmio, chan->ddc_base);	/* flush posted write */
 }
 
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 5c363d0..1ab2c25 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -53,11 +53,8 @@
 #define LCDC_SIZE	0x04
 #define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20)
 
-#ifdef CONFIG_ARCH_MX1
-#define SIZE_YMAX(y)	((y) & 0x1ff)
-#else
-#define SIZE_YMAX(y)	((y) & 0x3ff)
-#endif
+#define YMAX_MASK       (cpu_is_mx1() ? 0x1ff : 0x3ff)
+#define SIZE_YMAX(y)	((y) & YMAX_MASK)
 
 #define LCDC_VPW	0x08
 #define VPW_VPW(x)	((x) & 0x3ff)
@@ -623,7 +620,7 @@
 	if (var->right_margin > 255)
 		printk(KERN_ERR "%s: invalid right_margin %d\n",
 			info->fix.id, var->right_margin);
-	if (var->yres < 1 || var->yres > 511)
+	if (var->yres < 1 || var->yres > YMAX_MASK)
 		printk(KERN_ERR "%s: invalid yres %d\n",
 			info->fix.id, var->yres);
 	if (var->vsync_len > 100)
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index de450c1..d2bb365 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -274,10 +274,61 @@
        /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
        NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5,
        0, FB_VMODE_INTERLACED
+    }, {
+	/* 864x480 @ 60 Hz, 35.15 kHz hsync */
+	NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
+	0, FB_VMODE_NONINTERLACED
     },
 };
 
 #ifdef CONFIG_FB_MODE_HELPERS
+const struct fb_videomode cea_modes[64] = {
+	/* #1: 640x480p@59.94/60Hz */
+	[1] = {
+		NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #3: 720x480p@59.94/60Hz */
+	[3] = {
+		NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #5: 1920x1080i@59.94/60Hz */
+	[5] = {
+		NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0,
+	},
+	/* #7: 720(1440)x480iH@59.94/60Hz */
+	[7] = {
+		NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0, FB_VMODE_INTERLACED, 0,
+	},
+	/* #9: 720(1440)x240pH@59.94/60Hz */
+	[9] = {
+		NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0, FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #18: 720x576pH@50Hz */
+	[18] = {
+		NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0, FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #19: 1280x720p@50Hz */
+	[19] = {
+		NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #20: 1920x1080i@50Hz */
+	[20] = {
+		NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0,
+	},
+	/* #32: 1920x1080p@23.98/24Hz */
+	[32] = {
+		NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
+		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0,
+	},
+	/* #35: (2880)x480p4x@59.94/60Hz */
+	[35] = {
+		NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0, FB_VMODE_NONINTERLACED, 0,
+	},
+};
+
 const struct fb_videomode vesa_modes[] = {
 	/* 0 640x350-85 VESA */
 	{ NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index ca0f6be..cb01391 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -1474,8 +1474,7 @@
 		goto eremap;
 	}
 
-	pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end,
-		 mx3fb->reg_base);
+	pr_debug("Remapped %pR at %p\n", sdc_reg, mx3fb->reg_base);
 
 	/* IDMAC interface */
 	dmaengine_get();
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index 64dcc74..90e3bdd 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -396,7 +396,7 @@
 static void mipid_esd_stop_check(struct mipid_device *md)
 {
 	if (md->esd_check != NULL)
-		cancel_rearming_delayed_workqueue(md->esd_wq, &md->esd_work);
+		cancel_delayed_work_sync(&md->esd_work);
 }
 
 static void mipid_esd_work(struct work_struct *work)
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
new file mode 100644
index 0000000..b81168d
--- /dev/null
+++ b/drivers/video/pxa3xx-gcu.c
@@ -0,0 +1,772 @@
+/*
+ *  pxa3xx-gc.c - Linux kernel module for PXA3xx graphics controllers
+ *
+ *  This driver needs a DirectFB counterpart in user space, communication
+ *  is handled via mmap()ed memory areas and an ioctl.
+ *
+ *  Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *  Copyright (c) 2009 Janine Kropp <nin@directfb.org>
+ *  Copyright (c) 2009 Denis Oliver Kropp <dok@directfb.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.
+ */
+
+/*
+ * WARNING: This controller is attached to System Bus 2 of the PXA which
+ * needs its arbiter to be enabled explictly (CKENB & 1<<9).
+ * There is currently no way to do this from Linux, so you need to teach
+ * your bootloader for now.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+
+#include "pxa3xx-gcu.h"
+
+#define DRV_NAME	"pxa3xx-gcu"
+#define MISCDEV_MINOR	197
+
+#define REG_GCCR	0x00
+#define GCCR_SYNC_CLR	(1 << 9)
+#define GCCR_BP_RST	(1 << 8)
+#define GCCR_ABORT	(1 << 6)
+#define GCCR_STOP	(1 << 4)
+
+#define REG_GCISCR	0x04
+#define REG_GCIECR	0x08
+#define REG_GCRBBR	0x20
+#define REG_GCRBLR	0x24
+#define REG_GCRBHR	0x28
+#define REG_GCRBTR	0x2C
+#define REG_GCRBEXHR	0x30
+
+#define IE_EOB		(1 << 0)
+#define IE_EEOB		(1 << 5)
+#define IE_ALL		0xff
+
+#define SHARED_SIZE	PAGE_ALIGN(sizeof(struct pxa3xx_gcu_shared))
+
+/* #define PXA3XX_GCU_DEBUG */
+/* #define PXA3XX_GCU_DEBUG_TIMER */
+
+#ifdef PXA3XX_GCU_DEBUG
+#define QDUMP(msg)					\
+	do {						\
+		QPRINT(priv, KERN_DEBUG, msg);		\
+	} while (0)
+#else
+#define QDUMP(msg)	do {} while (0)
+#endif
+
+#define QERROR(msg)					\
+	do {						\
+		QPRINT(priv, KERN_ERR, msg);		\
+	} while (0)
+
+struct pxa3xx_gcu_batch {
+	struct pxa3xx_gcu_batch *next;
+	u32			*ptr;
+	dma_addr_t		 phys;
+	unsigned long		 length;
+};
+
+struct pxa3xx_gcu_priv {
+	void __iomem		 *mmio_base;
+	struct clk		 *clk;
+	struct pxa3xx_gcu_shared *shared;
+	dma_addr_t		  shared_phys;
+	struct resource		 *resource_mem;
+	struct miscdevice	  misc_dev;
+	struct file_operations	  misc_fops;
+	wait_queue_head_t	  wait_idle;
+	wait_queue_head_t	  wait_free;
+	spinlock_t		  spinlock;
+	struct timeval 		  base_time;
+
+	struct pxa3xx_gcu_batch *free;
+
+	struct pxa3xx_gcu_batch *ready;
+	struct pxa3xx_gcu_batch *ready_last;
+	struct pxa3xx_gcu_batch *running;
+};
+
+static inline unsigned long
+gc_readl(struct pxa3xx_gcu_priv *priv, unsigned int off)
+{
+	return __raw_readl(priv->mmio_base + off);
+}
+
+static inline void
+gc_writel(struct pxa3xx_gcu_priv *priv, unsigned int off, unsigned long val)
+{
+	__raw_writel(val, priv->mmio_base + off);
+}
+
+#define QPRINT(priv, level, msg)					\
+	do {								\
+		struct timeval tv;					\
+		struct pxa3xx_gcu_shared *shared = priv->shared;	\
+		u32 base = gc_readl(priv, REG_GCRBBR);			\
+									\
+		do_gettimeofday(&tv);					\
+									\
+		printk(level "%ld.%03ld.%03ld - %-17s: %-21s (%s, "	\
+			"STATUS "					\
+			"0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, "	\
+			"T %5ld)\n",					\
+			tv.tv_sec - priv->base_time.tv_sec,		\
+			tv.tv_usec / 1000, tv.tv_usec % 1000,		\
+			__func__, msg,					\
+			shared->hw_running ? "running" : "   idle",	\
+			gc_readl(priv, REG_GCISCR),			\
+			gc_readl(priv, REG_GCRBBR),			\
+			gc_readl(priv, REG_GCRBLR),			\
+			(gc_readl(priv, REG_GCRBEXHR) - base) / 4,	\
+			(gc_readl(priv, REG_GCRBHR) - base) / 4,	\
+			(gc_readl(priv, REG_GCRBTR) - base) / 4);	\
+	} while (0)
+
+static void
+pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
+{
+	QDUMP("RESET");
+
+	/* disable interrupts */
+	gc_writel(priv, REG_GCIECR, 0);
+
+	/* reset hardware */
+	gc_writel(priv, REG_GCCR, GCCR_ABORT);
+	gc_writel(priv, REG_GCCR, 0);
+
+	memset(priv->shared, 0, SHARED_SIZE);
+	priv->shared->buffer_phys = priv->shared_phys;
+	priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
+
+	do_gettimeofday(&priv->base_time);
+
+	/* set up the ring buffer pointers */
+	gc_writel(priv, REG_GCRBLR, 0);
+	gc_writel(priv, REG_GCRBBR, priv->shared_phys);
+	gc_writel(priv, REG_GCRBTR, priv->shared_phys);
+
+	/* enable all IRQs except EOB */
+	gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
+}
+
+static void
+dump_whole_state(struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_shared *sh = priv->shared;
+	u32 base = gc_readl(priv, REG_GCRBBR);
+
+	QDUMP("DUMP");
+
+	printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
+		"%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
+		sh->hw_running ? "running" : "idle   ",
+		gc_readl(priv, REG_GCISCR),
+		gc_readl(priv, REG_GCRBBR),
+		gc_readl(priv, REG_GCRBLR),
+		(gc_readl(priv, REG_GCRBEXHR) - base) / 4,
+		(gc_readl(priv, REG_GCRBHR) - base) / 4,
+		(gc_readl(priv, REG_GCRBTR) - base) / 4);
+}
+
+static void
+flush_running(struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_batch *running = priv->running;
+	struct pxa3xx_gcu_batch *next;
+
+	while (running) {
+		next = running->next;
+		running->next = priv->free;
+		priv->free = running;
+		running = next;
+	}
+
+	priv->running = NULL;
+}
+
+static void
+run_ready(struct pxa3xx_gcu_priv *priv)
+{
+	unsigned int num = 0;
+	struct pxa3xx_gcu_shared *shared = priv->shared;
+	struct pxa3xx_gcu_batch	*ready = priv->ready;
+
+	QDUMP("Start");
+
+	BUG_ON(!ready);
+
+	shared->buffer[num++] = 0x05000000;
+
+	while (ready) {
+		shared->buffer[num++] = 0x00000001;
+		shared->buffer[num++] = ready->phys;
+		ready = ready->next;
+	}
+
+	shared->buffer[num++] = 0x05000000;
+	priv->running = priv->ready;
+	priv->ready = priv->ready_last = NULL;
+	gc_writel(priv, REG_GCRBLR, 0);
+	shared->hw_running = 1;
+
+	/* ring base address */
+	gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
+
+	/* ring tail address */
+	gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
+
+	/* ring length */
+	gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
+}
+
+static irqreturn_t
+pxa3xx_gcu_handle_irq(int irq, void *ctx)
+{
+	struct pxa3xx_gcu_priv *priv = ctx;
+	struct pxa3xx_gcu_shared *shared = priv->shared;
+	u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
+
+	QDUMP("-Interrupt");
+
+	if (!status)
+		return IRQ_NONE;
+
+	spin_lock(&priv->spinlock);
+	shared->num_interrupts++;
+
+	if (status & IE_EEOB) {
+		QDUMP(" [EEOB]");
+
+		flush_running(priv);
+		wake_up_all(&priv->wait_free);
+
+		if (priv->ready) {
+			run_ready(priv);
+		} else {
+			/* There is no more data prepared by the userspace.
+			 * Set hw_running = 0 and wait for the next userspace
+			 * kick-off */
+			shared->num_idle++;
+			shared->hw_running = 0;
+
+			QDUMP(" '-> Idle.");
+
+			/* set ring buffer length to zero */
+			gc_writel(priv, REG_GCRBLR, 0);
+
+			wake_up_all(&priv->wait_idle);
+		}
+
+		shared->num_done++;
+	} else {
+		QERROR(" [???]");
+		dump_whole_state(priv);
+	}
+
+	/* Clear the interrupt */
+	gc_writel(priv, REG_GCISCR, status);
+	spin_unlock(&priv->spinlock);
+
+	return IRQ_HANDLED;
+}
+
+static int
+pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
+{
+	int ret = 0;
+
+	QDUMP("Waiting for idle...");
+
+	/* Does not need to be atomic. There's a lock in user space,
+	 * but anyhow, this is just for statistics. */
+	priv->shared->num_wait_idle++;
+
+	while (priv->shared->hw_running) {
+		int num = priv->shared->num_interrupts;
+		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
+
+		ret = wait_event_interruptible_timeout(priv->wait_idle,
+					!priv->shared->hw_running, HZ*4);
+
+		if (ret < 0)
+			break;
+
+		if (ret > 0)
+			continue;
+
+		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
+		    priv->shared->num_interrupts == num) {
+			QERROR("TIMEOUT");
+			ret = -ETIMEDOUT;
+			break;
+		}
+	}
+
+	QDUMP("done");
+
+	return ret;
+}
+
+static int
+pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
+{
+	int ret = 0;
+
+	QDUMP("Waiting for free...");
+
+	/* Does not need to be atomic. There's a lock in user space,
+	 * but anyhow, this is just for statistics. */
+	priv->shared->num_wait_free++;
+
+	while (!priv->free) {
+		u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
+
+		ret = wait_event_interruptible_timeout(priv->wait_free,
+						       priv->free, HZ*4);
+
+		if (ret < 0)
+			break;
+
+		if (ret > 0)
+			continue;
+
+		if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
+			QERROR("TIMEOUT");
+			ret = -ETIMEDOUT;
+			break;
+		}
+	}
+
+	QDUMP("done");
+
+	return ret;
+}
+
+/* Misc device layer */
+
+static ssize_t
+pxa3xx_gcu_misc_write(struct file *filp, const char *buff,
+		      size_t count, loff_t *offp)
+{
+	int ret;
+	unsigned long flags;
+	struct pxa3xx_gcu_batch	*buffer;
+	struct pxa3xx_gcu_priv *priv =
+		container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+
+	int words = count / 4;
+
+	/* Does not need to be atomic. There's a lock in user space,
+	 * but anyhow, this is just for statistics. */
+	priv->shared->num_writes++;
+
+	priv->shared->num_words += words;
+
+	/* Last word reserved for batch buffer end command */
+	if (words >= PXA3XX_GCU_BATCH_WORDS)
+		return -E2BIG;
+
+	/* Wait for a free buffer */
+	if (!priv->free) {
+		ret = pxa3xx_gcu_wait_free(priv);
+		if (ret < 0)
+			return ret;
+	}
+
+	/*
+	 * Get buffer from free list
+	 */
+	spin_lock_irqsave(&priv->spinlock, flags);
+
+	buffer = priv->free;
+	priv->free = buffer->next;
+
+	spin_unlock_irqrestore(&priv->spinlock, flags);
+
+
+	/* Copy data from user into buffer */
+	ret = copy_from_user(buffer->ptr, buff, words * 4);
+	if (ret) {
+		spin_lock_irqsave(&priv->spinlock, flags);
+		buffer->next = priv->free;
+		priv->free = buffer;
+		spin_unlock_irqrestore(&priv->spinlock, flags);
+		return ret;
+	}
+
+	buffer->length = words;
+
+	/* Append batch buffer end command */
+	buffer->ptr[words] = 0x01000000;
+
+	/*
+	 * Add buffer to ready list
+	 */
+	spin_lock_irqsave(&priv->spinlock, flags);
+
+	buffer->next = NULL;
+
+	if (priv->ready) {
+		BUG_ON(priv->ready_last == NULL);
+
+		priv->ready_last->next = buffer;
+	} else
+		priv->ready = buffer;
+
+	priv->ready_last = buffer;
+
+	if (!priv->shared->hw_running)
+		run_ready(priv);
+
+	spin_unlock_irqrestore(&priv->spinlock, flags);
+
+	return words * 4;
+}
+
+
+static long
+pxa3xx_gcu_misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	unsigned long flags;
+	struct pxa3xx_gcu_priv *priv =
+		container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+
+	switch (cmd) {
+	case PXA3XX_GCU_IOCTL_RESET:
+		spin_lock_irqsave(&priv->spinlock, flags);
+		pxa3xx_gcu_reset(priv);
+		spin_unlock_irqrestore(&priv->spinlock, flags);
+		return 0;
+
+	case PXA3XX_GCU_IOCTL_WAIT_IDLE:
+		return pxa3xx_gcu_wait_idle(priv);
+	}
+
+	return -ENOSYS;
+}
+
+static int
+pxa3xx_gcu_misc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	unsigned int size = vma->vm_end - vma->vm_start;
+	struct pxa3xx_gcu_priv *priv =
+		container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
+
+	switch (vma->vm_pgoff) {
+	case 0:
+		/* hand out the shared data area */
+		if (size != SHARED_SIZE)
+			return -EINVAL;
+
+		return dma_mmap_coherent(NULL, vma,
+			priv->shared, priv->shared_phys, size);
+
+	case SHARED_SIZE >> PAGE_SHIFT:
+		/* hand out the MMIO base for direct register access
+		 * from userspace */
+		if (size != resource_size(priv->resource_mem))
+			return -EINVAL;
+
+		vma->vm_flags |= VM_IO;
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+		return io_remap_pfn_range(vma, vma->vm_start,
+				priv->resource_mem->start >> PAGE_SHIFT,
+				size, vma->vm_page_prot);
+	}
+
+	return -EINVAL;
+}
+
+
+#ifdef PXA3XX_GCU_DEBUG_TIMER
+static struct timer_list pxa3xx_gcu_debug_timer;
+
+static void pxa3xx_gcu_debug_timedout(unsigned long ptr)
+{
+	struct pxa3xx_gcu_priv *priv = (struct pxa3xx_gcu_priv *) ptr;
+
+	QERROR("Timer DUMP");
+
+	/* init the timer structure */
+	init_timer(&pxa3xx_gcu_debug_timer);
+	pxa3xx_gcu_debug_timer.function = pxa3xx_gcu_debug_timedout;
+	pxa3xx_gcu_debug_timer.data = ptr;
+	pxa3xx_gcu_debug_timer.expires = jiffies + 5*HZ; /* one second */
+
+	add_timer(&pxa3xx_gcu_debug_timer);
+}
+
+static void pxa3xx_gcu_init_debug_timer(void)
+{
+	pxa3xx_gcu_debug_timedout((unsigned long) &pxa3xx_gcu_debug_timer);
+}
+#else
+static inline void pxa3xx_gcu_init_debug_timer(void) {}
+#endif
+
+static int
+add_buffer(struct platform_device *dev,
+	   struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_batch *buffer;
+
+	buffer = kzalloc(sizeof(struct pxa3xx_gcu_batch), GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	buffer->ptr = dma_alloc_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
+					 &buffer->phys, GFP_KERNEL);
+	if (!buffer->ptr) {
+		kfree(buffer);
+		return -ENOMEM;
+	}
+
+	buffer->next = priv->free;
+
+	priv->free = buffer;
+
+	return 0;
+}
+
+static void
+free_buffers(struct platform_device *dev,
+	     struct pxa3xx_gcu_priv *priv)
+{
+	struct pxa3xx_gcu_batch *next, *buffer = priv->free;
+
+	while (buffer) {
+		next = buffer->next;
+
+		dma_free_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
+				  buffer->ptr, buffer->phys);
+
+		kfree(buffer);
+
+		buffer = next;
+	}
+
+	priv->free = NULL;
+}
+
+static int __devinit
+pxa3xx_gcu_probe(struct platform_device *dev)
+{
+	int i, ret, irq;
+	struct resource *r;
+	struct pxa3xx_gcu_priv *priv;
+
+	priv = kzalloc(sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	for (i = 0; i < 8; i++) {
+		ret = add_buffer(dev, priv);
+		if (ret) {
+			dev_err(&dev->dev, "failed to allocate DMA memory\n");
+			goto err_free_priv;
+		}
+	}
+
+	init_waitqueue_head(&priv->wait_idle);
+	init_waitqueue_head(&priv->wait_free);
+	spin_lock_init(&priv->spinlock);
+
+	/* we allocate the misc device structure as part of our own allocation,
+	 * so we can get a pointer to our priv structure later on with
+	 * container_of(). This isn't really necessary as we have a fixed minor
+	 * number anyway, but this is to avoid statics. */
+
+	priv->misc_fops.owner	= THIS_MODULE;
+	priv->misc_fops.write	= pxa3xx_gcu_misc_write;
+	priv->misc_fops.unlocked_ioctl = pxa3xx_gcu_misc_ioctl;
+	priv->misc_fops.mmap	= pxa3xx_gcu_misc_mmap;
+
+	priv->misc_dev.minor	= MISCDEV_MINOR,
+	priv->misc_dev.name	= DRV_NAME,
+	priv->misc_dev.fops	= &priv->misc_fops,
+
+	/* register misc device */
+	ret = misc_register(&priv->misc_dev);
+	if (ret < 0) {
+		dev_err(&dev->dev, "misc_register() for minor %d failed\n",
+			MISCDEV_MINOR);
+		goto err_free_priv;
+	}
+
+	/* handle IO resources */
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&dev->dev, "no I/O memory resource defined\n");
+		ret = -ENODEV;
+		goto err_misc_deregister;
+	}
+
+	if (!request_mem_region(r->start, resource_size(r), dev->name)) {
+		dev_err(&dev->dev, "failed to request I/O memory\n");
+		ret = -EBUSY;
+		goto err_misc_deregister;
+	}
+
+	priv->mmio_base = ioremap_nocache(r->start, resource_size(r));
+	if (!priv->mmio_base) {
+		dev_err(&dev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto err_free_mem_region;
+	}
+
+	/* allocate dma memory */
+	priv->shared = dma_alloc_coherent(&dev->dev, SHARED_SIZE,
+					  &priv->shared_phys, GFP_KERNEL);
+
+	if (!priv->shared) {
+		dev_err(&dev->dev, "failed to allocate DMA memory\n");
+		ret = -ENOMEM;
+		goto err_free_io;
+	}
+
+	/* enable the clock */
+	priv->clk = clk_get(&dev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&dev->dev, "failed to get clock\n");
+		ret = -ENODEV;
+		goto err_free_dma;
+	}
+
+	ret = clk_enable(priv->clk);
+	if (ret < 0) {
+		dev_err(&dev->dev, "failed to enable clock\n");
+		goto err_put_clk;
+	}
+
+	/* request the IRQ */
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "no IRQ defined\n");
+		ret = -ENODEV;
+		goto err_put_clk;
+	}
+
+	ret = request_irq(irq, pxa3xx_gcu_handle_irq,
+			  IRQF_DISABLED, DRV_NAME, priv);
+	if (ret) {
+		dev_err(&dev->dev, "request_irq failed\n");
+		ret = -EBUSY;
+		goto err_put_clk;
+	}
+
+	platform_set_drvdata(dev, priv);
+	priv->resource_mem = r;
+	pxa3xx_gcu_reset(priv);
+	pxa3xx_gcu_init_debug_timer();
+
+	dev_info(&dev->dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
+			(void *) r->start, (void *) priv->shared_phys,
+			SHARED_SIZE, irq);
+	return 0;
+
+err_put_clk:
+	clk_disable(priv->clk);
+	clk_put(priv->clk);
+
+err_free_dma:
+	dma_free_coherent(&dev->dev, SHARED_SIZE,
+			priv->shared, priv->shared_phys);
+
+err_free_io:
+	iounmap(priv->mmio_base);
+
+err_free_mem_region:
+	release_mem_region(r->start, resource_size(r));
+
+err_misc_deregister:
+	misc_deregister(&priv->misc_dev);
+
+err_free_priv:
+	platform_set_drvdata(dev, NULL);
+	free_buffers(dev, priv);
+	kfree(priv);
+	return ret;
+}
+
+static int __devexit
+pxa3xx_gcu_remove(struct platform_device *dev)
+{
+	struct pxa3xx_gcu_priv *priv = platform_get_drvdata(dev);
+	struct resource *r = priv->resource_mem;
+
+	pxa3xx_gcu_wait_idle(priv);
+
+	misc_deregister(&priv->misc_dev);
+	dma_free_coherent(&dev->dev, SHARED_SIZE,
+			priv->shared, priv->shared_phys);
+	iounmap(priv->mmio_base);
+	release_mem_region(r->start, resource_size(r));
+	platform_set_drvdata(dev, NULL);
+	clk_disable(priv->clk);
+	free_buffers(dev, priv);
+	kfree(priv);
+
+	return 0;
+}
+
+static struct platform_driver pxa3xx_gcu_driver = {
+	.probe	  = pxa3xx_gcu_probe,
+	.remove	 = __devexit_p(pxa3xx_gcu_remove),
+	.driver	 = {
+		.owner  = THIS_MODULE,
+		.name   = DRV_NAME,
+	},
+};
+
+static int __init
+pxa3xx_gcu_init(void)
+{
+	return platform_driver_register(&pxa3xx_gcu_driver);
+}
+
+static void __exit
+pxa3xx_gcu_exit(void)
+{
+	platform_driver_unregister(&pxa3xx_gcu_driver);
+}
+
+module_init(pxa3xx_gcu_init);
+module_exit(pxa3xx_gcu_exit);
+
+MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(MISCDEV_MINOR);
+MODULE_AUTHOR("Janine Kropp <nin@directfb.org>, "
+		"Denis Oliver Kropp <dok@directfb.org>, "
+		"Daniel Mack <daniel@caiaq.de>");
diff --git a/drivers/video/pxa3xx-gcu.h b/drivers/video/pxa3xx-gcu.h
new file mode 100644
index 0000000..0428ed0
--- /dev/null
+++ b/drivers/video/pxa3xx-gcu.h
@@ -0,0 +1,38 @@
+#ifndef __PXA3XX_GCU_H__
+#define __PXA3XX_GCU_H__
+
+#include <linux/types.h>
+
+/* Number of 32bit words in display list (ring buffer). */
+#define PXA3XX_GCU_BUFFER_WORDS  ((256 * 1024 - 256) / 4)
+
+/* To be increased when breaking the ABI */
+#define PXA3XX_GCU_SHARED_MAGIC  0x30000001
+
+#define PXA3XX_GCU_BATCH_WORDS   8192
+
+struct pxa3xx_gcu_shared {
+	u32            buffer[PXA3XX_GCU_BUFFER_WORDS];
+
+	bool           hw_running;
+
+	unsigned long  buffer_phys;
+
+	unsigned int   num_words;
+	unsigned int   num_writes;
+	unsigned int   num_done;
+	unsigned int   num_interrupts;
+	unsigned int   num_wait_idle;
+	unsigned int   num_wait_free;
+	unsigned int   num_idle;
+
+	u32            magic;
+};
+
+/* Initialization and synchronization.
+ * Hardware is started upon write(). */
+#define PXA3XX_GCU_IOCTL_RESET		_IO('G', 0)
+#define PXA3XX_GCU_IOCTL_WAIT_IDLE	_IO('G', 2)
+
+#endif /* __PXA3XX_GCU_H__ */
+
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index a6247fc..28b1c6c 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -410,28 +410,6 @@
  ************************************************************/
 
 /**
- *	bltbit_wait_bitset - waits for change in register value
- *	@info : framebuffer structure
- *	@bit  : value expected in register
- *	@timeout : ...
- *
- *	waits until value changes INTO bit
- */
-static u8
-bltbit_wait_bitset(struct fb_info *info, u8 bit, int timeout)
-{
-	while (!(s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit)) {
-		udelay(10);
-		if (!--timeout) {
-			dbg_blit("wait_bitset timeout\n");
-			break;
-		}
-	}
-
-	return timeout;
-}
-
-/**
  *	bltbit_wait_bitclear - waits for change in register value
  *	@info : frambuffer structure
  *	@bit  : value currently in register
@@ -454,34 +432,6 @@
 	return timeout;
 }
 
-/**
- *	bltbit_fifo_status - checks the current status of the fifo
- *	@info : framebuffer structure
- *
- *	returns number of free words in buffer
- */
-static u8
-bltbit_fifo_status(struct fb_info *info)
-{
-	u8 status;
-
-	status = s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0);
-
-	/* its empty so room for 16 words */
-	if (status & BBLT_FIFO_EMPTY)
-		return 16;
-
-	/* its full so we dont want to add */
-	if (status & BBLT_FIFO_FULL)
-		return 0;
-
-	/* its atleast half full but we can add one atleast */
-	if (status & BBLT_FIFO_NOT_FULL)
-		return 1;
-
-	return 0;
-}
-
 /*
  *	s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
  *	@info : framebuffer structure
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index f9aca9d..83ce9a04 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/map.h>
 #include <plat/regs-fb-v4.h>
@@ -1013,8 +1014,30 @@
 	return ret;
 }
 
+static int s3c_fb_open(struct fb_info *info, int user)
+{
+	struct s3c_fb_win *win = info->par;
+	struct s3c_fb *sfb = win->parent;
+
+	pm_runtime_get_sync(sfb->dev);
+
+	return 0;
+}
+
+static int s3c_fb_release(struct fb_info *info, int user)
+{
+	struct s3c_fb_win *win = info->par;
+	struct s3c_fb *sfb = win->parent;
+
+	pm_runtime_put_sync(sfb->dev);
+
+	return 0;
+}
+
 static struct fb_ops s3c_fb_ops = {
 	.owner		= THIS_MODULE,
+	.fb_open	= s3c_fb_open,
+	.fb_release	= s3c_fb_release,
 	.fb_check_var	= s3c_fb_check_var,
 	.fb_set_par	= s3c_fb_set_par,
 	.fb_blank	= s3c_fb_blank,
@@ -1322,6 +1345,8 @@
 
 	clk_enable(sfb->bus_clk);
 
+	pm_runtime_enable(sfb->dev);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "failed to find registers\n");
@@ -1360,6 +1385,9 @@
 
 	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
 
+	platform_set_drvdata(pdev, sfb);
+	pm_runtime_get_sync(sfb->dev);
+
 	/* setup gpio and output polarity controls */
 
 	pd->setup_gpio();
@@ -1400,6 +1428,7 @@
 	}
 
 	platform_set_drvdata(pdev, sfb);
+	pm_runtime_put_sync(sfb->dev);
 
 	return 0;
 
@@ -1434,6 +1463,8 @@
 	struct s3c_fb *sfb = platform_get_drvdata(pdev);
 	int win;
 
+	pm_runtime_get_sync(sfb->dev);
+
 	for (win = 0; win < S3C_FB_MAX_WIN; win++)
 		if (sfb->windows[win])
 			s3c_fb_release_win(sfb, sfb->windows[win]);
@@ -1450,12 +1481,16 @@
 
 	kfree(sfb);
 
+	pm_runtime_put_sync(sfb->dev);
+	pm_runtime_disable(sfb->dev);
+
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
+static int s3c_fb_suspend(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct s3c_fb *sfb = platform_get_drvdata(pdev);
 	struct s3c_fb_win *win;
 	int win_no;
@@ -1473,8 +1508,9 @@
 	return 0;
 }
 
-static int s3c_fb_resume(struct platform_device *pdev)
+static int s3c_fb_resume(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct s3c_fb *sfb = platform_get_drvdata(pdev);
 	struct s3c_fb_platdata *pd = sfb->pdata;
 	struct s3c_fb_win *win;
@@ -1509,9 +1545,70 @@
 
 	return 0;
 }
+
+int s3c_fb_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct s3c_fb *sfb = platform_get_drvdata(pdev);
+	struct s3c_fb_win *win;
+	int win_no;
+
+	for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
+		win = sfb->windows[win_no];
+		if (!win)
+			continue;
+
+		/* use the blank function to push into power-down */
+		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
+	}
+
+	clk_disable(sfb->bus_clk);
+	return 0;
+}
+
+int s3c_fb_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct s3c_fb *sfb = platform_get_drvdata(pdev);
+	struct s3c_fb_platdata *pd = sfb->pdata;
+	struct s3c_fb_win *win;
+	int win_no;
+
+	clk_enable(sfb->bus_clk);
+
+	/* setup registers */
+	writel(pd->vidcon1, sfb->regs + VIDCON1);
+
+	/* zero all windows before we do anything */
+	for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
+		s3c_fb_clear_win(sfb, win_no);
+
+	for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
+		void __iomem *regs = sfb->regs + sfb->variant.keycon;
+
+		regs += (win_no * 8);
+		writel(0xffffff, regs + WKEYCON0);
+		writel(0xffffff, regs + WKEYCON1);
+	}
+
+	/* restore framebuffers */
+	for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
+		win = sfb->windows[win_no];
+		if (!win)
+			continue;
+
+		dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
+		s3c_fb_set_par(win->fbinfo);
+	}
+
+	return 0;
+}
+
 #else
 #define s3c_fb_suspend NULL
 #define s3c_fb_resume  NULL
+#define s3c_fb_runtime_suspend NULL
+#define s3c_fb_runtime_resume NULL
 #endif
 
 
@@ -1710,15 +1807,21 @@
 };
 MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
 
+static const struct dev_pm_ops s3cfb_pm_ops = {
+	.suspend	= s3c_fb_suspend,
+	.resume		= s3c_fb_resume,
+	.runtime_suspend	= s3c_fb_runtime_suspend,
+	.runtime_resume		= s3c_fb_runtime_resume,
+};
+
 static struct platform_driver s3c_fb_driver = {
 	.probe		= s3c_fb_probe,
 	.remove		= __devexit_p(s3c_fb_remove),
-	.suspend	= s3c_fb_suspend,
-	.resume		= s3c_fb_resume,
 	.id_table	= s3c_fb_driver_ids,
 	.driver		= {
 		.name	= "s3c-fb",
 		.owner	= THIS_MODULE,
+		.pm	= &s3cfb_pm_ops,
 	},
 };
 
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 3f3d43103..24640c8 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -21,18 +22,40 @@
 #include <video/sh_mipi_dsi.h>
 #include <video/sh_mobile_lcdc.h>
 
-#define CMTSRTCTR	0x80d0
-#define CMTSRTREQ	0x8070
-
+#define SYSCTRL		0x0000
+#define SYSCONF		0x0004
+#define TIMSET		0x0008
+#define RESREQSET0	0x0018
+#define RESREQSET1	0x001c
+#define HSTTOVSET	0x0020
+#define LPRTOVSET	0x0024
+#define TATOVSET	0x0028
+#define PRTOVSET	0x002c
+#define DSICTRL		0x0030
 #define DSIINTE		0x0060
+#define PHYCTRL		0x0070
+
+/* relative to linkbase */
+#define DTCTR		0x0000
+#define VMCTR1		0x0020
+#define VMCTR2		0x0024
+#define VMLEN1		0x0028
+#define CMTSRTREQ	0x0070
+#define CMTSRTCTR	0x00d0
 
 /* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
 #define MAX_SH_MIPI_DSI 2
 
 struct sh_mipi {
 	void __iomem	*base;
+	void __iomem	*linkbase;
 	struct clk	*dsit_clk;
 	struct clk	*dsip_clk;
+	struct device	*dev;
+
+	void	*next_board_data;
+	void	(*next_display_on)(void *board_data, struct fb_info *info);
+	void	(*next_display_off)(void *board_data);
 };
 
 static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
@@ -55,10 +78,10 @@
 	int cnt = 100;
 
 	/* transmit a short packet to LCD panel */
-	iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */
-	iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */
+	iowrite32(1 | data, mipi->linkbase + CMTSRTCTR);
+	iowrite32(1, mipi->linkbase + CMTSRTREQ);
 
-	while ((ioread32(mipi->base + 0x8070) & 1) && --cnt)
+	while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt)
 		udelay(1);
 
 	return cnt ? 0 : -ETIMEDOUT;
@@ -90,7 +113,7 @@
 	 * enable LCDC data tx, transition to LPS after completion of each HS
 	 * packet
 	 */
-	iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */
+	iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR);
 }
 
 static void sh_mipi_shutdown(struct platform_device *pdev)
@@ -104,14 +127,22 @@
 {
 	struct sh_mipi *mipi = arg;
 
+	pm_runtime_get_sync(mipi->dev);
 	sh_mipi_dsi_enable(mipi, true);
+
+	if (mipi->next_display_on)
+		mipi->next_display_on(mipi->next_board_data, info);
 }
 
 static void mipi_display_off(void *arg)
 {
 	struct sh_mipi *mipi = arg;
 
+	if (mipi->next_display_off)
+		mipi->next_display_off(mipi->next_board_data);
+
 	sh_mipi_dsi_enable(mipi, false);
+	pm_runtime_put(mipi->dev);
 }
 
 static int __init sh_mipi_setup(struct sh_mipi *mipi,
@@ -119,8 +150,7 @@
 {
 	void __iomem *base = mipi->base;
 	struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
-	u32 pctype, datatype, pixfmt;
-	u32 linelength;
+	u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000;
 	bool yuv;
 
 	/*
@@ -223,10 +253,10 @@
 		return -EINVAL;
 
 	/* reset DSI link */
-	iowrite32(0x00000001, base); /* SYSCTRL */
+	iowrite32(0x00000001, base + SYSCTRL);
 	/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
 	udelay(50);
-	iowrite32(0x00000000, base); /* SYSCTRL */
+	iowrite32(0x00000000, base + SYSCTRL);
 
 	/* setup DSI link */
 
@@ -238,7 +268,7 @@
 	 *	ECC check enable
 	 * additionally enable first two lanes
 	 */
-	iowrite32(0x00003703, base + 0x04); /* SYSCONF */
+	iowrite32(0x00003703, base + SYSCONF);
 	/*
 	 * T_wakeup = 0x7000
 	 * T_hs-trail = 3
@@ -246,28 +276,28 @@
 	 * T_clk-trail = 3
 	 * T_clk-prepare = 2
 	 */
-	iowrite32(0x70003332, base + 0x08); /* TIMSET */
+	iowrite32(0x70003332, base + TIMSET);
 	/* no responses requested */
-	iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */
+	iowrite32(0x00000000, base + RESREQSET0);
 	/* request response to packets of type 0x28 */
-	iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */
+	iowrite32(0x00000100, base + RESREQSET1);
 	/* High-speed transmission timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */
+	iowrite32(0x0fffffff, base + HSTTOVSET);
 	/* LP reception timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */
+	iowrite32(0x0fffffff, base + LPRTOVSET);
 	/* Turn-around timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */
+	iowrite32(0x0fffffff, base + TATOVSET);
 	/* Peripheral reset timeout, default 0xffffffff */
-	iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */
+	iowrite32(0x0fffffff, base + PRTOVSET);
 	/* Enable timeout counters */
-	iowrite32(0x00000f00, base + 0x30); /* DSICTRL */
+	iowrite32(0x00000f00, base + DSICTRL);
 	/* Interrupts not used, disable all */
 	iowrite32(0, base + DSIINTE);
 	/* DSI-Tx bias on */
-	iowrite32(0x00000001, base + 0x70); /* PHYCTRL */
+	iowrite32(0x00000001, base + PHYCTRL);
 	udelay(200);
 	/* Deassert resets, power on, set multiplier */
-	iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */
+	iowrite32(0x03070b01, base + PHYCTRL);
 
 	/* setup l-bridge */
 
@@ -275,20 +305,28 @@
 	 * Enable transmission of all packets,
 	 * transmit LPS after each HS packet completion
 	 */
-	iowrite32(0x00000006, base + 0x8000); /* DTCTR */
+	iowrite32(0x00000006, mipi->linkbase + DTCTR);
 	/* VSYNC width = 2 (<< 17) */
-	iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */
+	iowrite32((ch->lcd_cfg[0].vsync_len << pdata->vsynw_offset) |
+		  (pdata->clksrc << 16) | (pctype << 12) | datatype,
+		  mipi->linkbase + VMCTR1);
+
 	/*
 	 * Non-burst mode with sync pulses: VSE and HSE are output,
 	 * HSA period allowed, no commands in LP
 	 */
-	iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
+	if (pdata->flags & SH_MIPI_DSI_HSABM)
+		vmctr2 |= 0x20;
+	if (pdata->flags & SH_MIPI_DSI_HSPBM)
+		vmctr2 |= 0x10;
+	iowrite32(vmctr2, mipi->linkbase + VMCTR2);
+
 	/*
 	 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
 	 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
-	 * (unused, since VMCTR2[HSABM] = 0)
+	 * (unused if VMCTR2[HSABM] = 0)
 	 */
-	iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
+	iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1);
 
 	msleep(5);
 
@@ -321,11 +359,12 @@
 	struct sh_mipi *mipi;
 	struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	unsigned long rate, f_current;
 	int idx = pdev->id, ret;
 	char dsip_clk[] = "dsi.p_clk";
 
-	if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
+	if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
 		return -ENODEV;
 
 	mutex_lock(&array_lock);
@@ -356,6 +395,20 @@
 		goto emap;
 	}
 
+	if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) {
+		dev_err(&pdev->dev, "MIPI register region 2 already claimed\n");
+		ret = -EBUSY;
+		goto ereqreg2;
+	}
+
+	mipi->linkbase = ioremap(res2->start, resource_size(res2));
+	if (!mipi->linkbase) {
+		ret = -ENOMEM;
+		goto emap2;
+	}
+
+	mipi->dev = &pdev->dev;
+
 	mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
 	if (IS_ERR(mipi->dsit_clk)) {
 		ret = PTR_ERR(mipi->dsit_clk);
@@ -405,6 +458,9 @@
 
 	mipi_dsi[idx] = mipi;
 
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_resume(&pdev->dev);
+
 	ret = sh_mipi_setup(mipi, pdata);
 	if (ret < 0)
 		goto emipisetup;
@@ -412,15 +468,22 @@
 	mutex_unlock(&array_lock);
 	platform_set_drvdata(pdev, mipi);
 
+	/* Save original LCDC callbacks */
+	mipi->next_board_data = pdata->lcd_chan->board_cfg.board_data;
+	mipi->next_display_on = pdata->lcd_chan->board_cfg.display_on;
+	mipi->next_display_off = pdata->lcd_chan->board_cfg.display_off;
+
 	/* Set up LCDC callbacks */
 	pdata->lcd_chan->board_cfg.board_data = mipi;
 	pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
 	pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
+	pdata->lcd_chan->board_cfg.owner = THIS_MODULE;
 
 	return 0;
 
 emipisetup:
 	mipi_dsi[idx] = NULL;
+	pm_runtime_disable(&pdev->dev);
 	clk_disable(mipi->dsip_clk);
 eclkpon:
 	clk_disable(mipi->dsit_clk);
@@ -431,6 +494,10 @@
 esettrate:
 	clk_put(mipi->dsit_clk);
 eclktget:
+	iounmap(mipi->linkbase);
+emap2:
+	release_mem_region(res2->start, resource_size(res2));
+ereqreg2:
 	iounmap(mipi->base);
 emap:
 	release_mem_region(res->start, resource_size(res));
@@ -447,6 +514,7 @@
 {
 	struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	struct sh_mipi *mipi = platform_get_drvdata(pdev);
 	int i, ret;
 
@@ -467,14 +535,19 @@
 	if (ret < 0)
 		return ret;
 
+	pdata->lcd_chan->board_cfg.owner = NULL;
 	pdata->lcd_chan->board_cfg.display_on = NULL;
 	pdata->lcd_chan->board_cfg.display_off = NULL;
 	pdata->lcd_chan->board_cfg.board_data = NULL;
 
+	pm_runtime_disable(&pdev->dev);
 	clk_disable(mipi->dsip_clk);
 	clk_disable(mipi->dsit_clk);
 	clk_put(mipi->dsit_clk);
 	clk_put(mipi->dsip_clk);
+	iounmap(mipi->linkbase);
+	if (res2)
+		release_mem_region(res2->start, resource_size(res2));
 	iounmap(mipi->base);
 	if (res)
 		release_mem_region(res->start, resource_size(res));
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index d7df103..8c59cc8 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -209,7 +209,11 @@
 struct sh_hdmi {
 	void __iomem *base;
 	enum hotplug_state hp_state;	/* hot-plug status */
-	bool preprogrammed_mode;	/* use a pre-programmed VIC or the external mode */
+	u8 preprogrammed_vic;		/* use a pre-programmed VIC or
+					   the external mode */
+	u8 edid_block_addr;
+	u8 edid_segment_nr;
+	u8 edid_blocks;
 	struct clk *hdmi_clk;
 	struct device *dev;
 	struct fb_info *info;
@@ -342,7 +346,7 @@
 	hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
 
 	/* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
-	if (!hdmi->preprogrammed_mode)
+	if (!hdmi->preprogrammed_vic)
 		hdmi_write(hdmi, sync | 1 | (voffset << 4),
 			   HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
 }
@@ -466,7 +470,18 @@
  */
 static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
 {
-	if (hdmi->var.yres > 480) {
+	if (hdmi->var.pixclock < 10000) {
+		/* for 1080p8bit 148MHz */
+		hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
+		hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
+		hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
+		hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
+		hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
+		hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
+		hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
+		hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
+	} else if (hdmi->var.pixclock < 30000) {
 		/* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
 		/*
 		 * [1:0]	Speed_A
@@ -565,13 +580,11 @@
 	hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
 
 	/*
-	 * VIC = 1280 x 720p: ignored if external config is used
-	 * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode
+	 * VIC should be ignored if external config is used, so, we could just use 0,
+	 * but play safe and use a valid value in any case just in case
 	 */
-	if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920)
-		vic = 16;
-	else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
-		vic = 2;
+	if (hdmi->preprogrammed_vic)
+		vic = hdmi->preprogrammed_vic;
 	else
 		vic = 4;
 	hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
@@ -685,11 +698,21 @@
 }
 
 static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
-					const struct fb_videomode *mode)
+		const struct fb_videomode *mode,
+		unsigned long *hdmi_rate, unsigned long *parent_rate)
 {
-	long target = PICOS2KHZ(mode->pixclock) * 1000,
-		rate = clk_round_rate(hdmi->hdmi_clk, target);
-	unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
+	unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
+	struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
+
+	*hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
+	if ((long)*hdmi_rate < 0)
+		*hdmi_rate = clk_get_rate(hdmi->hdmi_clk);
+
+	rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX;
+	if (rate_error && pdata->clk_optimize_parent)
+		rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate);
+	else if (clk_get_parent(hdmi->hdmi_clk))
+		*parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk));
 
 	dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
 		mode->left_margin, mode->xres,
@@ -697,14 +720,15 @@
 		mode->upper_margin, mode->yres,
 		mode->lower_margin, mode->vsync_len);
 
-	dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target,
-		 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
-		 mode->refresh);
+	dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target,
+		rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
+		mode->refresh, *parent_rate);
 
 	return rate_error;
 }
 
-static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
+static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
+			     unsigned long *parent_rate)
 {
 	struct fb_var_screeninfo tmpvar;
 	struct fb_var_screeninfo *var = &tmpvar;
@@ -735,7 +759,38 @@
 	printk(KERN_CONT "\n");
 #endif
 
-	fb_edid_to_monspecs(edid, &hdmi->monspec);
+	if (!hdmi->edid_blocks) {
+		fb_edid_to_monspecs(edid, &hdmi->monspec);
+		hdmi->edid_blocks = edid[126] + 1;
+
+		dev_dbg(hdmi->dev, "%d main modes, %d extension blocks\n",
+			hdmi->monspec.modedb_len, hdmi->edid_blocks - 1);
+	} else {
+		dev_dbg(hdmi->dev, "Extension %u detected, DTD start %u\n",
+			edid[0], edid[2]);
+		fb_edid_add_monspecs(edid, &hdmi->monspec);
+	}
+
+	if (hdmi->edid_blocks > hdmi->edid_segment_nr * 2 +
+	    (hdmi->edid_block_addr >> 7) + 1) {
+		/* More blocks to read */
+		if (hdmi->edid_block_addr) {
+			hdmi->edid_block_addr = 0;
+			hdmi->edid_segment_nr++;
+		} else {
+			hdmi->edid_block_addr = 0x80;
+		}
+		/* Set EDID word address  */
+		hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
+		/* Enable EDID interrupt */
+		hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
+		/* Set EDID segment pointer - starts reading EDID */
+		hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
+		return -EAGAIN;
+	}
+
+	/* All E-EDID blocks ready */
+	dev_dbg(hdmi->dev, "%d main and extended modes\n", hdmi->monspec.modedb_len);
 
 	fb_get_options("sh_mobile_lcdc", &forced);
 	if (forced && *forced) {
@@ -754,11 +809,14 @@
 	for (i = 0, mode = hdmi->monspec.modedb;
 	     f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
 	     i++, mode++) {
-		unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode);
+		unsigned long rate_error;
 
 		/* No interest in unmatching modes */
 		if (f_width != mode->xres || f_height != mode->yres)
 			continue;
+
+		rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
+
 		if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
 			/*
 			 * Exact match if either the refresh rate matches or it
@@ -787,6 +845,9 @@
 		found_rate_error = rate_error;
 	}
 
+	hdmi->var.width = hdmi->monspec.max_x * 10;
+	hdmi->var.height = hdmi->monspec.max_y * 10;
+
 	/*
 	 * TODO 1: if no ->info is present, postpone running the config until
 	 * after ->info first gets registered.
@@ -802,7 +863,7 @@
 
 		if (modelist) {
 			found = &modelist->mode;
-			found_rate_error = sh_hdmi_rate_error(hdmi, found);
+			found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, parent_rate);
 		}
 	}
 
@@ -810,16 +871,27 @@
 	if (!found)
 		return -ENXIO;
 
-	dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
-		 modelist ? "default" : "EDID", found->xres, found->yres,
-		 found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
-
-	if ((found->xres == 720 && found->yres == 480) ||
-	    (found->xres == 1280 && found->yres == 720) ||
-	    (found->xres == 1920 && found->yres == 1080))
-		hdmi->preprogrammed_mode = true;
+	if (found->xres == 640 && found->yres == 480 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 1;
+	else if (found->xres == 720 && found->yres == 480 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 2;
+	else if (found->xres == 720 && found->yres == 576 && found->refresh == 50)
+		hdmi->preprogrammed_vic = 17;
+	else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 4;
+	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24)
+		hdmi->preprogrammed_vic = 32;
+	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50)
+		hdmi->preprogrammed_vic = 31;
+	else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60)
+		hdmi->preprogrammed_vic = 16;
 	else
-		hdmi->preprogrammed_mode = false;
+		hdmi->preprogrammed_vic = 0;
+
+	dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
+		modelist ? "default" : "EDID", hdmi->preprogrammed_vic ? "VIC" : "external",
+		found->xres, found->yres, found->refresh,
+		PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
 
 	fb_videomode_to_var(&hdmi->var, found);
 	sh_hdmi_external_video_param(hdmi);
@@ -868,32 +940,34 @@
 		/* Check, if hot plug & MSENS pin status are both high */
 		if ((msens & 0xC0) == 0xC0) {
 			/* Display plug in */
+			hdmi->edid_segment_nr = 0;
+			hdmi->edid_block_addr = 0;
+			hdmi->edid_blocks = 0;
 			hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
 
 			/* Set EDID word address  */
 			hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
-			/* Set EDID segment pointer */
-			hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
 			/* Enable EDID interrupt */
 			hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
+			/* Set EDID segment pointer - starts reading EDID */
+			hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
 		} else if (!(status1 & 0x80)) {
 			/* Display unplug, beware multiple interrupts */
-			if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED)
+			if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) {
+				hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
 				schedule_delayed_work(&hdmi->edid_work, 0);
-
-			hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
+			}
 			/* display_off will switch back to mode_a */
 		}
 	} else if (status1 & 2) {
 		/* EDID error interrupt: retry */
 		/* Set EDID word address  */
-		hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
+		hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
 		/* Set EDID segment pointer */
-		hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
+		hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
 	} else if (status1 & 4) {
 		/* Disable EDID interrupt */
 		hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
-		hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
 		schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
 	}
 
@@ -960,8 +1034,12 @@
 	dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
 		mode1.xres, mode1.yres, mode2.xres, mode2.yres);
 
-	if (fb_mode_is_equal(&mode1, &mode2))
+	if (fb_mode_is_equal(&mode1, &mode2)) {
+		/* It can be a different monitor with an equal video-mode */
+		old_var->width = new_var->width;
+		old_var->height = new_var->height;
 		return false;
+	}
 
 	dev_dbg(info->dev, "Switching %u -> %u lines\n",
 		mode1.yres, mode2.yres);
@@ -972,39 +1050,37 @@
 
 /**
  * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
- * @hdmi:	driver context
- * @pixclock:	pixel clock period in picoseconds
- * return:	configured positive rate if successful
- *		0 if couldn't set the rate, but managed to enable the clock
- *		negative error, if couldn't enable the clock
+ * @hdmi:		driver context
+ * @hdmi_rate:		HDMI clock frequency in Hz
+ * @parent_rate:	if != 0 - set parent clock rate for optimal precision
+ * return:		configured positive rate if successful
+ *			0 if couldn't set the rate, but managed to enable the
+ *			clock, negative error, if couldn't enable the clock
  */
-static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock)
+static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
+				  unsigned long parent_rate)
 {
-	long rate;
 	int ret;
 
-	rate = PICOS2KHZ(pixclock) * 1000;
-	rate = clk_round_rate(hdmi->hdmi_clk, rate);
-	if (rate > 0) {
-		ret = clk_set_rate(hdmi->hdmi_clk, rate);
+	if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) {
+		ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate);
 		if (ret < 0) {
-			dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret);
-			rate = 0;
+			dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret);
+			hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate);
 		} else {
-			dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate);
+			dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate);
 		}
-	} else {
-		rate = 0;
-		dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
 	}
 
-	ret = clk_enable(hdmi->hdmi_clk);
+	ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate);
 	if (ret < 0) {
-		dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
-		return ret;
+		dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret);
+		hdmi_rate = 0;
+	} else {
+		dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate);
 	}
 
-	return rate;
+	return hdmi_rate;
 }
 
 /* Hotplug interrupt occurred, read EDID */
@@ -1023,17 +1099,20 @@
 
 	mutex_lock(&hdmi->mutex);
 
-	if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
+	if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
+		unsigned long parent_rate = 0, hdmi_rate;
+
 		/* A device has been plugged in */
 		pm_runtime_get_sync(hdmi->dev);
 
-		ret = sh_hdmi_read_edid(hdmi);
+		ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
 		if (ret < 0)
 			goto out;
 
+		hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
+
 		/* Reconfigure the clock */
-		clk_disable(hdmi->hdmi_clk);
-		ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
+		ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
 		if (ret < 0)
 			goto out;
 
@@ -1057,8 +1136,11 @@
 			 * on, if we run a resume here, the logo disappears
 			 */
 			if (lock_fb_info(hdmi->info)) {
-				sh_hdmi_display_on(hdmi, hdmi->info);
-				unlock_fb_info(hdmi->info);
+				struct fb_info *info = hdmi->info;
+				info->var.width = hdmi->var.width;
+				info->var.height = hdmi->var.height;
+				sh_hdmi_display_on(hdmi, info);
+				unlock_fb_info(info);
 			}
 		} else {
 			/* New monitor or have to wake up */
@@ -1085,7 +1167,7 @@
 	}
 
 out:
-	if (ret < 0)
+	if (ret < 0 && ret != -EAGAIN)
 		hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
 	mutex_unlock(&hdmi->mutex);
 
@@ -1166,13 +1248,22 @@
 		goto egetclk;
 	}
 
-	/* Some arbitrary relaxed pixclock just to get things started */
-	rate = sh_hdmi_clk_configure(hdmi, 37037);
+	/* An arbitrary relaxed pixclock just to get things started: from standard 480p */
+	rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
+	if (rate > 0)
+		rate = sh_hdmi_clk_configure(hdmi, rate, 0);
+
 	if (rate < 0) {
 		ret = rate;
 		goto erate;
 	}
 
+	ret = clk_enable(hdmi->hdmi_clk);
+	if (ret < 0) {
+		dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
+		goto erate;
+	}
+
 	dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
 
 	if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
@@ -1190,10 +1281,6 @@
 
 	platform_set_drvdata(pdev, hdmi);
 
-	/* Product and revision IDs are 0 in sh-mobile version */
-	dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
-		 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
-
 	/* Set up LCDC callbacks */
 	board_cfg = &pdata->lcd_chan->board_cfg;
 	board_cfg->owner = THIS_MODULE;
@@ -1206,6 +1293,10 @@
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_resume(&pdev->dev);
 
+	/* Product and revision IDs are 0 in sh-mobile version */
+	dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
+		 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
+
 	ret = request_irq(irq, sh_hdmi_hotplug, 0,
 			  dev_name(&pdev->dev), hdmi);
 	if (ret < 0) {
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index b02d97a..bd4840a 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -54,8 +54,8 @@
 };
 #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
 
-#define DEFAULT_XRES 1280
-#define DEFAULT_YRES 1024
+#define MAX_XRES 1920
+#define MAX_YRES 1080
 
 static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
 	[LDDCKPAT1R] = 0x400,
@@ -139,6 +139,7 @@
 	struct notifier_block notifier;
 	unsigned long saved_shared_regs[NR_SHARED_REGS];
 	int started;
+	int forced_bpp; /* 2 channel LCDC must share bpp setting */
 };
 
 static bool banked(int reg_nr)
@@ -461,13 +462,18 @@
 	struct sh_mobile_lcdc_chan *ch;
 	struct sh_mobile_lcdc_board_cfg	*board_cfg;
 	unsigned long tmp;
+	int bpp = 0;
 	int k, m;
 	int ret = 0;
 
 	/* enable clocks before accessing the hardware */
-	for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
-		if (priv->ch[k].enabled)
+	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+		if (priv->ch[k].enabled) {
 			sh_mobile_lcdc_clk_on(priv);
+			if (!bpp)
+				bpp = priv->ch[k].info->var.bits_per_pixel;
+		}
+	}
 
 	/* reset */
 	lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
@@ -535,7 +541,17 @@
 	}
 
 	/* word and long word swap */
-	lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
+	switch (bpp) {
+	case 16:
+		lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
+		break;
+	case 24:
+		lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 7);
+		break;
+	case 32:
+		lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 4);
+		break;
+	}
 
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		ch = &priv->ch[k];
@@ -546,7 +562,16 @@
 		/* set bpp format in PKF[4:0] */
 		tmp = lcdc_read_chan(ch, LDDFR);
 		tmp &= ~0x0001001f;
-		tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
+		switch (ch->info->var.bits_per_pixel) {
+		case 16:
+			tmp |= 0x03;
+			break;
+		case 24:
+			tmp |= 0x0b;
+			break;
+		case 32:
+			break;
+		}
 		lcdc_write_chan(ch, LDDFR, tmp);
 
 		/* point out our frame buffer */
@@ -913,25 +938,30 @@
 static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct sh_mobile_lcdc_chan *ch = info->par;
+	struct sh_mobile_lcdc_priv *p = ch->lcdc;
 
-	if (var->xres < 160 || var->xres > 1920 ||
-	    var->yres < 120 || var->yres > 1080 ||
-	    var->left_margin < 32 || var->left_margin > 320 ||
-	    var->right_margin < 12 || var->right_margin > 240 ||
-	    var->upper_margin < 12 || var->upper_margin > 120 ||
-	    var->lower_margin < 1 || var->lower_margin > 64 ||
-	    var->hsync_len < 32 || var->hsync_len > 240 ||
-	    var->vsync_len < 2 || var->vsync_len > 64 ||
-	    var->pixclock < 6000 || var->pixclock > 40000 ||
+	if (var->xres > MAX_XRES || var->yres > MAX_YRES ||
 	    var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
-		dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n",
-			 var->xres, var->yres,
-			 var->left_margin, var->right_margin,
-			 var->upper_margin, var->lower_margin,
-			 var->hsync_len, var->vsync_len,
-			 var->pixclock);
+		dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n",
+			 var->left_margin, var->xres, var->right_margin, var->hsync_len,
+			 var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
+			 PICOS2KHZ(var->pixclock));
 		return -EINVAL;
 	}
+
+	/* only accept the forced_bpp for dual channel configurations */
+	if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel)
+		return -EINVAL;
+
+	switch (var->bits_per_pixel) {
+	case 16: /* PKF[4:0] = 00011 - RGB 565 */
+	case 24: /* PKF[4:0] = 01011 - RGB 888 */
+	case 32: /* PKF[4:0] = 00000 - RGBA 888 */
+		break;
+	default:
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -964,19 +994,27 @@
 		var->transp.length = 0;
 		break;
 
-	case 32: /* PKF[4:0] = 00000 - RGB 888
-		  * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
-		  * this may be because LDDDSR has word swap enabled..
-		  */
-		var->red.offset = 0;
+	case 24: /* PKF[4:0] = 01011 - RGB 888 */
+		var->red.offset = 16;
 		var->red.length = 8;
-		var->green.offset = 24;
+		var->green.offset = 8;
 		var->green.length = 8;
-		var->blue.offset = 16;
+		var->blue.offset = 0;
 		var->blue.length = 8;
 		var->transp.offset = 0;
 		var->transp.length = 0;
 		break;
+
+	case 32: /* PKF[4:0] = 00000 - RGBA 888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1180,6 +1218,10 @@
 		goto err1;
 	}
 
+	/* for dual channel LCDC (MAIN + SUB) force shared bpp setting */
+	if (j == 2)
+		priv->forced_bpp = pdata->ch[0].bpp;
+
 	priv->base = ioremap_nocache(res->start, resource_size(res));
 	if (!priv->base)
 		goto err1;
@@ -1226,7 +1268,7 @@
 		}
 
 		if (!mode)
-			max_size = DEFAULT_XRES * DEFAULT_YRES;
+			max_size = MAX_XRES * MAX_YRES;
 		else if (max_cfg)
 			dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
 				max_cfg->xres, max_cfg->yres);
@@ -1238,12 +1280,14 @@
 			mode = &default_720p;
 			num_cfg = 1;
 		} else {
-			num_cfg = ch->cfg.num_cfg;
+			num_cfg = cfg->num_cfg;
 		}
 
 		fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
 
 		fb_videomode_to_var(var, mode);
+		var->width = cfg->lcd_size_cfg.width;
+		var->height = cfg->lcd_size_cfg.height;
 		/* Default Y virtual resolution is 2x panel size */
 		var->yres_virtual = var->yres * 2;
 		var->activate = FB_ACTIVATE_NOW;
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index 31137ad..66de8323 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -56,10 +56,6 @@
  * Used by permission.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "init.h"
 
 #ifdef CONFIG_FB_SIS_300
@@ -880,59 +876,59 @@
 /*********************************************/
 
 void
-SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data)
+SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
 {
-	outb((u8)index, port);
-	outb((u8)data, port + 1);
+	outb(index, port);
+	outb(data, port + 1);
 }
 
 void
-SiS_SetRegByte(SISIOADDRESS port, unsigned short data)
+SiS_SetRegByte(SISIOADDRESS port, u8 data)
 {
-	outb((u8)data, port);
+	outb(data, port);
 }
 
 void
-SiS_SetRegShort(SISIOADDRESS port, unsigned short data)
+SiS_SetRegShort(SISIOADDRESS port, u16 data)
 {
-	outw((u16)data, port);
+	outw(data, port);
 }
 
 void
-SiS_SetRegLong(SISIOADDRESS port, unsigned int data)
+SiS_SetRegLong(SISIOADDRESS port, u32 data)
 {
-	outl((u32)data, port);
+	outl(data, port);
 }
 
-unsigned char
-SiS_GetReg(SISIOADDRESS port, unsigned short index)
+u8
+SiS_GetReg(SISIOADDRESS port, u8 index)
 {
-	outb((u8)index, port);
+	outb(index, port);
 	return inb(port + 1);
 }
 
-unsigned char
+u8
 SiS_GetRegByte(SISIOADDRESS port)
 {
 	return inb(port);
 }
 
-unsigned short
+u16
 SiS_GetRegShort(SISIOADDRESS port)
 {
 	return inw(port);
 }
 
-unsigned int
+u32
 SiS_GetRegLong(SISIOADDRESS port)
 {
 	return inl(port);
 }
 
 void
-SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR)
+SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
 {
-   unsigned short temp;
+   u8 temp;
 
    temp = SiS_GetReg(Port, Index);
    temp = (temp & (DataAND)) | DataOR;
@@ -940,9 +936,9 @@
 }
 
 void
-SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
+SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
 {
-   unsigned short temp;
+   u8 temp;
 
    temp = SiS_GetReg(Port, Index);
    temp &= DataAND;
@@ -950,9 +946,9 @@
 }
 
 void
-SiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR)
+SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
 {
-   unsigned short temp;
+   u8 temp;
 
    temp = SiS_GetReg(Port, Index);
    temp |= DataOR;
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index ee8ed3c..aff7384 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -1516,19 +1516,6 @@
 unsigned short	SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
 				int VDisplay, int Depth, unsigned int VBFlags2);
 
-void		SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data);
-void		SiS_SetRegByte(SISIOADDRESS port, unsigned short data);
-void		SiS_SetRegShort(SISIOADDRESS port, unsigned short data);
-void		SiS_SetRegLong(SISIOADDRESS port, unsigned int data);
-unsigned char	SiS_GetReg(SISIOADDRESS port, unsigned short index);
-unsigned char	SiS_GetRegByte(SISIOADDRESS port);
-unsigned short	SiS_GetRegShort(SISIOADDRESS port);
-unsigned int	SiS_GetRegLong(SISIOADDRESS port);
-void		SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
-				unsigned short DataOR);
-void		SiS_SetRegAND(SISIOADDRESS Port,unsigned short Index, unsigned short DataAND);
-void		SiS_SetRegOR(SISIOADDRESS Port,unsigned short Index, unsigned short DataOR);
-
 void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
 void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
 void		SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 9fa66fd..a89e3ca 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -57,10 +57,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #if 1
 #define SET_EMI		/* 302LV/ELV: Set EMI values */
 #endif
@@ -5856,7 +5852,7 @@
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
      temp = ((tempax & 0xFF00) >> 8) << 3;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
 
      tempax = SiS_Pr->SiS_VDE;				 	/* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
      if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
@@ -5870,7 +5866,7 @@
      temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
      temp = ((tempeax & 0x01000000) >> 24) << 7;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
 
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index e1fd31d..2112d6d 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -428,17 +428,6 @@
 static void		SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
 #endif
 
-extern void		SiS_SetReg(SISIOADDRESS, unsigned short, unsigned short);
-extern void		SiS_SetRegByte(SISIOADDRESS, unsigned short);
-extern void		SiS_SetRegShort(SISIOADDRESS, unsigned short);
-extern void		SiS_SetRegLong(SISIOADDRESS, unsigned int);
-extern unsigned char	SiS_GetReg(SISIOADDRESS, unsigned short);
-extern unsigned char	SiS_GetRegByte(SISIOADDRESS);
-extern unsigned short	SiS_GetRegShort(SISIOADDRESS);
-extern unsigned int	SiS_GetRegLong(SISIOADDRESS);
-extern void		SiS_SetRegANDOR(SISIOADDRESS, unsigned short, unsigned short, unsigned short);
-extern void		SiS_SetRegOR(SISIOADDRESS, unsigned short, unsigned short);
-extern void		SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
 extern void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
 extern void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
 extern bool		SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index 80d89d3..eac7a01 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -307,58 +307,19 @@
 #define VB2_LCDOVER1600BRIDGE	(VB2_307T  | VB2_307LV)
 #define VB2_RAMDAC202MHZBRIDGE	(VB2_301C  | VB2_307T)
 
-/* I/O port access macros */
-#define inSISREG(base)		inb(base)
+/* I/O port access functions */
 
-#define outSISREG(base,val)	outb(val,base)
-
-#define orSISREG(base,val)      			\
-		do {					\
-			u8 __Temp = inSISREG(base); 	\
-			outSISREG(base, __Temp | (val));\
-		} while (0)
-
-#define andSISREG(base,val)     			\
-		do {					\
-			u8 __Temp = inSISREG(base); 	\
-			outSISREG(base, __Temp & (val));\
-		} while (0)
-
-#define inSISIDXREG(base,idx,var)			\
-		do {					\
-			outSISREG(base, idx); 		\
-			var = inSISREG((base)+1);	\
-		} while (0)
-
-#define outSISIDXREG(base,idx,val)			\
-		do {					\
-			outSISREG(base, idx);		\
-			outSISREG((base)+1, val);	\
-		} while (0)
-
-#define orSISIDXREG(base,idx,val)				\
-		do {						\
-			u8 __Temp; 				\
-			outSISREG(base, idx);   		\
-			__Temp = inSISREG((base)+1) | (val); 	\
-			outSISREG((base)+1, __Temp);		\
-		} while (0)
-
-#define andSISIDXREG(base,idx,and)				\
-		do {						\
-			u8 __Temp; 				\
-			outSISREG(base, idx);   		\
-			__Temp = inSISREG((base)+1) & (and); 	\
-			outSISREG((base)+1, __Temp);		\
-		} while (0)
-
-#define setSISIDXREG(base,idx,and,or)   				\
-		do {							\
-			u8 __Temp; 					\
-			outSISREG(base, idx);				\
-			__Temp = (inSISREG((base)+1) & (and)) | (or); 	\
-			outSISREG((base)+1, __Temp);			\
-		} while (0)
+void SiS_SetReg(SISIOADDRESS, u8, u8);
+void SiS_SetRegByte(SISIOADDRESS, u8);
+void SiS_SetRegShort(SISIOADDRESS, u16);
+void SiS_SetRegLong(SISIOADDRESS, u32);
+void SiS_SetRegANDOR(SISIOADDRESS, u8, u8, u8);
+void SiS_SetRegAND(SISIOADDRESS, u8, u8);
+void SiS_SetRegOR(SISIOADDRESS, u8, u8);
+u8 SiS_GetReg(SISIOADDRESS, u8);
+u8 SiS_GetRegByte(SISIOADDRESS);
+u16 SiS_GetRegShort(SISIOADDRESS);
+u32 SiS_GetRegLong(SISIOADDRESS);
 
 /* MMIO access macros */
 #define MMIO_IN8(base, offset)  readb((base+offset))
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 7e3370f..2fb8c5a 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -737,7 +737,7 @@
 	if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
 		return false;
 
-	inSISIDXREG(SISPART1,0x00,P1_00);
+	P1_00 = SiS_GetReg(SISPART1, 0x00);
 	if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
 	    ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
 		return true;
@@ -751,11 +751,11 @@
 {
 	u8 temp;
 
-	inSISIDXREG(SISCR,0x17,temp);
+	temp = SiS_GetReg(SISCR, 0x17);
 	if(!(temp & 0x80))
 		return false;
 
-	inSISIDXREG(SISSR,0x1f,temp);
+	temp = SiS_GetReg(SISSR, 0x1f);
 	if(temp & 0xc0)
 		return false;
 
@@ -768,7 +768,7 @@
 	if(!sisfballowretracecrt1(ivideo))
 		return false;
 
-	if(inSISREG(SISINPSTAT) & 0x08)
+	if (SiS_GetRegByte(SISINPSTAT) & 0x08)
 		return true;
 	else
 		return false;
@@ -783,9 +783,9 @@
 		return;
 
 	watchdog = 65536;
-	while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
+	while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
 	watchdog = 65536;
-	while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
+	while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
 }
 
 static bool
@@ -799,7 +799,7 @@
 	default:	  return false;
 	}
 
-	inSISIDXREG(SISPART1, reg, temp);
+	temp = SiS_GetReg(SISPART1, reg);
 	if(temp & 0x02)
 		return true;
 	else
@@ -837,10 +837,10 @@
 			default:
 			case SIS_315_VGA: idx = 0x30; break;
 		}
-		inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
-		inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
-		inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
-		inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+		reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
+		reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
+		reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
+		reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
 		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
 		if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
 		if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
@@ -853,13 +853,13 @@
 			FB_VBLANK_HAVE_VBLANK |
 			FB_VBLANK_HAVE_VCOUNT |
 			FB_VBLANK_HAVE_HCOUNT);
-		reg1 = inSISREG(SISINPSTAT);
+		reg1 = SiS_GetRegByte(SISINPSTAT);
 		if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
 		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
-		inSISIDXREG(SISCR,0x20,reg1);
-		inSISIDXREG(SISCR,0x1b,reg1);
-		inSISIDXREG(SISCR,0x1c,reg2);
-		inSISIDXREG(SISCR,0x1d,reg3);
+		reg1 = SiS_GetReg(SISCR, 0x20);
+		reg1 = SiS_GetReg(SISCR, 0x1b);
+		reg2 = SiS_GetReg(SISCR, 0x1c);
+		reg3 = SiS_GetReg(SISCR, 0x1d);
 		(*vcount) = reg2 | ((reg3 & 0x07) << 8);
 		(*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
 	}
@@ -930,12 +930,12 @@
 		     (ivideo->sisfb_thismonitor.feature & 0xe0))) {
 
 			if(ivideo->sisvga_engine == SIS_315_VGA) {
-				setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+				SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
 			}
 
 			if(!(sisfb_bridgeisslave(ivideo))) {
-				setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
-				setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+				SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
+				SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
 			}
 		}
 
@@ -965,25 +965,25 @@
 		    (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
 		   ((ivideo->sisvga_engine == SIS_315_VGA) &&
 		    ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
-			setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
+			SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
 		}
 
 		if(ivideo->sisvga_engine == SIS_300_VGA) {
 			if((ivideo->vbflags2 & VB2_30xB) &&
 			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
-				setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
+				SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
 			}
 		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
 			if((ivideo->vbflags2 & VB2_30xB) &&
 			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
-				setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+				SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
 			}
 		}
 
 	} else if(ivideo->currentvbflags & CRT2_VGA) {
 
 		if(ivideo->vbflags2 & VB2_30xB) {
-			setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+			SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
 		}
 
 	}
@@ -1114,15 +1114,15 @@
 
 	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
 	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
-		outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
-		setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
+		SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
+		SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
 	}
 
 	/* We must not set the pitch for CRT2 if bridge is in slave mode */
 	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
-		orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
-		outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
-		setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
+		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
+		SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
+		SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
 	}
 }
 
@@ -1167,7 +1167,7 @@
 	/* >=2.6.12's fbcon clears the screen anyway */
 	modeno |= 0x80;
 
-	outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
 	sisfb_pre_setmode(ivideo);
 
@@ -1176,7 +1176,7 @@
 		return -EINVAL;
 	}
 
-	outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
 	sisfb_post_setmode(ivideo);
 
@@ -1308,13 +1308,13 @@
 static void
 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
 {
-	outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-	outSISIDXREG(SISCR, 0x0D, base & 0xFF);
-	outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
-	outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
+	SiS_SetReg(SISCR, 0x0D, base & 0xFF);
+	SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
+	SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
 	if(ivideo->sisvga_engine == SIS_315_VGA) {
-		setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
+		SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
 	}
 }
 
@@ -1322,12 +1322,12 @@
 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
 {
 	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-		orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
-		outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
-		outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
-		outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
+		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
+		SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
+		SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
+		SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
 		if(ivideo->sisvga_engine == SIS_315_VGA) {
-			setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
+			SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
 		}
 	}
 }
@@ -1388,15 +1388,15 @@
 
 	switch(info->var.bits_per_pixel) {
 	case 8:
-		outSISREG(SISDACA, regno);
-		outSISREG(SISDACD, (red >> 10));
-		outSISREG(SISDACD, (green >> 10));
-		outSISREG(SISDACD, (blue >> 10));
+		SiS_SetRegByte(SISDACA, regno);
+		SiS_SetRegByte(SISDACD, (red >> 10));
+		SiS_SetRegByte(SISDACD, (green >> 10));
+		SiS_SetRegByte(SISDACD, (blue >> 10));
 		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-			outSISREG(SISDAC2A, regno);
-			outSISREG(SISDAC2D, (red >> 8));
-			outSISREG(SISDAC2D, (green >> 8));
-			outSISREG(SISDAC2D, (blue >> 8));
+			SiS_SetRegByte(SISDAC2A, regno);
+			SiS_SetRegByte(SISDAC2D, (red >> 8));
+			SiS_SetRegByte(SISDAC2D, (green >> 8));
+			SiS_SetRegByte(SISDAC2D, (blue >> 8));
 		}
 		break;
 	case 16:
@@ -1961,7 +1961,7 @@
 	switch(ivideo->chip) {
 #ifdef CONFIG_FB_SIS_300
 	case SIS_300:
-		inSISIDXREG(SISSR, 0x14, reg);
+		reg = SiS_GetReg(SISSR, 0x14);
 		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
 		break;
 	case SIS_540:
@@ -1977,7 +1977,7 @@
 	case SIS_315H:
 	case SIS_315PRO:
 	case SIS_315:
-		inSISIDXREG(SISSR, 0x14, reg);
+		reg = SiS_GetReg(SISSR, 0x14);
 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
 		switch((reg >> 2) & 0x03) {
 		case 0x01:
@@ -1989,31 +1989,31 @@
 		}
 		break;
 	case SIS_330:
-		inSISIDXREG(SISSR, 0x14, reg);
+		reg = SiS_GetReg(SISSR, 0x14);
 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
 		if(reg & 0x0c) ivideo->video_size <<= 1;
 		break;
 	case SIS_550:
 	case SIS_650:
 	case SIS_740:
-		inSISIDXREG(SISSR, 0x14, reg);
+		reg = SiS_GetReg(SISSR, 0x14);
 		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
 		break;
 	case SIS_661:
 	case SIS_741:
-		inSISIDXREG(SISCR, 0x79, reg);
+		reg = SiS_GetReg(SISCR, 0x79);
 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
 		break;
 	case SIS_660:
 	case SIS_760:
 	case SIS_761:
-		inSISIDXREG(SISCR, 0x79, reg);
+		reg = SiS_GetReg(SISCR, 0x79);
 		reg = (reg & 0xf0) >> 4;
 		if(reg)	{
 			ivideo->video_size = (1 << reg) << 20;
 			ivideo->UMAsize = ivideo->video_size;
 		}
-		inSISIDXREG(SISCR, 0x78, reg);
+		reg = SiS_GetReg(SISCR, 0x78);
 		reg &= 0x30;
 		if(reg) {
 			if(reg == 0x10) {
@@ -2027,7 +2027,7 @@
 	case SIS_340:
 	case XGI_20:
 	case XGI_40:
-		inSISIDXREG(SISSR, 0x14, reg);
+		reg = SiS_GetReg(SISSR, 0x14);
 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
 		if(ivideo->chip != XGI_20) {
 			reg = (reg & 0x0c) >> 2;
@@ -2061,11 +2061,11 @@
 
 #ifdef CONFIG_FB_SIS_300
 	if(ivideo->sisvga_engine == SIS_300_VGA) {
-		inSISIDXREG(SISSR, 0x17, temp);
+		temp = SiS_GetReg(SISSR, 0x17);
 		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
 			/* PAL/NTSC is stored on SR16 on such machines */
 			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-				inSISIDXREG(SISSR, 0x16, temp);
+				temp = SiS_GetReg(SISSR, 0x16);
 				if(temp & 0x20)
 					ivideo->vbflags |= TV_PAL;
 				else
@@ -2075,7 +2075,7 @@
 	}
 #endif
 
-	inSISIDXREG(SISCR, 0x32, cr32);
+	cr32 = SiS_GetReg(SISCR, 0x32);
 
 	if(cr32 & SIS_CRT1) {
 		ivideo->sisfb_crt1off = 0;
@@ -2151,15 +2151,15 @@
 	    }
 	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
 		if(ivideo->sisvga_engine == SIS_300_VGA) {
-			inSISIDXREG(SISSR, 0x38, temp);
+			temp = SiS_GetReg(SISSR, 0x38);
 			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
 			else		ivideo->vbflags |= TV_NTSC;
 		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
-			inSISIDXREG(SISSR, 0x38, temp);
+			temp = SiS_GetReg(SISSR, 0x38);
 			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
 			else		ivideo->vbflags |= TV_NTSC;
 		} else {
-			inSISIDXREG(SISCR, 0x79, temp);
+			temp = SiS_GetReg(SISCR, 0x79);
 			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
 			else		ivideo->vbflags |= TV_NTSC;
 		}
@@ -2198,26 +2198,26 @@
     u16 temp = 0xffff;
     int i;
 
-    inSISIDXREG(SISSR,0x1F,sr1F);
-    orSISIDXREG(SISSR,0x1F,0x04);
-    andSISIDXREG(SISSR,0x1F,0x3F);
+    sr1F = SiS_GetReg(SISSR, 0x1F);
+    SiS_SetRegOR(SISSR, 0x1F, 0x04);
+    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
     if(sr1F & 0xc0) mustwait = true;
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->sisvga_engine == SIS_315_VGA) {
-       inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63);
+       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
        cr63 &= 0x40;
-       andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
+       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
     }
 #endif
 
-    inSISIDXREG(SISCR,0x17,cr17);
+    cr17 = SiS_GetReg(SISCR, 0x17);
     cr17 &= 0x80;
     if(!cr17) {
-       orSISIDXREG(SISCR,0x17,0x80);
+       SiS_SetRegOR(SISCR, 0x17, 0x80);
        mustwait = true;
-       outSISIDXREG(SISSR, 0x00, 0x01);
-       outSISIDXREG(SISSR, 0x00, 0x03);
+       SiS_SetReg(SISSR, 0x00, 0x01);
+       SiS_SetReg(SISSR, 0x00, 0x03);
     }
 
     if(mustwait) {
@@ -2226,18 +2226,18 @@
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->chip >= SIS_330) {
-       andSISIDXREG(SISCR,0x32,~0x20);
+       SiS_SetRegAND(SISCR, 0x32, ~0x20);
        if(ivideo->chip >= SIS_340) {
-          outSISIDXREG(SISCR, 0x57, 0x4a);
+	   SiS_SetReg(SISCR, 0x57, 0x4a);
        } else {
-          outSISIDXREG(SISCR, 0x57, 0x5f);
+	   SiS_SetReg(SISCR, 0x57, 0x5f);
        }
-       orSISIDXREG(SISCR, 0x53, 0x02);
-       while((inSISREG(SISINPSTAT)) & 0x01)    break;
-       while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
-       if((inSISREG(SISMISCW)) & 0x10) temp = 1;
-       andSISIDXREG(SISCR, 0x53, 0xfd);
-       andSISIDXREG(SISCR, 0x57, 0x00);
+	SiS_SetRegOR(SISCR, 0x53, 0x02);
+	while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
+	while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
+	if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
+	SiS_SetRegAND(SISCR, 0x53, 0xfd);
+	SiS_SetRegAND(SISCR, 0x57, 0x00);
     }
 #endif
 
@@ -2254,18 +2254,18 @@
     }
 
     if((temp) && (temp != 0xffff)) {
-       orSISIDXREG(SISCR,0x32,0x20);
+       SiS_SetRegOR(SISCR, 0x32, 0x20);
     }
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->sisvga_engine == SIS_315_VGA) {
-       setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63);
+	SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
     }
 #endif
 
-    setSISIDXREG(SISCR,0x17,0x7F,cr17);
+    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
 
-    outSISIDXREG(SISSR,0x1F,sr1F);
+    SiS_SetReg(SISSR, 0x1F, sr1F);
 }
 
 /* Determine and detect attached devices on SiS30x */
@@ -2286,7 +2286,7 @@
 		return;
 
 	/* If LCD already set up by BIOS, skip it */
-	inSISIDXREG(SISCR, 0x32, reg);
+	reg = SiS_GetReg(SISCR, 0x32);
 	if(reg & 0x08)
 		return;
 
@@ -2349,10 +2349,10 @@
 	else
 		cr37 |= 0xc0;
 
-	outSISIDXREG(SISCR, 0x36, paneltype);
+	SiS_SetReg(SISCR, 0x36, paneltype);
 	cr37 &= 0xf1;
-	setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
-	orSISIDXREG(SISCR, 0x32, 0x08);
+	SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
+	SiS_SetRegOR(SISCR, 0x32, 0x08);
 
 	ivideo->SiS_Pr.PanelSelfDetected = true;
 }
@@ -2366,19 +2366,19 @@
        result = 0;
        for(i = 0; i < 3; i++) {
           mytest = test;
-          outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
+	   SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
           temp = (type >> 8) | (mytest & 0x00ff);
-          setSISIDXREG(SISPART4,0x10,0xe0,temp);
+	  SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
           SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
           mytest >>= 8;
           mytest &= 0x7f;
-          inSISIDXREG(SISPART4,0x03,temp);
+	   temp = SiS_GetReg(SISPART4, 0x03);
           temp ^= 0x0e;
           temp &= mytest;
           if(temp == mytest) result++;
 #if 1
-	  outSISIDXREG(SISPART4,0x11,0x00);
-	  andSISIDXREG(SISPART4,0x10,0xe0);
+	  SiS_SetReg(SISPART4, 0x11, 0x00);
+	  SiS_SetRegAND(SISPART4, 0x10, 0xe0);
 	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
 #endif
        }
@@ -2400,7 +2400,7 @@
 
     if(ivideo->vbflags2 & VB2_301) {
        svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
-       inSISIDXREG(SISPART4,0x01,myflag);
+       myflag = SiS_GetReg(SISPART4, 0x01);
        if(myflag & 0x04) {
 	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
        }
@@ -2430,7 +2430,7 @@
     }
 
     if(ivideo->chip == SIS_300) {
-       inSISIDXREG(SISSR,0x3b,myflag);
+       myflag = SiS_GetReg(SISSR, 0x3b);
        if(!(myflag & 0x01)) vga2 = vga2_c = 0;
     }
 
@@ -2438,93 +2438,93 @@
        vga2 = vga2_c = 0;
     }
 
-    inSISIDXREG(SISSR,0x1e,backupSR_1e);
-    orSISIDXREG(SISSR,0x1e,0x20);
+    backupSR_1e = SiS_GetReg(SISSR, 0x1e);
+    SiS_SetRegOR(SISSR, 0x1e, 0x20);
 
-    inSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
     if(ivideo->vbflags2 & VB2_30xC) {
-       setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
+	SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
     } else {
-       orSISIDXREG(SISPART4,0x0d,0x04);
+       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
     }
     SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
 
-    inSISIDXREG(SISPART2,0x00,backupP2_00);
-    outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
+    backupP2_00 = SiS_GetReg(SISPART2, 0x00);
+    SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
 
-    inSISIDXREG(SISPART2,0x4d,backupP2_4d);
+    backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
     if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
-       outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
+	SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
     }
 
     if(!(ivideo->vbflags2 & VB2_30xCLV)) {
        SISDoSense(ivideo, 0, 0);
     }
 
-    andSISIDXREG(SISCR, 0x32, ~0x14);
+    SiS_SetRegAND(SISCR, 0x32, ~0x14);
 
     if(vga2_c || vga2) {
        if(SISDoSense(ivideo, vga2, vga2_c)) {
           if(biosflag & 0x01) {
 	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
-	     orSISIDXREG(SISCR, 0x32, 0x04);
+	     SiS_SetRegOR(SISCR, 0x32, 0x04);
 	  } else {
 	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
-	     orSISIDXREG(SISCR, 0x32, 0x10);
+	     SiS_SetRegOR(SISCR, 0x32, 0x10);
 	  }
        }
     }
 
-    andSISIDXREG(SISCR, 0x32, 0x3f);
+    SiS_SetRegAND(SISCR, 0x32, 0x3f);
 
     if(ivideo->vbflags2 & VB2_30xCLV) {
-       orSISIDXREG(SISPART4,0x0d,0x04);
+       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
     }
 
     if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
-       outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
+       SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
        if((result = SISDoSense(ivideo, svhs, 0x0604))) {
           if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
 	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
-	     orSISIDXREG(SISCR,0x32,0x80);
+	     SiS_SetRegOR(SISCR, 0x32, 0x80);
 	  }
        }
-       outSISIDXREG(SISPART2,0x4d,backupP2_4d);
+       SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
     }
 
-    andSISIDXREG(SISCR, 0x32, ~0x03);
+    SiS_SetRegAND(SISCR, 0x32, ~0x03);
 
     if(!(ivideo->vbflags & TV_YPBPR)) {
        if((result = SISDoSense(ivideo, svhs, svhs_c))) {
           printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
-          orSISIDXREG(SISCR, 0x32, 0x02);
+	   SiS_SetRegOR(SISCR, 0x32, 0x02);
        }
        if((biosflag & 0x02) || (!result)) {
           if(SISDoSense(ivideo, cvbs, cvbs_c)) {
 	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
-	     orSISIDXREG(SISCR, 0x32, 0x01);
+	     SiS_SetRegOR(SISCR, 0x32, 0x01);
           }
        }
     }
 
     SISDoSense(ivideo, 0, 0);
 
-    outSISIDXREG(SISPART2,0x00,backupP2_00);
-    outSISIDXREG(SISPART4,0x0d,backupP4_0d);
-    outSISIDXREG(SISSR,0x1e,backupSR_1e);
+    SiS_SetReg(SISPART2, 0x00, backupP2_00);
+    SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
+    SiS_SetReg(SISSR, 0x1e, backupSR_1e);
 
     if(ivideo->vbflags2 & VB2_30xCLV) {
-       inSISIDXREG(SISPART2,0x00,biosflag);
+	biosflag = SiS_GetReg(SISPART2, 0x00);
        if(biosflag & 0x20) {
           for(myflag = 2; myflag > 0; myflag--) {
 	     biosflag ^= 0x20;
-	     outSISIDXREG(SISPART2,0x00,biosflag);
+	     SiS_SetReg(SISPART2, 0x00, biosflag);
 	  }
        }
     }
 
-    outSISIDXREG(SISPART2,0x00,backupP2_00);
+    SiS_SetReg(SISPART2, 0x00, backupP2_00);
 }
 
 /* Determine and detect attached TV's on Chrontel */
@@ -2588,20 +2588,20 @@
 	   if(temp1 == 0x02) {
 		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
 		ivideo->vbflags |= TV_SVIDEO;
-		orSISIDXREG(SISCR, 0x32, 0x02);
-		andSISIDXREG(SISCR, 0x32, ~0x05);
+		SiS_SetRegOR(SISCR, 0x32, 0x02);
+		SiS_SetRegAND(SISCR, 0x32, ~0x05);
 	   } else if (temp1 == 0x01) {
 		printk(KERN_INFO "%s CVBS output\n", stdstr);
 		ivideo->vbflags |= TV_AVIDEO;
-		orSISIDXREG(SISCR, 0x32, 0x01);
-		andSISIDXREG(SISCR, 0x32, ~0x06);
+		SiS_SetRegOR(SISCR, 0x32, 0x01);
+		SiS_SetRegAND(SISCR, 0x32, ~0x06);
 	   } else {
 		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
-		andSISIDXREG(SISCR, 0x32, ~0x07);
+		SiS_SetRegAND(SISCR, 0x32, ~0x07);
 	   }
        } else if(temp1 == 0) {
 	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
-	  andSISIDXREG(SISCR, 0x32, ~0x07);
+	  SiS_SetRegAND(SISCR, 0x32, ~0x07);
        }
        /* Set general purpose IO for Chrontel communication */
        SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
@@ -2632,22 +2632,22 @@
 	case 0x01:
 	     printk(KERN_INFO "%s CVBS output\n", stdstr);
 	     ivideo->vbflags |= TV_AVIDEO;
-	     orSISIDXREG(SISCR, 0x32, 0x01);
-	     andSISIDXREG(SISCR, 0x32, ~0x06);
+	     SiS_SetRegOR(SISCR, 0x32, 0x01);
+	     SiS_SetRegAND(SISCR, 0x32, ~0x06);
 	     break;
 	case 0x02:
 	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
 	     ivideo->vbflags |= TV_SVIDEO;
-	     orSISIDXREG(SISCR, 0x32, 0x02);
-	     andSISIDXREG(SISCR, 0x32, ~0x05);
+	     SiS_SetRegOR(SISCR, 0x32, 0x02);
+	     SiS_SetRegAND(SISCR, 0x32, ~0x05);
 	     break;
 	case 0x04:
 	     printk(KERN_INFO "%s SCART output\n", stdstr);
-	     orSISIDXREG(SISCR, 0x32, 0x04);
-	     andSISIDXREG(SISCR, 0x32, ~0x03);
+	     SiS_SetRegOR(SISCR, 0x32, 0x04);
+	     SiS_SetRegAND(SISCR, 0x32, ~0x03);
 	     break;
 	default:
-	     andSISIDXREG(SISCR, 0x32, ~0x07);
+	     SiS_SetRegAND(SISCR, 0x32, ~0x07);
 	}
 #endif
     }
@@ -2665,10 +2665,10 @@
 	if(ivideo->chip == XGI_20)
 		return;
 
-	inSISIDXREG(SISPART4, 0x00, vb_chipid);
+	vb_chipid = SiS_GetReg(SISPART4, 0x00);
 	switch(vb_chipid) {
 	case 0x01:
-		inSISIDXREG(SISPART4, 0x01, reg);
+		reg = SiS_GetReg(SISPART4, 0x01);
 		if(reg < 0xb0) {
 			ivideo->vbflags |= VB_301;	/* Deprecated */
 			ivideo->vbflags2 |= VB2_301;
@@ -2676,7 +2676,7 @@
 		} else if(reg < 0xc0) {
 			ivideo->vbflags |= VB_301B;	/* Deprecated */
 			ivideo->vbflags2 |= VB2_301B;
-			inSISIDXREG(SISPART4,0x23,reg);
+			reg = SiS_GetReg(SISPART4, 0x23);
 			if(!(reg & 0x02)) {
 			   ivideo->vbflags |= VB_30xBDH;	/* Deprecated */
 			   ivideo->vbflags2 |= VB2_30xBDH;
@@ -2693,7 +2693,7 @@
 			ivideo->vbflags2 |= VB2_301LV;
 			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
 		} else if(reg <= 0xe1) {
-			inSISIDXREG(SISPART4,0x39,reg);
+			reg = SiS_GetReg(SISPART4, 0x39);
 			if(reg == 0xff) {
 			   ivideo->vbflags |= VB_302LV;	/* Deprecated */
 			   ivideo->vbflags2 |= VB2_302LV;
@@ -2718,7 +2718,7 @@
 	}
 
 	if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
-		inSISIDXREG(SISCR, 0x37, reg);
+		reg = SiS_GetReg(SISCR, 0x37);
 		reg &= SIS_EXTERNAL_CHIP_MASK;
 		reg >>= 1;
 		if(ivideo->sisvga_engine == SIS_300_VGA) {
@@ -2759,7 +2759,7 @@
 #endif
 		} else if(ivideo->chip >= SIS_661) {
 #ifdef CONFIG_FB_SIS_315
-			inSISIDXREG(SISCR, 0x38, reg);
+			reg = SiS_GetReg(SISCR, 0x38);
 			reg >>= 5;
 			switch(reg) {
 			   case 0x02:
@@ -2822,13 +2822,13 @@
 
 		tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
 
-		inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+		tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
 		tq_state |= 0xf0;
 		tq_state &= 0xfc;
 		tq_state |= (u8)(tqueue_pos >> 8);
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
 
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
 
 		ivideo->caps |= TURBO_QUEUE_CAP;
 	}
@@ -2865,8 +2865,8 @@
 			}
 		}
 
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
 
 		if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
 			/* Must disable dual pipe on XGI_40. Can't do
@@ -2878,7 +2878,7 @@
 
 				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
 
-				outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
+				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
 
 				tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
 				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
@@ -2895,7 +2895,7 @@
 
 				sisfb_syncaccel(ivideo);
 
-				outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
 
 			}
 		}
@@ -2904,7 +2904,7 @@
 		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
 
 		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
 
 		tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
 		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
@@ -2922,7 +2922,7 @@
 	u8 reg;
 	int i;
 
-	inSISIDXREG(SISCR, 0x36, reg);
+	reg = SiS_GetReg(SISCR, 0x36);
 	reg &= 0x0f;
 	if(ivideo->sisvga_engine == SIS_300_VGA) {
 		ivideo->CRT2LCDType = sis300paneltype[reg];
@@ -2941,8 +2941,8 @@
 	if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
 		/* For broken BIOSes: Assume 1024x768, RGB18 */
 		ivideo->CRT2LCDType = LCD_1024x768;
-		setSISIDXREG(SISCR,0x36,0xf0,0x02);
-		setSISIDXREG(SISCR,0x37,0xee,0x01);
+		SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
+		SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
 		printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
 	}
 
@@ -2980,10 +2980,10 @@
 	if(ivideo->sisvga_engine == SIS_300_VGA) {
 		if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
 			int tmp;
-			inSISIDXREG(SISCR,0x30,tmp);
+			tmp = SiS_GetReg(SISCR, 0x30);
 			if(tmp & 0x20) {
 				/* Currently on LCD? If yes, read current pdc */
-				inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+				ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
 				ivideo->detectedpdc &= 0x3c;
 				if(ivideo->SiS_Pr.PDC == -1) {
 					/* Let option override detection */
@@ -3007,7 +3007,7 @@
 		/* Try to find about LCDA */
 		if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
 			int tmp;
-			inSISIDXREG(SISPART1,0x13,tmp);
+			tmp = SiS_GetReg(SISPART1, 0x13);
 			if(tmp & 0x04) {
 				ivideo->SiS_Pr.SiS_UseLCDA = true;
 				ivideo->detectedlcda = 0x03;
@@ -3017,16 +3017,16 @@
 		/* Save PDC */
 		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
 			int tmp;
-			inSISIDXREG(SISCR,0x30,tmp);
+			tmp = SiS_GetReg(SISCR, 0x30);
 			if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
 				/* Currently on LCD? If yes, read current pdc */
 				u8 pdc;
-				inSISIDXREG(SISPART1,0x2D,pdc);
+				pdc = SiS_GetReg(SISPART1, 0x2D);
 				ivideo->detectedpdc  = (pdc & 0x0f) << 1;
 				ivideo->detectedpdca = (pdc & 0xf0) >> 3;
-				inSISIDXREG(SISPART1,0x35,pdc);
+				pdc = SiS_GetReg(SISPART1, 0x35);
 				ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
-				inSISIDXREG(SISPART1,0x20,pdc);
+				pdc = SiS_GetReg(SISPART1, 0x20);
 				ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
 				if(ivideo->newrom) {
 					/* New ROM invalidates other PDC resp. */
@@ -3060,10 +3060,10 @@
 
 			/* Save EMI */
 			if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
-				inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
-				inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
-				inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
-				inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+				ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
+				ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
+				ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
+				ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
 				ivideo->SiS_Pr.HaveEMI = true;
 				if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
 					ivideo->SiS_Pr.HaveEMILCD = true;
@@ -3488,8 +3488,8 @@
 	 * ivideo->accel here, as this might have
 	 * been changed before this is called.
 	 */
-	inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
-	inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
+	cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
+	cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
 	/* MMIO and 2D/3D engine enabled? */
 	if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
 #ifdef CONFIG_FB_SIS_300
@@ -3507,7 +3507,7 @@
 			 * enabled, and that the queue
 			 * is not in the state of "reset"
 			 */
-			inSISIDXREG(SISSR, 0x26, cr30);
+			cr30 = SiS_GetReg(SISSR, 0x26);
 			if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
 				sisfb_syncaccel(ivideo);
 			}
@@ -3524,9 +3524,9 @@
 
 	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
 
-	outSISIDXREG(SISSR, 0x05, 0x86);
+	SiS_SetReg(SISSR, 0x05, 0x86);
 
-	inSISIDXREG(SISCR, 0x31, cr31);
+	cr31 = SiS_GetReg(SISCR, 0x31);
 	cr31 &= ~0x60;
 	cr31 |= 0x04;
 
@@ -3535,11 +3535,11 @@
 #ifdef CONFIG_FB_SIS_315
 	if(ivideo->sisvga_engine == SIS_315_VGA) {
 	   if(ivideo->chip >= SIS_661) {
-	      inSISIDXREG(SISCR, 0x38, cr38);
+	      cr38 = SiS_GetReg(SISCR, 0x38);
 	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
 	   } else {
 	      tvregnum = 0x38;
-	      inSISIDXREG(SISCR, tvregnum, cr38);
+	      cr38 = SiS_GetReg(SISCR, tvregnum);
 	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
 	   }
 	}
@@ -3547,7 +3547,7 @@
 #ifdef CONFIG_FB_SIS_300
 	if(ivideo->sisvga_engine == SIS_300_VGA) {
 	   tvregnum = 0x35;
-	   inSISIDXREG(SISCR, tvregnum, cr38);
+	   cr38 = SiS_GetReg(SISCR, tvregnum);
 	}
 #endif
 
@@ -3654,20 +3654,20 @@
 	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
 	}
 
-	outSISIDXREG(SISCR, 0x30, cr30);
-	outSISIDXREG(SISCR, 0x33, cr33);
+	SiS_SetReg(SISCR, 0x30, cr30);
+	SiS_SetReg(SISCR, 0x33, cr33);
 
 	if(ivideo->chip >= SIS_661) {
 #ifdef CONFIG_FB_SIS_315
 	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
-	   setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
+	   SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
 	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
-	   setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
+	   SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
 #endif
 	} else if(ivideo->chip != SIS_300) {
-	   outSISIDXREG(SISCR, tvregnum, cr38);
+	   SiS_SetReg(SISCR, tvregnum, cr38);
 	}
-	outSISIDXREG(SISCR, 0x31, cr31);
+	SiS_SetReg(SISCR, 0x31, cr31);
 
 	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
 
@@ -3682,15 +3682,15 @@
 	u8  tmpreg;
 
 	if(ivideo->chip >= SIS_661) {
-		inSISIDXREG(SISSR,0x11,tmpreg);
+		tmpreg = SiS_GetReg(SISSR, 0x11);
 		if(tmpreg & 0x20) {
-			inSISIDXREG(SISSR,0x3e,tmpreg);
+			tmpreg = SiS_GetReg(SISSR, 0x3e);
 			tmpreg = (tmpreg + 1) & 0xff;
-			outSISIDXREG(SISSR,0x3e,tmpreg);
-			inSISIDXREG(SISSR,0x11,tmpreg);
+			SiS_SetReg(SISSR, 0x3e, tmpreg);
+			tmpreg = SiS_GetReg(SISSR, 0x11);
 		}
 		if(tmpreg & 0xf0) {
-			andSISIDXREG(SISSR,0x11,0x0f);
+			SiS_SetRegAND(SISSR, 0x11, 0x0f);
 		}
 	}
 }
@@ -3716,7 +3716,7 @@
 			case 1:
 				x += val;
 				if(x < 0) x = 0;
-				outSISIDXREG(SISSR,0x05,0x86);
+				SiS_SetReg(SISSR, 0x05, 0x86);
 				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
 				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
 				break;
@@ -3745,11 +3745,11 @@
 			temp += (val * 2);
 			p2_43 = temp & 0xff;
 			p2_42 = (temp & 0xf00) >> 4;
-			outSISIDXREG(SISPART2,0x1f,p2_1f);
-			setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
-			setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
-			setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
-			outSISIDXREG(SISPART2,0x43,p2_43);
+			SiS_SetReg(SISPART2, 0x1f, p2_1f);
+			SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
+			SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
+			SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
+			SiS_SetReg(SISPART2, 0x43, p2_43);
 		}
 	}
 }
@@ -3774,7 +3774,7 @@
 			case 1:
 				y -= val;
 				if(y < 0) y = 0;
-				outSISIDXREG(SISSR,0x05,0x86);
+				SiS_SetReg(SISSR, 0x05, 0x86);
 				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
 				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
 				break;
@@ -3798,8 +3798,8 @@
 					p2_02 += 2;
 				}
 			}
-			outSISIDXREG(SISPART2,0x01,p2_01);
-			outSISIDXREG(SISPART2,0x02,p2_02);
+			SiS_SetReg(SISPART2, 0x01, p2_01);
+			SiS_SetReg(SISPART2, 0x02, p2_02);
 		}
 	}
 }
@@ -3816,7 +3816,7 @@
 	u8 reg1;
 #endif
 
-	outSISIDXREG(SISSR, 0x05, 0x86);
+	SiS_SetReg(SISSR, 0x05, 0x86);
 
 #ifdef CONFIG_FB_SIS_315
 	sisfb_fixup_SR11(ivideo);
@@ -3840,7 +3840,7 @@
 			crt1isoff = false;
 			reg = 0x80;
 		}
-		setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+		SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
 	}
 #endif
 #ifdef CONFIG_FB_SIS_315
@@ -3854,8 +3854,8 @@
 			reg  = 0x00;
 			reg1 = 0x00;
 		}
-		setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
-		setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
+		SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
+		SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
 	}
 #endif
 
@@ -3871,17 +3871,17 @@
 		}
 	}
 
-	andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+	SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
 
 	if(ivideo->currentvbflags & CRT2_TV) {
 		if(ivideo->vbflags2 & VB2_SISBRIDGE) {
-			inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
-			inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
-			inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
-			inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
-			inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
-			inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
-			inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+			ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
+			ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
+			ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
+			ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
+			ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
+			ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
+			ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
 		} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
 			if(ivideo->chronteltype == 1) {
 				ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
@@ -4105,7 +4105,6 @@
 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 	void __iomem *rom_base;
 	unsigned char *myrombase = NULL;
-	u32 temp;
 	size_t romsize;
 
 	/* First, try the official pci ROM functions (except
@@ -4132,26 +4131,29 @@
 	/* Otherwise do it the conventional way. */
 
 #if defined(__i386__) || defined(__x86_64__)
+	{
+		u32 temp;
 
-	for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+		for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
 
-		rom_base = ioremap(temp, 65536);
-		if(!rom_base)
-			continue;
+			rom_base = ioremap(temp, 65536);
+			if (!rom_base)
+				continue;
 
-		if(!sisfb_check_rom(rom_base, ivideo)) {
+			if (!sisfb_check_rom(rom_base, ivideo)) {
+				iounmap(rom_base);
+				continue;
+			}
+
+			if ((myrombase = vmalloc(65536)))
+				memcpy_fromio(myrombase, rom_base, 65536);
+
 			iounmap(rom_base);
-			continue;
+			break;
+
 		}
 
-		if((myrombase = vmalloc(65536)))
-			memcpy_fromio(myrombase, rom_base, 65536);
-
-		iounmap(rom_base);
-		break;
-
-        }
-
+	}
 #endif
 
 	return myrombase;
@@ -4192,10 +4194,10 @@
 	unsigned char reg;
 	int i, j;
 
-	andSISIDXREG(SISSR, 0x15, 0xFB);
-	orSISIDXREG(SISSR, 0x15, 0x04);
-	outSISIDXREG(SISSR, 0x13, 0x00);
-	outSISIDXREG(SISSR, 0x14, 0xBF);
+	SiS_SetRegAND(SISSR, 0x15, 0xFB);
+	SiS_SetRegOR(SISSR, 0x15, 0x04);
+	SiS_SetReg(SISSR, 0x13, 0x00);
+	SiS_SetReg(SISSR, 0x14, 0xBF);
 
 	for(i = 0; i < 2; i++) {
 		temp = 0x1234;
@@ -4203,12 +4205,12 @@
 			writew(temp, FBAddress);
 			if(readw(FBAddress) == temp)
 				break;
-			orSISIDXREG(SISSR, 0x3c, 0x01);
-			inSISIDXREG(SISSR, 0x05, reg);
-			inSISIDXREG(SISSR, 0x05, reg);
-			andSISIDXREG(SISSR, 0x3c, 0xfe);
-			inSISIDXREG(SISSR, 0x05, reg);
-			inSISIDXREG(SISSR, 0x05, reg);
+			SiS_SetRegOR(SISSR, 0x3c, 0x01);
+			reg = SiS_GetReg(SISSR, 0x05);
+			reg = SiS_GetReg(SISSR, 0x05);
+			SiS_SetRegAND(SISSR, 0x3c, 0xfe);
+			reg = SiS_GetReg(SISSR, 0x05);
+			reg = SiS_GetReg(SISSR, 0x05);
 			temp++;
 		}
 	}
@@ -4218,7 +4220,7 @@
 	writel(0x89ABCDEFL, (FBAddress + 8));
 	writel(0xCDEF0123L, (FBAddress + 12));
 
-	inSISIDXREG(SISSR, 0x3b, reg);
+	reg = SiS_GetReg(SISSR, 0x3b);
 	if(reg & 0x01) {
 		if(readl((FBAddress + 12)) == 0xCDEF0123L)
 			return 4;	/* Channel A 128bit */
@@ -4281,13 +4283,13 @@
 		PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
 		PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
 
-		andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
-		orSISIDXREG(SISSR, 0x15, 0x04);  /* Test */
+		SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
+		SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
 		sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
 		if(buswidth == 4)      sr14 |= 0x80;
 		else if(buswidth == 2) sr14 |= 0x40;
-		outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
-		outSISIDXREG(SISSR, 0x14, sr14);
+		SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
+		SiS_SetReg(SISSR, 0x14, sr14);
 
 		BankNumHigh <<= 16;
 		BankNumMid <<= 16;
@@ -4354,13 +4356,13 @@
 	if(!ivideo->SiS_Pr.UseROM)
 		bios = NULL;
 
-	outSISIDXREG(SISSR, 0x05, 0x86);
+	SiS_SetReg(SISSR, 0x05, 0x86);
 
 	if(bios) {
 		if(bios[0x52] & 0x80) {
 			memtype = bios[0x52];
 		} else {
-			inSISIDXREG(SISSR, 0x3a, memtype);
+			memtype = SiS_GetReg(SISSR, 0x3a);
 		}
 		memtype &= 0x07;
 	}
@@ -4384,19 +4386,19 @@
 			v6 = bios[rindex++];
 		}
 	}
-	outSISIDXREG(SISSR, 0x28, v1);
-	outSISIDXREG(SISSR, 0x29, v2);
-	outSISIDXREG(SISSR, 0x2a, v3);
-	outSISIDXREG(SISSR, 0x2e, v4);
-	outSISIDXREG(SISSR, 0x2f, v5);
-	outSISIDXREG(SISSR, 0x30, v6);
+	SiS_SetReg(SISSR, 0x28, v1);
+	SiS_SetReg(SISSR, 0x29, v2);
+	SiS_SetReg(SISSR, 0x2a, v3);
+	SiS_SetReg(SISSR, 0x2e, v4);
+	SiS_SetReg(SISSR, 0x2f, v5);
+	SiS_SetReg(SISSR, 0x30, v6);
 
 	v1 = 0x10;
 	if(bios)
 		v1 = bios[0xa4];
-	outSISIDXREG(SISSR, 0x07, v1);       /* DAC speed */
+	SiS_SetReg(SISSR, 0x07, v1);       /* DAC speed */
 
-	outSISIDXREG(SISSR, 0x11, 0x0f);     /* DDC, power save */
+	SiS_SetReg(SISSR, 0x11, 0x0f);     /* DDC, power save */
 
 	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
 	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
@@ -4413,87 +4415,87 @@
 	}
 	if(ivideo->revision_id >= 0x80)
 		v3 &= 0xfd;
-	outSISIDXREG(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
-	outSISIDXREG(SISSR, 0x16, v2);
-	outSISIDXREG(SISSR, 0x17, v3);
-	outSISIDXREG(SISSR, 0x18, v4);
-	outSISIDXREG(SISSR, 0x19, v5);
-	outSISIDXREG(SISSR, 0x1a, v6);
-	outSISIDXREG(SISSR, 0x1b, v7);
-	outSISIDXREG(SISSR, 0x1c, v8);	   /* ---- */
-	andSISIDXREG(SISSR, 0x15 ,0xfb);
-	orSISIDXREG(SISSR, 0x15, 0x04);
+	SiS_SetReg(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+	SiS_SetReg(SISSR, 0x16, v2);
+	SiS_SetReg(SISSR, 0x17, v3);
+	SiS_SetReg(SISSR, 0x18, v4);
+	SiS_SetReg(SISSR, 0x19, v5);
+	SiS_SetReg(SISSR, 0x1a, v6);
+	SiS_SetReg(SISSR, 0x1b, v7);
+	SiS_SetReg(SISSR, 0x1c, v8);	   /* ---- */
+	SiS_SetRegAND(SISSR, 0x15, 0xfb);
+	SiS_SetRegOR(SISSR, 0x15, 0x04);
 	if(bios) {
 		if(bios[0x53] & 0x02) {
-			orSISIDXREG(SISSR, 0x19, 0x20);
+			SiS_SetRegOR(SISSR, 0x19, 0x20);
 		}
 	}
 	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
 	if(ivideo->revision_id >= 0x80)
 		v1 |= 0x01;
-	outSISIDXREG(SISSR, 0x1f, v1);
-	outSISIDXREG(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
+	SiS_SetReg(SISSR, 0x1f, v1);
+	SiS_SetReg(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
 	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
 	if(bios) {
 		v1 = bios[0xe8];
 		v2 = bios[0xe9];
 		v3 = bios[0xea];
 	}
-	outSISIDXREG(SISSR, 0x23, v1);
-	outSISIDXREG(SISSR, 0x24, v2);
-	outSISIDXREG(SISSR, 0x25, v3);
-	outSISIDXREG(SISSR, 0x21, 0x84);
-	outSISIDXREG(SISSR, 0x22, 0x00);
-	outSISIDXREG(SISCR, 0x37, 0x00);
-	orSISIDXREG(SISPART1, 0x24, 0x01);   /* unlock crt2 */
-	outSISIDXREG(SISPART1, 0x00, 0x00);
+	SiS_SetReg(SISSR, 0x23, v1);
+	SiS_SetReg(SISSR, 0x24, v2);
+	SiS_SetReg(SISSR, 0x25, v3);
+	SiS_SetReg(SISSR, 0x21, 0x84);
+	SiS_SetReg(SISSR, 0x22, 0x00);
+	SiS_SetReg(SISCR, 0x37, 0x00);
+	SiS_SetRegOR(SISPART1, 0x24, 0x01);   /* unlock crt2 */
+	SiS_SetReg(SISPART1, 0x00, 0x00);
 	v1 = 0x40; v2 = 0x11;
 	if(bios) {
 		v1 = bios[0xec];
 		v2 = bios[0xeb];
 	}
-	outSISIDXREG(SISPART1, 0x02, v1);
+	SiS_SetReg(SISPART1, 0x02, v1);
 
 	if(ivideo->revision_id >= 0x80)
 		v2 &= ~0x01;
 
-	inSISIDXREG(SISPART4, 0x00, reg);
+	reg = SiS_GetReg(SISPART4, 0x00);
 	if((reg == 1) || (reg == 2)) {
-		outSISIDXREG(SISCR, 0x37, 0x02);
-		outSISIDXREG(SISPART2, 0x00, 0x1c);
+		SiS_SetReg(SISCR, 0x37, 0x02);
+		SiS_SetReg(SISPART2, 0x00, 0x1c);
 		v4 = 0x00; v5 = 0x00; v6 = 0x10;
 		if(ivideo->SiS_Pr.UseROM) {
 			v4 = bios[0xf5];
 			v5 = bios[0xf6];
 			v6 = bios[0xf7];
 		}
-		outSISIDXREG(SISPART4, 0x0d, v4);
-		outSISIDXREG(SISPART4, 0x0e, v5);
-		outSISIDXREG(SISPART4, 0x10, v6);
-		outSISIDXREG(SISPART4, 0x0f, 0x3f);
-		inSISIDXREG(SISPART4, 0x01, reg);
+		SiS_SetReg(SISPART4, 0x0d, v4);
+		SiS_SetReg(SISPART4, 0x0e, v5);
+		SiS_SetReg(SISPART4, 0x10, v6);
+		SiS_SetReg(SISPART4, 0x0f, 0x3f);
+		reg = SiS_GetReg(SISPART4, 0x01);
 		if(reg >= 0xb0) {
-			inSISIDXREG(SISPART4, 0x23, reg);
+			reg = SiS_GetReg(SISPART4, 0x23);
 			reg &= 0x20;
 			reg <<= 1;
-			outSISIDXREG(SISPART4, 0x23, reg);
+			SiS_SetReg(SISPART4, 0x23, reg);
 		}
 	} else {
 		v2 &= ~0x10;
 	}
-	outSISIDXREG(SISSR, 0x32, v2);
+	SiS_SetReg(SISSR, 0x32, v2);
 
-	andSISIDXREG(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
+	SiS_SetRegAND(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
 
-	inSISIDXREG(SISSR, 0x16, reg);
+	reg = SiS_GetReg(SISSR, 0x16);
 	reg &= 0xc3;
-	outSISIDXREG(SISCR, 0x35, reg);
-	outSISIDXREG(SISCR, 0x83, 0x00);
+	SiS_SetReg(SISCR, 0x35, reg);
+	SiS_SetReg(SISCR, 0x83, 0x00);
 #if !defined(__i386__) && !defined(__x86_64__)
 	if(sisfb_videoram) {
-		outSISIDXREG(SISSR, 0x13, 0x28);  /* ? */
+		SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
 		reg = ((sisfb_videoram >> 10) - 1) | 0x40;
-		outSISIDXREG(SISSR, 0x14, reg);
+		SiS_SetReg(SISSR, 0x14, reg);
 	} else {
 #endif
 		/* Need to map max FB size for finding out about RAM size */
@@ -4506,8 +4508,8 @@
 		} else {
 			printk(KERN_DEBUG
 				"sisfb: Failed to map memory for size detection, assuming 8MB\n");
-			outSISIDXREG(SISSR, 0x13, 0x28);  /* ? */
-			outSISIDXREG(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
+			SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
+			SiS_SetReg(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
 		}
 #if !defined(__i386__) && !defined(__x86_64__)
 	}
@@ -4516,7 +4518,7 @@
 		v1 = bios[0xe6];
 		v2 = bios[0xe7];
 	} else {
-		inSISIDXREG(SISSR, 0x3a, reg);
+		reg = SiS_GetReg(SISSR, 0x3a);
 		if((reg & 0x30) == 0x30) {
 			v1 = 0x04; /* PCI */
 			v2 = 0x92;
@@ -4525,8 +4527,8 @@
 			v2 = 0xb2;
 		}
 	}
-	outSISIDXREG(SISSR, 0x21, v1);
-	outSISIDXREG(SISSR, 0x22, v2);
+	SiS_SetReg(SISSR, 0x21, v1);
+	SiS_SetReg(SISSR, 0x22, v2);
 
 	/* Sense CRT1 */
 	sisfb_sense_crt1(ivideo);
@@ -4539,13 +4541,13 @@
 	ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
-	outSISIDXREG(SISSR, 0x05, 0x86);
+	SiS_SetReg(SISSR, 0x05, 0x86);
 
 	/* Display off */
-	orSISIDXREG(SISSR, 0x01, 0x20);
+	SiS_SetRegOR(SISSR, 0x01, 0x20);
 
 	/* Save mode number in CR34 */
-	outSISIDXREG(SISCR, 0x34, 0x2e);
+	SiS_SetReg(SISCR, 0x34, 0x2e);
 
 	/* Let everyone know what the current mode is */
 	ivideo->modeprechange = 0x2e;
@@ -4568,7 +4570,7 @@
 	u8 reg;
 
 	for(i = 0; i <= (delay * 10 * 36); i++) {
-		inSISIDXREG(SISSR, 0x05, reg);
+		reg = SiS_GetReg(SISSR, 0x05);
 		reg++;
 	}
 }
@@ -4660,7 +4662,7 @@
 	 * - if running on non-x86, there usually is no VGA window
 	 *   at a0000.
 	 */
-	orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
+	SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
 
 	/* Need to map max FB size for finding out about RAM size */
 	mapsize = ivideo->video_size;
@@ -4668,76 +4670,76 @@
 
 	if(!ivideo->video_vbase) {
 		printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
-		outSISIDXREG(SISSR, 0x13, 0x35);
-		outSISIDXREG(SISSR, 0x14, 0x41);
+		SiS_SetReg(SISSR, 0x13, 0x35);
+		SiS_SetReg(SISSR, 0x14, 0x41);
 		/* TODO */
 		return;
 	}
 
 	/* Non-interleaving */
-	outSISIDXREG(SISSR, 0x15, 0x00);
+	SiS_SetReg(SISSR, 0x15, 0x00);
 	/* No tiling */
-	outSISIDXREG(SISSR, 0x1c, 0x00);
+	SiS_SetReg(SISSR, 0x1c, 0x00);
 
 	if(ivideo->chip == XGI_20) {
 
 		channelab = 1;
-		inSISIDXREG(SISCR, 0x97, reg);
+		reg = SiS_GetReg(SISCR, 0x97);
 		if(!(reg & 0x01)) {	/* Single 32/16 */
 			buswidth = 32;
-			outSISIDXREG(SISSR, 0x13, 0xb1);
-			outSISIDXREG(SISSR, 0x14, 0x52);
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x52);
 			sisfb_post_xgi_delay(ivideo, 1);
 			sr14 = 0x02;
 			if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
 				goto bail_out;
 
-			outSISIDXREG(SISSR, 0x13, 0x31);
-			outSISIDXREG(SISSR, 0x14, 0x42);
+			SiS_SetReg(SISSR, 0x13, 0x31);
+			SiS_SetReg(SISSR, 0x14, 0x42);
 			sisfb_post_xgi_delay(ivideo, 1);
 			if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
 				goto bail_out;
 
 			buswidth = 16;
-			outSISIDXREG(SISSR, 0x13, 0xb1);
-			outSISIDXREG(SISSR, 0x14, 0x41);
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x41);
 			sisfb_post_xgi_delay(ivideo, 1);
 			sr14 = 0x01;
 			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
 				goto bail_out;
 			else
-				outSISIDXREG(SISSR, 0x13, 0x31);
+				SiS_SetReg(SISSR, 0x13, 0x31);
 		} else {		/* Dual 16/8 */
 			buswidth = 16;
-			outSISIDXREG(SISSR, 0x13, 0xb1);
-			outSISIDXREG(SISSR, 0x14, 0x41);
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x41);
 			sisfb_post_xgi_delay(ivideo, 1);
 			sr14 = 0x01;
 			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
 				goto bail_out;
 
-			outSISIDXREG(SISSR, 0x13, 0x31);
-			outSISIDXREG(SISSR, 0x14, 0x31);
+			SiS_SetReg(SISSR, 0x13, 0x31);
+			SiS_SetReg(SISSR, 0x14, 0x31);
 			sisfb_post_xgi_delay(ivideo, 1);
 			if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
 				goto bail_out;
 
 			buswidth = 8;
-			outSISIDXREG(SISSR, 0x13, 0xb1);
-			outSISIDXREG(SISSR, 0x14, 0x30);
+			SiS_SetReg(SISSR, 0x13, 0xb1);
+			SiS_SetReg(SISSR, 0x14, 0x30);
 			sisfb_post_xgi_delay(ivideo, 1);
 			sr14 = 0x00;
 			if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
 				goto bail_out;
 			else
-				outSISIDXREG(SISSR, 0x13, 0x31);
+				SiS_SetReg(SISSR, 0x13, 0x31);
 		}
 
 	} else {	/* XGI_40 */
 
-		inSISIDXREG(SISCR, 0x97, reg);
+		reg = SiS_GetReg(SISCR, 0x97);
 		if(!(reg & 0x10)) {
-			inSISIDXREG(SISSR, 0x39, reg);
+			reg = SiS_GetReg(SISSR, 0x39);
 			reg >>= 1;
 		}
 
@@ -4745,52 +4747,52 @@
 			buswidth = 32;
 			if(ivideo->revision_id == 2) {
 				channelab = 2;
-				outSISIDXREG(SISSR, 0x13, 0xa1);
-				outSISIDXREG(SISSR, 0x14, 0x44);
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x44);
 				sr14 = 0x04;
 				sisfb_post_xgi_delay(ivideo, 1);
 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
 					goto bail_out;
 
-				outSISIDXREG(SISSR, 0x13, 0x21);
-				outSISIDXREG(SISSR, 0x14, 0x34);
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x34);
 				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
 					goto bail_out;
 
 				channelab = 1;
-				outSISIDXREG(SISSR, 0x13, 0xa1);
-				outSISIDXREG(SISSR, 0x14, 0x40);
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x40);
 				sr14 = 0x00;
 				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
 					goto bail_out;
 
-				outSISIDXREG(SISSR, 0x13, 0x21);
-				outSISIDXREG(SISSR, 0x14, 0x30);
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x30);
 			} else {
 				channelab = 3;
-				outSISIDXREG(SISSR, 0x13, 0xa1);
-				outSISIDXREG(SISSR, 0x14, 0x4c);
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x4c);
 				sr14 = 0x0c;
 				sisfb_post_xgi_delay(ivideo, 1);
 				if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
 					goto bail_out;
 
 				channelab = 2;
-				outSISIDXREG(SISSR, 0x14, 0x48);
+				SiS_SetReg(SISSR, 0x14, 0x48);
 				sisfb_post_xgi_delay(ivideo, 1);
 				sr14 = 0x08;
 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
 					goto bail_out;
 
-				outSISIDXREG(SISSR, 0x13, 0x21);
-				outSISIDXREG(SISSR, 0x14, 0x3c);
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x3c);
 				sr14 = 0x0c;
 
 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
 					channelab = 3;
 				} else {
 					channelab = 2;
-					outSISIDXREG(SISSR, 0x14, 0x38);
+					SiS_SetReg(SISSR, 0x14, 0x38);
 					sr14 = 0x08;
 				}
 			}
@@ -4801,26 +4803,26 @@
 			buswidth = 64;
 			if(ivideo->revision_id == 2) {
 				channelab = 1;
-				outSISIDXREG(SISSR, 0x13, 0xa1);
-				outSISIDXREG(SISSR, 0x14, 0x52);
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x52);
 				sisfb_post_xgi_delay(ivideo, 1);
 				sr14 = 0x02;
 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
 					goto bail_out;
 
-				outSISIDXREG(SISSR, 0x13, 0x21);
-				outSISIDXREG(SISSR, 0x14, 0x42);
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x42);
 			} else {
 				channelab = 2;
-				outSISIDXREG(SISSR, 0x13, 0xa1);
-				outSISIDXREG(SISSR, 0x14, 0x5a);
+				SiS_SetReg(SISSR, 0x13, 0xa1);
+				SiS_SetReg(SISSR, 0x14, 0x5a);
 				sisfb_post_xgi_delay(ivideo, 1);
 				sr14 = 0x0a;
 				if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
 					goto bail_out;
 
-				outSISIDXREG(SISSR, 0x13, 0x21);
-				outSISIDXREG(SISSR, 0x14, 0x4a);
+				SiS_SetReg(SISSR, 0x13, 0x21);
+				SiS_SetReg(SISSR, 0x14, 0x4a);
 			}
 			sisfb_post_xgi_delay(ivideo, 1);
 
@@ -4828,7 +4830,7 @@
 	}
 
 bail_out:
-	setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
+	SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
 	sisfb_post_xgi_delay(ivideo, 1);
 
 	j = (ivideo->chip == XGI_20) ? 5 : 9;
@@ -4838,13 +4840,13 @@
 
 		reg = (ivideo->chip == XGI_20) ?
 				dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
-		setSISIDXREG(SISSR, 0x13, 0x80, reg);
+		SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
 		sisfb_post_xgi_delay(ivideo, 50);
 
 		ranksize = (ivideo->chip == XGI_20) ?
 				dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
 
-		inSISIDXREG(SISSR, 0x13, reg);
+		reg = SiS_GetReg(SISSR, 0x13);
 		if(reg & 0x80) ranksize <<= 1;
 
 		if(ivideo->chip == XGI_20) {
@@ -4863,7 +4865,7 @@
 
 		if(!reg) continue;
 
-		setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
+		SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
 		sisfb_post_xgi_delay(ivideo, 1);
 
 		if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
@@ -4908,9 +4910,9 @@
 		v2 = ivideo->bios_abase[0x90 + index + 1];
 		v3 = ivideo->bios_abase[0x90 + index + 2];
 	}
-	outSISIDXREG(SISSR, 0x28, v1);
-	outSISIDXREG(SISSR, 0x29, v2);
-	outSISIDXREG(SISSR, 0x2a, v3);
+	SiS_SetReg(SISSR, 0x28, v1);
+	SiS_SetReg(SISSR, 0x29, v2);
+	SiS_SetReg(SISSR, 0x2a, v3);
 	sisfb_post_xgi_delay(ivideo, 0x43);
 	sisfb_post_xgi_delay(ivideo, 0x43);
 	sisfb_post_xgi_delay(ivideo, 0x43);
@@ -4921,9 +4923,9 @@
 		v2 = ivideo->bios_abase[0xb8 + index + 1];
 		v3 = ivideo->bios_abase[0xb8 + index + 2];
 	}
-	outSISIDXREG(SISSR, 0x2e, v1);
-	outSISIDXREG(SISSR, 0x2f, v2);
-	outSISIDXREG(SISSR, 0x30, v3);
+	SiS_SetReg(SISSR, 0x2e, v1);
+	SiS_SetReg(SISSR, 0x2f, v2);
+	SiS_SetReg(SISSR, 0x30, v3);
 	sisfb_post_xgi_delay(ivideo, 0x43);
 	sisfb_post_xgi_delay(ivideo, 0x43);
 	sisfb_post_xgi_delay(ivideo, 0x43);
@@ -4996,29 +4998,29 @@
 	};
 
 	/* VGA enable */
-	reg = inSISREG(SISVGAENABLE) | 0x01;
-	outSISREG(SISVGAENABLE, reg);
+	reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
+	SiS_SetRegByte(SISVGAENABLE, reg);
 
 	/* Misc */
-	reg = inSISREG(SISMISCR) | 0x01;
-	outSISREG(SISMISCW, reg);
+	reg = SiS_GetRegByte(SISMISCR) | 0x01;
+	SiS_SetRegByte(SISMISCW, reg);
 
 	/* Unlock SR */
-	outSISIDXREG(SISSR, 0x05, 0x86);
-	inSISIDXREG(SISSR, 0x05, reg);
+	SiS_SetReg(SISSR, 0x05, 0x86);
+	reg = SiS_GetReg(SISSR, 0x05);
 	if(reg != 0xa1)
 		return 0;
 
 	/* Clear some regs */
 	for(i = 0; i < 0x22; i++) {
 		if(0x06 + i == 0x20) continue;
-		outSISIDXREG(SISSR, 0x06 + i, 0x00);
+		SiS_SetReg(SISSR, 0x06 + i, 0x00);
 	}
 	for(i = 0; i < 0x0b; i++) {
-		outSISIDXREG(SISSR, 0x31 + i, 0x00);
+		SiS_SetReg(SISSR, 0x31 + i, 0x00);
 	}
 	for(i = 0; i < 0x10; i++) {
-		outSISIDXREG(SISCR, 0x30 + i, 0x00);
+		SiS_SetReg(SISCR, 0x30 + i, 0x00);
 	}
 
 	ptr = cs78;
@@ -5026,7 +5028,7 @@
 		ptr = (const u8 *)&bios[0x78];
 	}
 	for(i = 0; i < 3; i++) {
-		outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
+		SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
 	}
 
 	ptr = cs76;
@@ -5034,7 +5036,7 @@
 		ptr = (const u8 *)&bios[0x76];
 	}
 	for(i = 0; i < 2; i++) {
-		outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
+		SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
 	}
 
 	v1 = 0x18; v2 = 0x00;
@@ -5042,83 +5044,83 @@
 		v1 = bios[0x74];
 		v2 = bios[0x75];
 	}
-	outSISIDXREG(SISSR, 0x07, v1);
-	outSISIDXREG(SISSR, 0x11, 0x0f);
-	outSISIDXREG(SISSR, 0x1f, v2);
+	SiS_SetReg(SISSR, 0x07, v1);
+	SiS_SetReg(SISSR, 0x11, 0x0f);
+	SiS_SetReg(SISSR, 0x1f, v2);
 	/* PCI linear mode, RelIO enabled, A0000 decoding disabled */
-	outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
-	outSISIDXREG(SISSR, 0x27, 0x74);
+	SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
+	SiS_SetReg(SISSR, 0x27, 0x74);
 
 	ptr = cs7b;
 	if(ivideo->haveXGIROM) {
 		ptr = (const u8 *)&bios[0x7b];
 	}
 	for(i = 0; i < 3; i++) {
-		outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
+		SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
 	}
 
 	if(ivideo->chip == XGI_40) {
 		if(ivideo->revision_id == 2) {
-			setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
+			SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
 		}
-		outSISIDXREG(SISCR, 0x7d, 0xfe);
-		outSISIDXREG(SISCR, 0x7e, 0x0f);
+		SiS_SetReg(SISCR, 0x7d, 0xfe);
+		SiS_SetReg(SISCR, 0x7e, 0x0f);
 	}
 	if(ivideo->revision_id == 0) {	/* 40 *and* 20? */
-		andSISIDXREG(SISCR, 0x58, 0xd7);
-		inSISIDXREG(SISCR, 0xcb, reg);
+		SiS_SetRegAND(SISCR, 0x58, 0xd7);
+		reg = SiS_GetReg(SISCR, 0xcb);
 		if(reg & 0x20) {
-			setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
+			SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
 		}
 	}
 
 	reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
-	setSISIDXREG(SISCR, 0x38, 0x1f, reg);
+	SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
 
 	if(ivideo->chip == XGI_20) {
-		outSISIDXREG(SISSR, 0x36, 0x70);
+		SiS_SetReg(SISSR, 0x36, 0x70);
 	} else {
-		outSISIDXREG(SISVID, 0x00, 0x86);
-		outSISIDXREG(SISVID, 0x32, 0x00);
-		outSISIDXREG(SISVID, 0x30, 0x00);
-		outSISIDXREG(SISVID, 0x32, 0x01);
-		outSISIDXREG(SISVID, 0x30, 0x00);
-		andSISIDXREG(SISVID, 0x2f, 0xdf);
-		andSISIDXREG(SISCAP, 0x00, 0x3f);
+		SiS_SetReg(SISVID, 0x00, 0x86);
+		SiS_SetReg(SISVID, 0x32, 0x00);
+		SiS_SetReg(SISVID, 0x30, 0x00);
+		SiS_SetReg(SISVID, 0x32, 0x01);
+		SiS_SetReg(SISVID, 0x30, 0x00);
+		SiS_SetRegAND(SISVID, 0x2f, 0xdf);
+		SiS_SetRegAND(SISCAP, 0x00, 0x3f);
 
-		outSISIDXREG(SISPART1, 0x2f, 0x01);
-		outSISIDXREG(SISPART1, 0x00, 0x00);
-		outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
-		outSISIDXREG(SISPART1, 0x2e, 0x08);
-		andSISIDXREG(SISPART1, 0x35, 0x7f);
-		andSISIDXREG(SISPART1, 0x50, 0xfe);
+		SiS_SetReg(SISPART1, 0x2f, 0x01);
+		SiS_SetReg(SISPART1, 0x00, 0x00);
+		SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
+		SiS_SetReg(SISPART1, 0x2e, 0x08);
+		SiS_SetRegAND(SISPART1, 0x35, 0x7f);
+		SiS_SetRegAND(SISPART1, 0x50, 0xfe);
 
-		inSISIDXREG(SISPART4, 0x00, reg);
+		reg = SiS_GetReg(SISPART4, 0x00);
 		if(reg == 1 || reg == 2) {
-			outSISIDXREG(SISPART2, 0x00, 0x1c);
-			outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
-			outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
-			outSISIDXREG(SISPART4, 0x10, bios[0x81]);
-			andSISIDXREG(SISPART4, 0x0f, 0x3f);
+			SiS_SetReg(SISPART2, 0x00, 0x1c);
+			SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
+			SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
+			SiS_SetReg(SISPART4, 0x10, bios[0x81]);
+			SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
 
-			inSISIDXREG(SISPART4, 0x01, reg);
+			reg = SiS_GetReg(SISPART4, 0x01);
 			if((reg & 0xf0) >= 0xb0) {
-				inSISIDXREG(SISPART4, 0x23, reg);
+				reg = SiS_GetReg(SISPART4, 0x23);
 				if(reg & 0x20) reg |= 0x40;
-				outSISIDXREG(SISPART4, 0x23, reg);
+				SiS_SetReg(SISPART4, 0x23, reg);
 				reg = (reg & 0x20) ? 0x02 : 0x00;
-				setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
+				SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
 			}
 		}
 
 		v1 = bios[0x77];
 
-		inSISIDXREG(SISSR, 0x3b, reg);
+		reg = SiS_GetReg(SISSR, 0x3b);
 		if(reg & 0x02) {
-			inSISIDXREG(SISSR, 0x3a, reg);
+			reg = SiS_GetReg(SISSR, 0x3a);
 			v2 = (reg & 0x30) >> 3;
 			if(!(v2 & 0x04)) v2 ^= 0x02;
-			inSISIDXREG(SISSR, 0x39, reg);
+			reg = SiS_GetReg(SISSR, 0x39);
 			if(reg & 0x80) v2 |= 0x80;
 			v2 |= 0x01;
 
@@ -5151,36 +5153,36 @@
 					v2 |= 0x08;
 				}
 			}
-			setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
+			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
 		}
-		outSISIDXREG(SISSR, 0x22, v1);
+		SiS_SetReg(SISSR, 0x22, v1);
 
 		if(ivideo->revision_id == 2) {
-			inSISIDXREG(SISSR, 0x3b, v1);
-			inSISIDXREG(SISSR, 0x3a, v2);
+			v1 = SiS_GetReg(SISSR, 0x3b);
+			v2 = SiS_GetReg(SISSR, 0x3a);
 			regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
 			if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
-				setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+				SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
 
 			if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
 				/* TODO: set CR5f &0xf1 | 0x01 for version 6570
 				 * of nforce 2 ROM
 				 */
 				if(0)
-					setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+					SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
 				pci_dev_put(mypdev);
 			}
 		}
 
 		v1 = 0x30;
-		inSISIDXREG(SISSR, 0x3b, reg);
-		inSISIDXREG(SISCR, 0x5f, v2);
+		reg = SiS_GetReg(SISSR, 0x3b);
+		v2 = SiS_GetReg(SISCR, 0x5f);
 		if((!(reg & 0x02)) && (v2 & 0x0e))
 			v1 |= 0x08;
-		outSISIDXREG(SISSR, 0x27, v1);
+		SiS_SetReg(SISSR, 0x27, v1);
 
 		if(bios[0x64] & 0x01) {
-			setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
+			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
 		}
 
 		v1 = bios[0x4f7];
@@ -5188,27 +5190,27 @@
 		regd = (regd >> 20) & 0x0f;
 		if(regd == 1) {
 			v1 &= 0xfc;
-			orSISIDXREG(SISCR, 0x5f, 0x08);
+			SiS_SetRegOR(SISCR, 0x5f, 0x08);
 		}
-		outSISIDXREG(SISCR, 0x48, v1);
+		SiS_SetReg(SISCR, 0x48, v1);
 
-		setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
-		setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
-		setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
-		setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
-		setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
-		outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
-		setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
-		outSISIDXREG(SISCR, 0x74, 0xd0);
-		setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
-		setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
-		setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
+		SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
+		SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
+		SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
+		SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
+		SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
+		SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
+		SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
+		SiS_SetReg(SISCR, 0x74, 0xd0);
+		SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
+		SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
+		SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
 		v1 = bios[0x501];
 		if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
 			v1 = 0xf0;
 			pci_dev_put(mypdev);
 		}
-		outSISIDXREG(SISCR, 0x77, v1);
+		SiS_SetReg(SISCR, 0x77, v1);
 	}
 
 	/* RAM type */
@@ -5219,14 +5221,14 @@
 	if(ivideo->haveXGIROM) {
 		v1 = bios[0x140 + regb];
 	}
-	outSISIDXREG(SISCR, 0x6d, v1);
+	SiS_SetReg(SISCR, 0x6d, v1);
 
 	ptr = cs128;
 	if(ivideo->haveXGIROM) {
 		ptr = (const u8 *)&bios[0x128];
 	}
 	for(i = 0, j = 0; i < 3; i++, j += 8) {
-		outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
+		SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
 	}
 
 	ptr  = cs31a;
@@ -5250,14 +5252,14 @@
 			if(regd & 0x01) reg |= 0x04;
 			if(regd & 0x02) reg |= 0x08;
 			regd >>= 2;
-			outSISIDXREG(SISCR, rega, reg);
-			inSISIDXREG(SISCR, rega, reg);
-			inSISIDXREG(SISCR, rega, reg);
+			SiS_SetReg(SISCR, rega, reg);
+			reg = SiS_GetReg(SISCR, rega);
+			reg = SiS_GetReg(SISCR, rega);
 			reg += 0x10;
 		}
 	}
 
-	andSISIDXREG(SISCR, 0x6e, 0xfc);
+	SiS_SetRegAND(SISCR, 0x6e, 0xfc);
 
 	ptr  = NULL;
 	if(ivideo->haveXGIROM) {
@@ -5265,7 +5267,7 @@
 		ptr  = (const u8 *)&bios[index];
 	}
 	for(i = 0; i < 4; i++) {
-		setSISIDXREG(SISCR, 0x6e, 0xfc, i);
+		SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
 		reg = 0x00;
 		for(j = 0; j < 2; j++) {
 			regd = 0;
@@ -5279,9 +5281,9 @@
 				if(regd & 0x01) reg |= 0x01;
 				if(regd & 0x02) reg |= 0x02;
 				regd >>= 2;
-				outSISIDXREG(SISCR, 0x6f, reg);
-				inSISIDXREG(SISCR, 0x6f, reg);
-				inSISIDXREG(SISCR, 0x6f, reg);
+				SiS_SetReg(SISCR, 0x6f, reg);
+				reg = SiS_GetReg(SISCR, 0x6f);
+				reg = SiS_GetReg(SISCR, 0x6f);
 				reg += 0x08;
 			}
 		}
@@ -5292,10 +5294,10 @@
 		ptr  = (const u8 *)&bios[0x148];
 	}
 	for(i = 0, j = 0; i < 2; i++, j += 8) {
-		outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
+		SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
 	}
 
-	andSISIDXREG(SISCR, 0x89, 0x8f);
+	SiS_SetRegAND(SISCR, 0x89, 0x8f);
 
 	ptr  = cs45a;
 	if(ivideo->haveXGIROM) {
@@ -5309,9 +5311,9 @@
 		if(regd & 0x01) reg |= 0x01;
 		if(regd & 0x02) reg |= 0x02;
 		regd >>= 2;
-		outSISIDXREG(SISCR, 0x89, reg);
-		inSISIDXREG(SISCR, 0x89, reg);
-		inSISIDXREG(SISCR, 0x89, reg);
+		SiS_SetReg(SISCR, 0x89, reg);
+		reg = SiS_GetReg(SISCR, 0x89);
+		reg = SiS_GetReg(SISCR, 0x89);
 		reg += 0x10;
 	}
 
@@ -5322,27 +5324,27 @@
 		v3 = bios[0x120 + regb];
 		v4 = bios[0x1ca];
 	}
-	outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
-	outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
-	orSISIDXREG(SISCR, 0x40, v1 & 0x80);
-	outSISIDXREG(SISCR, 0x41, v2);
+	SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
+	SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
+	SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
+	SiS_SetReg(SISCR, 0x41, v2);
 
 	ptr  = cs170;
 	if(ivideo->haveXGIROM) {
 		ptr  = (const u8 *)&bios[0x170];
 	}
 	for(i = 0, j = 0; i < 7; i++, j += 8) {
-		outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
+		SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
 	}
 
-	outSISIDXREG(SISCR, 0x59, v3);
+	SiS_SetReg(SISCR, 0x59, v3);
 
 	ptr  = cs1a8;
 	if(ivideo->haveXGIROM) {
 		ptr  = (const u8 *)&bios[0x1a8];
 	}
 	for(i = 0, j = 0; i < 3; i++, j += 8) {
-		outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
+		SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
 	}
 
 	ptr  = cs100;
@@ -5350,27 +5352,27 @@
 		ptr  = (const u8 *)&bios[0x100];
 	}
 	for(i = 0, j = 0; i < 2; i++, j += 8) {
-		outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
+		SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
 	}
 
-	outSISIDXREG(SISCR, 0xcf, v4);
+	SiS_SetReg(SISCR, 0xcf, v4);
 
-	outSISIDXREG(SISCR, 0x83, 0x09);
-	outSISIDXREG(SISCR, 0x87, 0x00);
+	SiS_SetReg(SISCR, 0x83, 0x09);
+	SiS_SetReg(SISCR, 0x87, 0x00);
 
 	if(ivideo->chip == XGI_40) {
 		if( (ivideo->revision_id == 1) ||
 		    (ivideo->revision_id == 2) ) {
-			outSISIDXREG(SISCR, 0x8c, 0x87);
+			SiS_SetReg(SISCR, 0x8c, 0x87);
 		}
 	}
 
-	outSISIDXREG(SISSR, 0x17, 0x00);
-	outSISIDXREG(SISSR, 0x1a, 0x87);
+	SiS_SetReg(SISSR, 0x17, 0x00);
+	SiS_SetReg(SISSR, 0x1a, 0x87);
 
 	if(ivideo->chip == XGI_20) {
-		outSISIDXREG(SISSR, 0x15, 0x00);
-		outSISIDXREG(SISSR, 0x1c, 0x00);
+		SiS_SetReg(SISSR, 0x15, 0x00);
+		SiS_SetReg(SISSR, 0x1c, 0x00);
 	}
 
 	ramtype = 0x00; v1 = 0x10;
@@ -5380,16 +5382,16 @@
 	}
 	if(!(ramtype & 0x80)) {
 		if(ivideo->chip == XGI_20) {
-			outSISIDXREG(SISCR, 0x97, v1);
-			inSISIDXREG(SISCR, 0x97, reg);
+			SiS_SetReg(SISCR, 0x97, v1);
+			reg = SiS_GetReg(SISCR, 0x97);
 			if(reg & 0x10) {
 				ramtype = (reg & 0x01) << 1;
 			}
 		} else {
-			inSISIDXREG(SISSR, 0x39, reg);
+			reg = SiS_GetReg(SISSR, 0x39);
 			ramtype = reg & 0x02;
 			if(!(ramtype)) {
-				inSISIDXREG(SISSR, 0x3a, reg);
+				reg = SiS_GetReg(SISSR, 0x3a);
 				ramtype = (reg >> 1) & 0x01;
 			}
 		}
@@ -5410,55 +5412,55 @@
 				v2 = bios[regb + 0x160];
 				v3 = bios[regb + 0x168];
 			}
-			outSISIDXREG(SISCR, 0x82, v1);
-			outSISIDXREG(SISCR, 0x85, v2);
-			outSISIDXREG(SISCR, 0x86, v3);
+			SiS_SetReg(SISCR, 0x82, v1);
+			SiS_SetReg(SISCR, 0x85, v2);
+			SiS_SetReg(SISCR, 0x86, v3);
 		} else {
-			outSISIDXREG(SISCR, 0x82, 0x88);
-			outSISIDXREG(SISCR, 0x86, 0x00);
-			inSISIDXREG(SISCR, 0x86, reg);
-			outSISIDXREG(SISCR, 0x86, 0x88);
-			inSISIDXREG(SISCR, 0x86, reg);
-			outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
-			outSISIDXREG(SISCR, 0x82, 0x77);
-			outSISIDXREG(SISCR, 0x85, 0x00);
-			inSISIDXREG(SISCR, 0x85, reg);
-			outSISIDXREG(SISCR, 0x85, 0x88);
-			inSISIDXREG(SISCR, 0x85, reg);
-			outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
-			outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+			SiS_SetReg(SISCR, 0x82, 0x88);
+			SiS_SetReg(SISCR, 0x86, 0x00);
+			reg = SiS_GetReg(SISCR, 0x86);
+			SiS_SetReg(SISCR, 0x86, 0x88);
+			reg = SiS_GetReg(SISCR, 0x86);
+			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
+			SiS_SetReg(SISCR, 0x82, 0x77);
+			SiS_SetReg(SISCR, 0x85, 0x00);
+			reg = SiS_GetReg(SISCR, 0x85);
+			SiS_SetReg(SISCR, 0x85, 0x88);
+			reg = SiS_GetReg(SISCR, 0x85);
+			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
+			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
 		}
 		if(ivideo->chip == XGI_40) {
-			outSISIDXREG(SISCR, 0x97, 0x00);
+			SiS_SetReg(SISCR, 0x97, 0x00);
 		}
-		outSISIDXREG(SISCR, 0x98, 0x01);
-		outSISIDXREG(SISCR, 0x9a, 0x02);
+		SiS_SetReg(SISCR, 0x98, 0x01);
+		SiS_SetReg(SISCR, 0x9a, 0x02);
 
-		outSISIDXREG(SISSR, 0x18, 0x01);
+		SiS_SetReg(SISSR, 0x18, 0x01);
 		if((ivideo->chip == XGI_20) ||
 		   (ivideo->revision_id == 2)) {
-			outSISIDXREG(SISSR, 0x19, 0x40);
+			SiS_SetReg(SISSR, 0x19, 0x40);
 		} else {
-			outSISIDXREG(SISSR, 0x19, 0x20);
+			SiS_SetReg(SISSR, 0x19, 0x20);
 		}
-		outSISIDXREG(SISSR, 0x16, 0x00);
-		outSISIDXREG(SISSR, 0x16, 0x80);
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
 		if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
 			sisfb_post_xgi_delay(ivideo, 0x43);
 			sisfb_post_xgi_delay(ivideo, 0x43);
 			sisfb_post_xgi_delay(ivideo, 0x43);
-			outSISIDXREG(SISSR, 0x18, 0x00);
+			SiS_SetReg(SISSR, 0x18, 0x00);
 			if((ivideo->chip == XGI_20) ||
 			   (ivideo->revision_id == 2)) {
-				outSISIDXREG(SISSR, 0x19, 0x40);
+				SiS_SetReg(SISSR, 0x19, 0x40);
 			} else {
-				outSISIDXREG(SISSR, 0x19, 0x20);
+				SiS_SetReg(SISSR, 0x19, 0x20);
 			}
 		} else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
-			/* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
+			/* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
 		}
-		outSISIDXREG(SISSR, 0x16, 0x00);
-		outSISIDXREG(SISSR, 0x16, 0x80);
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
 		sisfb_post_xgi_delay(ivideo, 4);
 		v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
 		if(ivideo->haveXGIROM) {
@@ -5469,74 +5471,74 @@
 			v4 = bios[index + 2];
 			v5 = bios[index + 3];
 		}
-		outSISIDXREG(SISSR, 0x18, v1);
-		outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
-		outSISIDXREG(SISSR, 0x16, v2);
-		outSISIDXREG(SISSR, 0x16, v3);
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
+		SiS_SetReg(SISSR, 0x16, v2);
+		SiS_SetReg(SISSR, 0x16, v3);
 		sisfb_post_xgi_delay(ivideo, 0x43);
-		outSISIDXREG(SISSR, 0x1b, 0x03);
+		SiS_SetReg(SISSR, 0x1b, 0x03);
 		sisfb_post_xgi_delay(ivideo, 0x22);
-		outSISIDXREG(SISSR, 0x18, v1);
-		outSISIDXREG(SISSR, 0x19, 0x00);
-		outSISIDXREG(SISSR, 0x16, v4);
-		outSISIDXREG(SISSR, 0x16, v5);
-		outSISIDXREG(SISSR, 0x1b, 0x00);
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, 0x00);
+		SiS_SetReg(SISSR, 0x16, v4);
+		SiS_SetReg(SISSR, 0x16, v5);
+		SiS_SetReg(SISSR, 0x1b, 0x00);
 		break;
 	case 1:
-		outSISIDXREG(SISCR, 0x82, 0x77);
-		outSISIDXREG(SISCR, 0x86, 0x00);
-		inSISIDXREG(SISCR, 0x86, reg);
-		outSISIDXREG(SISCR, 0x86, 0x88);
-		inSISIDXREG(SISCR, 0x86, reg);
+		SiS_SetReg(SISCR, 0x82, 0x77);
+		SiS_SetReg(SISCR, 0x86, 0x00);
+		reg = SiS_GetReg(SISCR, 0x86);
+		SiS_SetReg(SISCR, 0x86, 0x88);
+		reg = SiS_GetReg(SISCR, 0x86);
 		v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
 		if(ivideo->haveXGIROM) {
 			v1 = bios[regb + 0x168];
 			v2 = bios[regb + 0x160];
 			v3 = bios[regb + 0x158];
 		}
-		outSISIDXREG(SISCR, 0x86, v1);
-		outSISIDXREG(SISCR, 0x82, 0x77);
-		outSISIDXREG(SISCR, 0x85, 0x00);
-		inSISIDXREG(SISCR, 0x85, reg);
-		outSISIDXREG(SISCR, 0x85, 0x88);
-		inSISIDXREG(SISCR, 0x85, reg);
-		outSISIDXREG(SISCR, 0x85, v2);
-		outSISIDXREG(SISCR, 0x82, v3);
-		outSISIDXREG(SISCR, 0x98, 0x01);
-		outSISIDXREG(SISCR, 0x9a, 0x02);
+		SiS_SetReg(SISCR, 0x86, v1);
+		SiS_SetReg(SISCR, 0x82, 0x77);
+		SiS_SetReg(SISCR, 0x85, 0x00);
+		reg = SiS_GetReg(SISCR, 0x85);
+		SiS_SetReg(SISCR, 0x85, 0x88);
+		reg = SiS_GetReg(SISCR, 0x85);
+		SiS_SetReg(SISCR, 0x85, v2);
+		SiS_SetReg(SISCR, 0x82, v3);
+		SiS_SetReg(SISCR, 0x98, 0x01);
+		SiS_SetReg(SISCR, 0x9a, 0x02);
 
-		outSISIDXREG(SISSR, 0x28, 0x64);
-		outSISIDXREG(SISSR, 0x29, 0x63);
+		SiS_SetReg(SISSR, 0x28, 0x64);
+		SiS_SetReg(SISSR, 0x29, 0x63);
 		sisfb_post_xgi_delay(ivideo, 15);
-		outSISIDXREG(SISSR, 0x18, 0x00);
-		outSISIDXREG(SISSR, 0x19, 0x20);
-		outSISIDXREG(SISSR, 0x16, 0x00);
-		outSISIDXREG(SISSR, 0x16, 0x80);
-		outSISIDXREG(SISSR, 0x18, 0xc5);
-		outSISIDXREG(SISSR, 0x19, 0x23);
-		outSISIDXREG(SISSR, 0x16, 0x00);
-		outSISIDXREG(SISSR, 0x16, 0x80);
+		SiS_SetReg(SISSR, 0x18, 0x00);
+		SiS_SetReg(SISSR, 0x19, 0x20);
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
+		SiS_SetReg(SISSR, 0x18, 0xc5);
+		SiS_SetReg(SISSR, 0x19, 0x23);
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
 		sisfb_post_xgi_delay(ivideo, 1);
-		outSISIDXREG(SISCR, 0x97,0x11);
+		SiS_SetReg(SISCR, 0x97, 0x11);
 		sisfb_post_xgi_setclocks(ivideo, regb);
 		sisfb_post_xgi_delay(ivideo, 0x46);
-		outSISIDXREG(SISSR, 0x18, 0xc5);
-		outSISIDXREG(SISSR, 0x19, 0x23);
-		outSISIDXREG(SISSR, 0x16, 0x00);
-		outSISIDXREG(SISSR, 0x16, 0x80);
+		SiS_SetReg(SISSR, 0x18, 0xc5);
+		SiS_SetReg(SISSR, 0x19, 0x23);
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
 		sisfb_post_xgi_delay(ivideo, 1);
-		outSISIDXREG(SISSR, 0x1b, 0x04);
+		SiS_SetReg(SISSR, 0x1b, 0x04);
 		sisfb_post_xgi_delay(ivideo, 1);
-		outSISIDXREG(SISSR, 0x1b, 0x00);
+		SiS_SetReg(SISSR, 0x1b, 0x00);
 		sisfb_post_xgi_delay(ivideo, 1);
 		v1 = 0x31;
 		if(ivideo->haveXGIROM) {
 			v1 = bios[0xf0];
 		}
-		outSISIDXREG(SISSR, 0x18, v1);
-		outSISIDXREG(SISSR, 0x19, 0x06);
-		outSISIDXREG(SISSR, 0x16, 0x04);
-		outSISIDXREG(SISSR, 0x16, 0x84);
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, 0x06);
+		SiS_SetReg(SISSR, 0x16, 0x04);
+		SiS_SetReg(SISSR, 0x16, 0x84);
 		sisfb_post_xgi_delay(ivideo, 1);
 		break;
 	default:
@@ -5544,85 +5546,85 @@
 		if((ivideo->chip == XGI_40) &&
 		   ((ivideo->revision_id == 1) ||
 		    (ivideo->revision_id == 2))) {
-			outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
-			outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
-			outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
+			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
+			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
 		} else {
-			outSISIDXREG(SISCR, 0x82, 0x88);
-			outSISIDXREG(SISCR, 0x86, 0x00);
-			inSISIDXREG(SISCR, 0x86, reg);
-			outSISIDXREG(SISCR, 0x86, 0x88);
-			outSISIDXREG(SISCR, 0x82, 0x77);
-			outSISIDXREG(SISCR, 0x85, 0x00);
-			inSISIDXREG(SISCR, 0x85, reg);
-			outSISIDXREG(SISCR, 0x85, 0x88);
-			inSISIDXREG(SISCR, 0x85, reg);
+			SiS_SetReg(SISCR, 0x82, 0x88);
+			SiS_SetReg(SISCR, 0x86, 0x00);
+			reg = SiS_GetReg(SISCR, 0x86);
+			SiS_SetReg(SISCR, 0x86, 0x88);
+			SiS_SetReg(SISCR, 0x82, 0x77);
+			SiS_SetReg(SISCR, 0x85, 0x00);
+			reg = SiS_GetReg(SISCR, 0x85);
+			SiS_SetReg(SISCR, 0x85, 0x88);
+			reg = SiS_GetReg(SISCR, 0x85);
 			v1 = cs160[regb]; v2 = cs158[regb];
 			if(ivideo->haveXGIROM) {
 				v1 = bios[regb + 0x160];
 				v2 = bios[regb + 0x158];
 			}
-			outSISIDXREG(SISCR, 0x85, v1);
-			outSISIDXREG(SISCR, 0x82, v2);
+			SiS_SetReg(SISCR, 0x85, v1);
+			SiS_SetReg(SISCR, 0x82, v2);
 		}
 		if(ivideo->chip == XGI_40) {
-			outSISIDXREG(SISCR, 0x97, 0x11);
+			SiS_SetReg(SISCR, 0x97, 0x11);
 		}
 		if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
-			outSISIDXREG(SISCR, 0x98, 0x01);
+			SiS_SetReg(SISCR, 0x98, 0x01);
 		} else {
-			outSISIDXREG(SISCR, 0x98, 0x03);
+			SiS_SetReg(SISCR, 0x98, 0x03);
 		}
-		outSISIDXREG(SISCR, 0x9a, 0x02);
+		SiS_SetReg(SISCR, 0x9a, 0x02);
 
 		if(ivideo->chip == XGI_40) {
-			outSISIDXREG(SISSR, 0x18, 0x01);
+			SiS_SetReg(SISSR, 0x18, 0x01);
 		} else {
-			outSISIDXREG(SISSR, 0x18, 0x00);
+			SiS_SetReg(SISSR, 0x18, 0x00);
 		}
-		outSISIDXREG(SISSR, 0x19, 0x40);
-		outSISIDXREG(SISSR, 0x16, 0x00);
-		outSISIDXREG(SISSR, 0x16, 0x80);
+		SiS_SetReg(SISSR, 0x19, 0x40);
+		SiS_SetReg(SISSR, 0x16, 0x00);
+		SiS_SetReg(SISSR, 0x16, 0x80);
 		if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
 			sisfb_post_xgi_delay(ivideo, 0x43);
 			sisfb_post_xgi_delay(ivideo, 0x43);
 			sisfb_post_xgi_delay(ivideo, 0x43);
-			outSISIDXREG(SISSR, 0x18, 0x00);
-			outSISIDXREG(SISSR, 0x19, 0x40);
-			outSISIDXREG(SISSR, 0x16, 0x00);
-			outSISIDXREG(SISSR, 0x16, 0x80);
+			SiS_SetReg(SISSR, 0x18, 0x00);
+			SiS_SetReg(SISSR, 0x19, 0x40);
+			SiS_SetReg(SISSR, 0x16, 0x00);
+			SiS_SetReg(SISSR, 0x16, 0x80);
 		}
 		sisfb_post_xgi_delay(ivideo, 4);
 		v1 = 0x31;
 		if(ivideo->haveXGIROM) {
 			v1 = bios[0xf0];
 		}
-		outSISIDXREG(SISSR, 0x18, v1);
-		outSISIDXREG(SISSR, 0x19, 0x01);
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, 0x01);
 		if(ivideo->chip == XGI_40) {
-			outSISIDXREG(SISSR, 0x16, bios[0x53e]);
-			outSISIDXREG(SISSR, 0x16, bios[0x53f]);
+			SiS_SetReg(SISSR, 0x16, bios[0x53e]);
+			SiS_SetReg(SISSR, 0x16, bios[0x53f]);
 		} else {
-			outSISIDXREG(SISSR, 0x16, 0x05);
-			outSISIDXREG(SISSR, 0x16, 0x85);
+			SiS_SetReg(SISSR, 0x16, 0x05);
+			SiS_SetReg(SISSR, 0x16, 0x85);
 		}
 		sisfb_post_xgi_delay(ivideo, 0x43);
 		if(ivideo->chip == XGI_40) {
-			outSISIDXREG(SISSR, 0x1b, 0x01);
+			SiS_SetReg(SISSR, 0x1b, 0x01);
 		} else {
-			outSISIDXREG(SISSR, 0x1b, 0x03);
+			SiS_SetReg(SISSR, 0x1b, 0x03);
 		}
 		sisfb_post_xgi_delay(ivideo, 0x22);
-		outSISIDXREG(SISSR, 0x18, v1);
-		outSISIDXREG(SISSR, 0x19, 0x00);
+		SiS_SetReg(SISSR, 0x18, v1);
+		SiS_SetReg(SISSR, 0x19, 0x00);
 		if(ivideo->chip == XGI_40) {
-			outSISIDXREG(SISSR, 0x16, bios[0x540]);
-			outSISIDXREG(SISSR, 0x16, bios[0x541]);
+			SiS_SetReg(SISSR, 0x16, bios[0x540]);
+			SiS_SetReg(SISSR, 0x16, bios[0x541]);
 		} else {
-			outSISIDXREG(SISSR, 0x16, 0x05);
-			outSISIDXREG(SISSR, 0x16, 0x85);
+			SiS_SetReg(SISSR, 0x16, 0x05);
+			SiS_SetReg(SISSR, 0x16, 0x85);
 		}
-		outSISIDXREG(SISSR, 0x1b, 0x00);
+		SiS_SetReg(SISSR, 0x1b, 0x00);
 	}
 
 	regb = 0;	/* ! */
@@ -5630,7 +5632,7 @@
 	if(ivideo->haveXGIROM) {
 		v1 = bios[0x110 + regb];
 	}
-	outSISIDXREG(SISSR, 0x1b, v1);
+	SiS_SetReg(SISSR, 0x1b, v1);
 
 	/* RAM size */
 	v1 = 0x00; v2 = 0x00;
@@ -5642,8 +5644,8 @@
 	regd = 1 << regb;
 	if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
 
-		outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
-		outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
+		SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
+		SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
 
 	} else {
 
@@ -5655,24 +5657,24 @@
 		ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
 		SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
-		outSISIDXREG(SISSR, 0x05, 0x86);
+		SiS_SetReg(SISSR, 0x05, 0x86);
 
 		/* Disable read-cache */
-		andSISIDXREG(SISSR, 0x21, 0xdf);
+		SiS_SetRegAND(SISSR, 0x21, 0xdf);
 		sisfb_post_xgi_ramsize(ivideo);
 		/* Enable read-cache */
-		orSISIDXREG(SISSR, 0x21, 0x20);
+		SiS_SetRegOR(SISSR, 0x21, 0x20);
 
 	}
 
 #if 0
 	printk(KERN_DEBUG "-----------------\n");
 	for(i = 0; i < 0xff; i++) {
-		inSISIDXREG(SISCR, i, reg);
+		reg = SiS_GetReg(SISCR, i);
 		printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
 	}
 	for(i = 0; i < 0x40; i++) {
-		inSISIDXREG(SISSR, i, reg);
+		reg = SiS_GetReg(SISSR, i);
 		printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
 	}
 	printk(KERN_DEBUG "-----------------\n");
@@ -5680,13 +5682,13 @@
 
 	/* Sense CRT1 */
 	if(ivideo->chip == XGI_20) {
-		orSISIDXREG(SISCR, 0x32, 0x20);
+		SiS_SetRegOR(SISCR, 0x32, 0x20);
 	} else {
-		inSISIDXREG(SISPART4, 0x00, reg);
+		reg = SiS_GetReg(SISPART4, 0x00);
 		if((reg == 1) || (reg == 2)) {
 			sisfb_sense_crt1(ivideo);
 		} else {
-			orSISIDXREG(SISCR, 0x32, 0x20);
+			SiS_SetRegOR(SISCR, 0x32, 0x20);
 		}
 	}
 
@@ -5697,20 +5699,20 @@
 	ivideo->curFSTN = ivideo->curDSTN = 0;
 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
-	outSISIDXREG(SISSR, 0x05, 0x86);
+	SiS_SetReg(SISSR, 0x05, 0x86);
 
 	/* Display off */
-	orSISIDXREG(SISSR, 0x01, 0x20);
+	SiS_SetRegOR(SISSR, 0x01, 0x20);
 
 	/* Save mode number in CR34 */
-	outSISIDXREG(SISCR, 0x34, 0x2e);
+	SiS_SetReg(SISCR, 0x34, 0x2e);
 
 	/* Let everyone know what the current mode is */
 	ivideo->modeprechange = 0x2e;
 
 	if(ivideo->chip == XGI_40) {
-		inSISIDXREG(SISCR, 0xca, reg);
-		inSISIDXREG(SISCR, 0xcc, v1);
+		reg = SiS_GetReg(SISCR, 0xca);
+		v1 = SiS_GetReg(SISCR, 0xcc);
 		if((reg & 0x10) && (!(v1 & 0x04))) {
 			printk(KERN_ERR
 				"sisfb: Please connect power to the card.\n");
@@ -5953,7 +5955,7 @@
 	}
 #endif
 
-	outSISIDXREG(SISSR, 0x05, 0x86);
+	SiS_SetReg(SISSR, 0x05, 0x86);
 
 	if( (!ivideo->sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
@@ -5961,13 +5963,13 @@
 #endif
 						   ) {
 		for(i = 0x30; i <= 0x3f; i++) {
-			outSISIDXREG(SISCR, i, 0x00);
+			SiS_SetReg(SISCR, i, 0x00);
 		}
 	}
 
 	/* Find out about current video mode */
 	ivideo->modeprechange = 0x03;
-	inSISIDXREG(SISCR, 0x34, reg);
+	reg = SiS_GetReg(SISCR, 0x34);
 	if(reg & 0x7f) {
 		ivideo->modeprechange = reg & 0x7f;
 	} else if(ivideo->sisvga_enabled) {
@@ -6064,9 +6066,9 @@
 	if((ivideo->sisfb_mode_idx < 0) ||
 	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
 		/* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
-		orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
+		SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
 		/* Enable 2D accelerator engine */
-		orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
+		SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
 	}
 
 	if(sisfb_pdc != 0xff) {
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
new file mode 100644
index 0000000..020589a
--- /dev/null
+++ b/drivers/video/udlfb.c
@@ -0,0 +1,1879 @@
+/*
+ * udlfb.c -- Framebuffer driver for DisplayLink USB controller
+ *
+ * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
+ * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
+ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
+ * usb-skeleton by GregKH.
+ *
+ * Device-specific portions based on information from Displaylink, with work
+ * from Florian Echtler, Henrik Bjerregaard Pedersen, and others.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <video/udlfb.h>
+#include "edid.h"
+
+static struct fb_fix_screeninfo dlfb_fix = {
+	.id =           "udlfb",
+	.type =         FB_TYPE_PACKED_PIXELS,
+	.visual =       FB_VISUAL_TRUECOLOR,
+	.xpanstep =     0,
+	.ypanstep =     0,
+	.ywrapstep =    0,
+	.accel =        FB_ACCEL_NONE,
+};
+
+static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+		FBINFO_VIRTFB |
+		FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
+
+/*
+ * There are many DisplayLink-based products, all with unique PIDs. We are able
+ * to support all volume ones (circa 2009) with a single driver, so we match
+ * globally on VID. TODO: Probe() needs to detect when we might be running
+ * "future" chips, and bail on those, so a compatible driver can match.
+ */
+static struct usb_device_id id_table[] = {
+	{.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
+	{},
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* module options */
+static int console;   /* Optionally allow fbcon to consume first framebuffer */
+static int fb_defio;  /* Optionally enable experimental fb_defio mmap support */
+
+/* dlfb keeps a list of urbs for efficient bulk transfers */
+static void dlfb_urb_completion(struct urb *urb);
+static struct urb *dlfb_get_urb(struct dlfb_data *dev);
+static int dlfb_submit_urb(struct dlfb_data *dev, struct urb * urb, size_t len);
+static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size);
+static void dlfb_free_urb_list(struct dlfb_data *dev);
+
+/*
+ * All DisplayLink bulk operations start with 0xAF, followed by specific code
+ * All operations are written to buffers which then later get sent to device
+ */
+static char *dlfb_set_register(char *buf, u8 reg, u8 val)
+{
+	*buf++ = 0xAF;
+	*buf++ = 0x20;
+	*buf++ = reg;
+	*buf++ = val;
+	return buf;
+}
+
+static char *dlfb_vidreg_lock(char *buf)
+{
+	return dlfb_set_register(buf, 0xFF, 0x00);
+}
+
+static char *dlfb_vidreg_unlock(char *buf)
+{
+	return dlfb_set_register(buf, 0xFF, 0xFF);
+}
+
+/*
+ * On/Off for driving the DisplayLink framebuffer to the display
+ *  0x00 H and V sync on
+ *  0x01 H and V sync off (screen blank but powered)
+ *  0x07 DPMS powerdown (requires modeset to come back)
+ */
+static char *dlfb_enable_hvsync(char *buf, bool enable)
+{
+	if (enable)
+		return dlfb_set_register(buf, 0x1F, 0x00);
+	else
+		return dlfb_set_register(buf, 0x1F, 0x07);
+}
+
+static char *dlfb_set_color_depth(char *buf, u8 selection)
+{
+	return dlfb_set_register(buf, 0x00, selection);
+}
+
+static char *dlfb_set_base16bpp(char *wrptr, u32 base)
+{
+	/* the base pointer is 16 bits wide, 0x20 is hi byte. */
+	wrptr = dlfb_set_register(wrptr, 0x20, base >> 16);
+	wrptr = dlfb_set_register(wrptr, 0x21, base >> 8);
+	return dlfb_set_register(wrptr, 0x22, base);
+}
+
+/*
+ * DisplayLink HW has separate 16bpp and 8bpp framebuffers.
+ * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
+ */
+static char *dlfb_set_base8bpp(char *wrptr, u32 base)
+{
+	wrptr = dlfb_set_register(wrptr, 0x26, base >> 16);
+	wrptr = dlfb_set_register(wrptr, 0x27, base >> 8);
+	return dlfb_set_register(wrptr, 0x28, base);
+}
+
+static char *dlfb_set_register_16(char *wrptr, u8 reg, u16 value)
+{
+	wrptr = dlfb_set_register(wrptr, reg, value >> 8);
+	return dlfb_set_register(wrptr, reg+1, value);
+}
+
+/*
+ * This is kind of weird because the controller takes some
+ * register values in a different byte order than other registers.
+ */
+static char *dlfb_set_register_16be(char *wrptr, u8 reg, u16 value)
+{
+	wrptr = dlfb_set_register(wrptr, reg, value);
+	return dlfb_set_register(wrptr, reg+1, value >> 8);
+}
+
+/*
+ * LFSR is linear feedback shift register. The reason we have this is
+ * because the display controller needs to minimize the clock depth of
+ * various counters used in the display path. So this code reverses the
+ * provided value into the lfsr16 value by counting backwards to get
+ * the value that needs to be set in the hardware comparator to get the
+ * same actual count. This makes sense once you read above a couple of
+ * times and think about it from a hardware perspective.
+ */
+static u16 dlfb_lfsr16(u16 actual_count)
+{
+	u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */
+
+	while (actual_count--) {
+		lv =	 ((lv << 1) |
+			(((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1))
+			& 0xFFFF;
+	}
+
+	return (u16) lv;
+}
+
+/*
+ * This does LFSR conversion on the value that is to be written.
+ * See LFSR explanation above for more detail.
+ */
+static char *dlfb_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
+{
+	return dlfb_set_register_16(wrptr, reg, dlfb_lfsr16(value));
+}
+
+/*
+ * This takes a standard fbdev screeninfo struct and all of its monitor mode
+ * details and converts them into the DisplayLink equivalent register commands.
+ */
+static char *dlfb_set_vid_cmds(char *wrptr, struct fb_var_screeninfo *var)
+{
+	u16 xds, yds;
+	u16 xde, yde;
+	u16 yec;
+
+	/* x display start */
+	xds = var->left_margin + var->hsync_len;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x01, xds);
+	/* x display end */
+	xde = xds + var->xres;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x03, xde);
+
+	/* y display start */
+	yds = var->upper_margin + var->vsync_len;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x05, yds);
+	/* y display end */
+	yde = yds + var->yres;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x07, yde);
+
+	/* x end count is active + blanking - 1 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x09,
+			xde + var->right_margin - 1);
+
+	/* libdlo hardcodes hsync start to 1 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0B, 1);
+
+	/* hsync end is width of sync pulse + 1 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x0D, var->hsync_len + 1);
+
+	/* hpixels is active pixels */
+	wrptr = dlfb_set_register_16(wrptr, 0x0F, var->xres);
+
+	/* yendcount is vertical active + vertical blanking */
+	yec = var->yres + var->upper_margin + var->lower_margin +
+			var->vsync_len;
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x11, yec);
+
+	/* libdlo hardcodes vsync start to 0 */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x13, 0);
+
+	/* vsync end is width of vsync pulse */
+	wrptr = dlfb_set_register_lfsr16(wrptr, 0x15, var->vsync_len);
+
+	/* vpixels is active pixels */
+	wrptr = dlfb_set_register_16(wrptr, 0x17, var->yres);
+
+	/* convert picoseconds to 5kHz multiple for pclk5k = x * 1E12/5k */
+	wrptr = dlfb_set_register_16be(wrptr, 0x1B,
+			200*1000*1000/var->pixclock);
+
+	return wrptr;
+}
+
+/*
+ * This takes a standard fbdev screeninfo struct that was fetched or prepared
+ * and then generates the appropriate command sequence that then drives the
+ * display controller.
+ */
+static int dlfb_set_video_mode(struct dlfb_data *dev,
+				struct fb_var_screeninfo *var)
+{
+	char *buf;
+	char *wrptr;
+	int retval = 0;
+	int writesize;
+	struct urb *urb;
+
+	if (!atomic_read(&dev->usb_active))
+		return -EPERM;
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return -ENOMEM;
+
+	buf = (char *) urb->transfer_buffer;
+
+	/*
+	* This first section has to do with setting the base address on the
+	* controller * associated with the display. There are 2 base
+	* pointers, currently, we only * use the 16 bpp segment.
+	*/
+	wrptr = dlfb_vidreg_lock(buf);
+	wrptr = dlfb_set_color_depth(wrptr, 0x00);
+	/* set base for 16bpp segment to 0 */
+	wrptr = dlfb_set_base16bpp(wrptr, 0);
+	/* set base for 8bpp segment to end of fb */
+	wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
+
+	wrptr = dlfb_set_vid_cmds(wrptr, var);
+	wrptr = dlfb_enable_hvsync(wrptr, true);
+	wrptr = dlfb_vidreg_unlock(wrptr);
+
+	writesize = wrptr - buf;
+
+	retval = dlfb_submit_urb(dev, urb, writesize);
+
+	return retval;
+}
+
+static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long page, pos;
+
+	if (offset + size > info->fix.smem_len)
+		return -EINVAL;
+
+	pos = (unsigned long)info->fix.smem_start + offset;
+
+	pr_notice("mmap() framebuffer addr:%lu size:%lu\n",
+		  pos, size);
+
+	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;
+	}
+
+	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
+	return 0;
+}
+
+/*
+ * Trims identical data from front and back of line
+ * Sets new front buffer address and width
+ * And returns byte count of identical pixels
+ * Assumes CPU natural alignment (unsigned long)
+ * for back and front buffer ptrs and width
+ */
+static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
+{
+	int j, k;
+	const unsigned long *back = (const unsigned long *) bback;
+	const unsigned long *front = (const unsigned long *) *bfront;
+	const int width = *width_bytes / sizeof(unsigned long);
+	int identical = width;
+	int start = width;
+	int end = width;
+
+	prefetch((void *) front);
+	prefetch((void *) back);
+
+	for (j = 0; j < width; j++) {
+		if (back[j] != front[j]) {
+			start = j;
+			break;
+		}
+	}
+
+	for (k = width - 1; k > j; k--) {
+		if (back[k] != front[k]) {
+			end = k+1;
+			break;
+		}
+	}
+
+	identical = start + (width - end);
+	*bfront = (u8 *) &front[start];
+	*width_bytes = (end - start) * sizeof(unsigned long);
+
+	return identical * sizeof(unsigned long);
+}
+
+/*
+ * Render a command stream for an encoded horizontal line segment of pixels.
+ *
+ * A command buffer holds several commands.
+ * It always begins with a fresh command header
+ * (the protocol doesn't require this, but we enforce it to allow
+ * multiple buffers to be potentially encoded and sent in parallel).
+ * A single command encodes one contiguous horizontal line of pixels
+ *
+ * The function relies on the client to do all allocation, so that
+ * rendering can be done directly to output buffers (e.g. USB URBs).
+ * The function fills the supplied command buffer, providing information
+ * on where it left off, so the client may call in again with additional
+ * buffers if the line will take several buffers to complete.
+ *
+ * A single command can transmit a maximum of 256 pixels,
+ * regardless of the compression ratio (protocol design limit).
+ * To the hardware, 0 for a size byte means 256
+ *
+ * Rather than 256 pixel commands which are either rl or raw encoded,
+ * the rlx command simply assumes alternating raw and rl spans within one cmd.
+ * This has a slightly larger header overhead, but produces more even results.
+ * It also processes all data (read and write) in a single pass.
+ * Performance benchmarks of common cases show it having just slightly better
+ * compression than 256 pixel raw or rle commands, with similar CPU consumpion.
+ * But for very rl friendly data, will compress not quite as well.
+ */
+static void dlfb_compress_hline(
+	const uint16_t **pixel_start_ptr,
+	const uint16_t *const pixel_end,
+	uint32_t *device_address_ptr,
+	uint8_t **command_buffer_ptr,
+	const uint8_t *const cmd_buffer_end)
+{
+	const uint16_t *pixel = *pixel_start_ptr;
+	uint32_t dev_addr  = *device_address_ptr;
+	uint8_t *cmd = *command_buffer_ptr;
+	const int bpp = 2;
+
+	while ((pixel_end > pixel) &&
+	       (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) {
+		uint8_t *raw_pixels_count_byte = 0;
+		uint8_t *cmd_pixels_count_byte = 0;
+		const uint16_t *raw_pixel_start = 0;
+		const uint16_t *cmd_pixel_start, *cmd_pixel_end = 0;
+
+		prefetchw((void *) cmd); /* pull in one cache line at least */
+
+		*cmd++ = 0xAF;
+		*cmd++ = 0x6B;
+		*cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
+		*cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
+		*cmd++ = (uint8_t) ((dev_addr) & 0xFF);
+
+		cmd_pixels_count_byte = cmd++; /*  we'll know this later */
+		cmd_pixel_start = pixel;
+
+		raw_pixels_count_byte = cmd++; /*  we'll know this later */
+		raw_pixel_start = pixel;
+
+		cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
+			min((int)(pixel_end - pixel),
+			    (int)(cmd_buffer_end - cmd) / bpp));
+
+		prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
+
+		while (pixel < cmd_pixel_end) {
+			const uint16_t * const repeating_pixel = pixel;
+
+			*(uint16_t *)cmd = cpu_to_be16p(pixel);
+			cmd += 2;
+			pixel++;
+
+			if (unlikely((pixel < cmd_pixel_end) &&
+				     (*pixel == *repeating_pixel))) {
+				/* go back and fill in raw pixel count */
+				*raw_pixels_count_byte = ((repeating_pixel -
+						raw_pixel_start) + 1) & 0xFF;
+
+				while ((pixel < cmd_pixel_end)
+				       && (*pixel == *repeating_pixel)) {
+					pixel++;
+				}
+
+				/* immediately after raw data is repeat byte */
+				*cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
+
+				/* Then start another raw pixel span */
+				raw_pixel_start = pixel;
+				raw_pixels_count_byte = cmd++;
+			}
+		}
+
+		if (pixel > raw_pixel_start) {
+			/* finalize last RAW span */
+			*raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
+		}
+
+		*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
+		dev_addr += (pixel - cmd_pixel_start) * bpp;
+	}
+
+	if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
+		/* Fill leftover bytes with no-ops */
+		if (cmd_buffer_end > cmd)
+			memset(cmd, 0xAF, cmd_buffer_end - cmd);
+		cmd = (uint8_t *) cmd_buffer_end;
+	}
+
+	*command_buffer_ptr = cmd;
+	*pixel_start_ptr = pixel;
+	*device_address_ptr = dev_addr;
+
+	return;
+}
+
+/*
+ * There are 3 copies of every pixel: The front buffer that the fbdev
+ * client renders to, the actual framebuffer across the USB bus in hardware
+ * (that we can only write to, slowly, and can never read), and (optionally)
+ * our shadow copy that tracks what's been sent to that hardware buffer.
+ */
+static int dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
+			      const char *front, char **urb_buf_ptr,
+			      u32 byte_offset, u32 byte_width,
+			      int *ident_ptr, int *sent_ptr)
+{
+	const u8 *line_start, *line_end, *next_pixel;
+	u32 dev_addr = dev->base16 + byte_offset;
+	struct urb *urb = *urb_ptr;
+	u8 *cmd = *urb_buf_ptr;
+	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
+
+	line_start = (u8 *) (front + byte_offset);
+	next_pixel = line_start;
+	line_end = next_pixel + byte_width;
+
+	if (dev->backing_buffer) {
+		int offset;
+		const u8 *back_start = (u8 *) (dev->backing_buffer
+						+ byte_offset);
+
+		*ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
+			&byte_width);
+
+		offset = next_pixel - line_start;
+		line_end = next_pixel + byte_width;
+		dev_addr += offset;
+		back_start += offset;
+		line_start += offset;
+
+		memcpy((char *)back_start, (char *) line_start,
+		       byte_width);
+	}
+
+	while (next_pixel < line_end) {
+
+		dlfb_compress_hline((const uint16_t **) &next_pixel,
+			     (const uint16_t *) line_end, &dev_addr,
+			(u8 **) &cmd, (u8 *) cmd_end);
+
+		if (cmd >= cmd_end) {
+			int len = cmd - (u8 *) urb->transfer_buffer;
+			if (dlfb_submit_urb(dev, urb, len))
+				return 1; /* lost pixels is set */
+			*sent_ptr += len;
+			urb = dlfb_get_urb(dev);
+			if (!urb)
+				return 1; /* lost_pixels is set */
+			*urb_ptr = urb;
+			cmd = urb->transfer_buffer;
+			cmd_end = &cmd[urb->transfer_buffer_length];
+		}
+	}
+
+	*urb_buf_ptr = cmd;
+
+	return 0;
+}
+
+int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+	       int width, int height, char *data)
+{
+	int i, ret;
+	char *cmd;
+	cycles_t start_cycles, end_cycles;
+	int bytes_sent = 0;
+	int bytes_identical = 0;
+	struct urb *urb;
+	int aligned_x;
+
+	start_cycles = get_cycles();
+
+	aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
+	width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
+	x = aligned_x;
+
+	if ((width <= 0) ||
+	    (x + width > dev->info->var.xres) ||
+	    (y + height > dev->info->var.yres))
+		return -EINVAL;
+
+	if (!atomic_read(&dev->usb_active))
+		return 0;
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return 0;
+	cmd = urb->transfer_buffer;
+
+	for (i = y; i < y + height ; i++) {
+		const int line_offset = dev->info->fix.line_length * i;
+		const int byte_offset = line_offset + (x * BPP);
+
+		if (dlfb_render_hline(dev, &urb,
+				      (char *) dev->info->fix.smem_start,
+				      &cmd, byte_offset, width * BPP,
+				      &bytes_identical, &bytes_sent))
+			goto error;
+	}
+
+	if (cmd > (char *) urb->transfer_buffer) {
+		/* Send partial buffer remaining before exiting */
+		int len = cmd - (char *) urb->transfer_buffer;
+		ret = dlfb_submit_urb(dev, urb, len);
+		bytes_sent += len;
+	} else
+		dlfb_urb_completion(urb);
+
+error:
+	atomic_add(bytes_sent, &dev->bytes_sent);
+	atomic_add(bytes_identical, &dev->bytes_identical);
+	atomic_add(width*height*2, &dev->bytes_rendered);
+	end_cycles = get_cycles();
+	atomic_add(((unsigned int) ((end_cycles - start_cycles)
+		    >> 10)), /* Kcycles */
+		   &dev->cpu_kcycles_used);
+
+	return 0;
+}
+
+/*
+ * Path triggered by usermode clients who write to filesystem
+ * e.g. cat filename > /dev/fb1
+ * Not used by X Windows or text-mode console. But useful for testing.
+ * Slow because of extra copy and we must assume all pixels dirty.
+ */
+static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
+			  size_t count, loff_t *ppos)
+{
+	ssize_t result;
+	struct dlfb_data *dev = info->par;
+	u32 offset = (u32) *ppos;
+
+	result = fb_sys_write(info, buf, count, ppos);
+
+	if (result > 0) {
+		int start = max((int)(offset / info->fix.line_length) - 1, 0);
+		int lines = min((u32)((result / info->fix.line_length) + 1),
+				(u32)info->var.yres);
+
+		dlfb_handle_damage(dev, 0, start, info->var.xres,
+			lines, info->screen_base);
+	}
+
+	return result;
+}
+
+/* hardware has native COPY command (see libdlo), but not worth it for fbcon */
+static void dlfb_ops_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+
+	struct dlfb_data *dev = info->par;
+
+	sys_copyarea(info, area);
+
+	dlfb_handle_damage(dev, area->dx, area->dy,
+			area->width, area->height, info->screen_base);
+}
+
+static void dlfb_ops_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	struct dlfb_data *dev = info->par;
+
+	sys_imageblit(info, image);
+
+	dlfb_handle_damage(dev, image->dx, image->dy,
+			image->width, image->height, info->screen_base);
+}
+
+static void dlfb_ops_fillrect(struct fb_info *info,
+			  const struct fb_fillrect *rect)
+{
+	struct dlfb_data *dev = info->par;
+
+	sys_fillrect(info, rect);
+
+	dlfb_handle_damage(dev, rect->dx, rect->dy, rect->width,
+			      rect->height, info->screen_base);
+}
+
+/*
+ * NOTE: fb_defio.c is holding info->fbdefio.mutex
+ *   Touching ANY framebuffer memory that triggers a page fault
+ *   in fb_defio will cause a deadlock, when it also tries to
+ *   grab the same mutex.
+ */
+static void dlfb_dpy_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	struct page *cur;
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+	struct dlfb_data *dev = info->par;
+	struct urb *urb;
+	char *cmd;
+	cycles_t start_cycles, end_cycles;
+	int bytes_sent = 0;
+	int bytes_identical = 0;
+	int bytes_rendered = 0;
+
+	if (!fb_defio)
+		return;
+
+	if (!atomic_read(&dev->usb_active))
+		return;
+
+	start_cycles = get_cycles();
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return;
+
+	cmd = urb->transfer_buffer;
+
+	/* walk the written page list and render each to device */
+	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+
+		if (dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
+				  &cmd, cur->index << PAGE_SHIFT,
+				  PAGE_SIZE, &bytes_identical, &bytes_sent))
+			goto error;
+		bytes_rendered += PAGE_SIZE;
+	}
+
+	if (cmd > (char *) urb->transfer_buffer) {
+		/* Send partial buffer remaining before exiting */
+		int len = cmd - (char *) urb->transfer_buffer;
+		dlfb_submit_urb(dev, urb, len);
+		bytes_sent += len;
+	} else
+		dlfb_urb_completion(urb);
+
+error:
+	atomic_add(bytes_sent, &dev->bytes_sent);
+	atomic_add(bytes_identical, &dev->bytes_identical);
+	atomic_add(bytes_rendered, &dev->bytes_rendered);
+	end_cycles = get_cycles();
+	atomic_add(((unsigned int) ((end_cycles - start_cycles)
+		    >> 10)), /* Kcycles */
+		   &dev->cpu_kcycles_used);
+}
+
+static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
+{
+	int i;
+	int ret;
+	char *rbuf;
+
+	rbuf = kmalloc(2, GFP_KERNEL);
+	if (!rbuf)
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		ret = usb_control_msg(dev->udev,
+				    usb_rcvctrlpipe(dev->udev, 0), (0x02),
+				    (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
+				    HZ);
+		if (ret < 1) {
+			pr_err("Read EDID byte %d failed err %x\n", i, ret);
+			i--;
+			break;
+		}
+		edid[i] = rbuf[1];
+	}
+
+	kfree(rbuf);
+
+	return i;
+}
+
+static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
+				unsigned long arg)
+{
+
+	struct dlfb_data *dev = info->par;
+	struct dloarea *area = NULL;
+
+	if (!atomic_read(&dev->usb_active))
+		return 0;
+
+	/* TODO: Update X server to get this from sysfs instead */
+	if (cmd == DLFB_IOCTL_RETURN_EDID) {
+		char *edid = (char *)arg;
+		if (copy_to_user(edid, dev->edid, dev->edid_size))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+	if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
+
+		/*
+		 * If we have a damage-aware client, turn fb_defio "off"
+		 * To avoid perf imact of unecessary page fault handling.
+		 * Done by resetting the delay for this fb_info to a very
+		 * long period. Pages will become writable and stay that way.
+		 * Reset to normal value when all clients have closed this fb.
+		 */
+		if (info->fbdefio)
+			info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
+
+		area = (struct dloarea *)arg;
+
+		if (area->x < 0)
+			area->x = 0;
+
+		if (area->x > info->var.xres)
+			area->x = info->var.xres;
+
+		if (area->y < 0)
+			area->y = 0;
+
+		if (area->y > info->var.yres)
+			area->y = info->var.yres;
+
+		dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
+			   info->screen_base);
+	}
+
+	return 0;
+}
+
+/* taken from vesafb */
+static int
+dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
+	       unsigned blue, unsigned transp, struct fb_info *info)
+{
+	int err = 0;
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	if (regno < 16) {
+		if (info->var.red.offset == 10) {
+			/* 1:5:5:5 */
+			((u32 *) (info->pseudo_palette))[regno] =
+			    ((red & 0xf800) >> 1) |
+			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
+		} else {
+			/* 0:5:6:5 */
+			((u32 *) (info->pseudo_palette))[regno] =
+			    ((red & 0xf800)) |
+			    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+		}
+	}
+
+	return err;
+}
+
+/*
+ * It's common for several clients to have framebuffer open simultaneously.
+ * e.g. both fbcon and X. Makes things interesting.
+ * Assumes caller is holding info->lock (for open and release at least)
+ */
+static int dlfb_ops_open(struct fb_info *info, int user)
+{
+	struct dlfb_data *dev = info->par;
+
+	/*
+	 * fbcon aggressively connects to first framebuffer it finds,
+	 * preventing other clients (X) from working properly. Usually
+	 * not what the user wants. Fail by default with option to enable.
+	 */
+	if ((user == 0) & (!console))
+		return -EBUSY;
+
+	/* If the USB device is gone, we don't accept new opens */
+	if (dev->virtualized)
+		return -ENODEV;
+
+	dev->fb_count++;
+
+	kref_get(&dev->kref);
+
+	if (fb_defio && (info->fbdefio == NULL)) {
+		/* enable defio at last moment if not disabled by client */
+
+		struct fb_deferred_io *fbdefio;
+
+		fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
+
+		if (fbdefio) {
+			fbdefio->delay = DL_DEFIO_WRITE_DELAY;
+			fbdefio->deferred_io = dlfb_dpy_deferred_io;
+		}
+
+		info->fbdefio = fbdefio;
+		fb_deferred_io_init(info);
+	}
+
+	pr_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
+	    info->node, user, info, dev->fb_count);
+
+	return 0;
+}
+
+/*
+ * Called when all client interfaces to start transactions have been disabled,
+ * and all references to our device instance (dlfb_data) are released.
+ * Every transaction must have a reference, so we know are fully spun down
+ */
+static void dlfb_free(struct kref *kref)
+{
+	struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
+
+	/* this function will wait for all in-flight urbs to complete */
+	if (dev->urbs.count > 0)
+		dlfb_free_urb_list(dev);
+
+	if (dev->backing_buffer)
+		vfree(dev->backing_buffer);
+
+	kfree(dev->edid);
+
+	pr_warn("freeing dlfb_data %p\n", dev);
+
+	kfree(dev);
+}
+
+static void dlfb_release_urb_work(struct work_struct *work)
+{
+	struct urb_node *unode = container_of(work, struct urb_node,
+					      release_urb_work.work);
+
+	up(&unode->dev->urbs.limit_sem);
+}
+
+static void dlfb_free_framebuffer_work(struct work_struct *work)
+{
+	struct dlfb_data *dev = container_of(work, struct dlfb_data,
+					     free_framebuffer_work.work);
+	struct fb_info *info = dev->info;
+	int node = info->node;
+
+	unregister_framebuffer(info);
+
+	if (info->cmap.len != 0)
+		fb_dealloc_cmap(&info->cmap);
+	if (info->monspecs.modedb)
+		fb_destroy_modedb(info->monspecs.modedb);
+	if (info->screen_base)
+		vfree(info->screen_base);
+
+	fb_destroy_modelist(&info->modelist);
+
+	dev->info = 0;
+
+	/* Assume info structure is freed after this point */
+	framebuffer_release(info);
+
+	pr_warn("fb_info for /dev/fb%d has been freed\n", node);
+
+	/* ref taken in probe() as part of registering framebfufer */
+	kref_put(&dev->kref, dlfb_free);
+}
+
+/*
+ * Assumes caller is holding info->lock mutex (for open and release at least)
+ */
+static int dlfb_ops_release(struct fb_info *info, int user)
+{
+	struct dlfb_data *dev = info->par;
+
+	dev->fb_count--;
+
+	/* We can't free fb_info here - fbmem will touch it when we return */
+	if (dev->virtualized && (dev->fb_count == 0))
+		schedule_delayed_work(&dev->free_framebuffer_work, HZ);
+
+	if ((dev->fb_count == 0) && (info->fbdefio)) {
+		fb_deferred_io_cleanup(info);
+		kfree(info->fbdefio);
+		info->fbdefio = NULL;
+		info->fbops->fb_mmap = dlfb_ops_mmap;
+	}
+
+	pr_warn("released /dev/fb%d user=%d count=%d\n",
+		  info->node, user, dev->fb_count);
+
+	kref_put(&dev->kref, dlfb_free);
+
+	return 0;
+}
+
+/*
+ * Check whether a video mode is supported by the DisplayLink chip
+ * We start from monitor's modes, so don't need to filter that here
+ */
+static int dlfb_is_valid_mode(struct fb_videomode *mode,
+		struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+
+	if (mode->xres * mode->yres > dev->sku_pixel_limit) {
+		pr_warn("%dx%d beyond chip capabilities\n",
+		       mode->xres, mode->yres);
+		return 0;
+	}
+
+	pr_info("%dx%d valid mode\n", mode->xres, mode->yres);
+
+	return 1;
+}
+
+static void dlfb_var_color_format(struct fb_var_screeninfo *var)
+{
+	const struct fb_bitfield red = { 11, 5, 0 };
+	const struct fb_bitfield green = { 5, 6, 0 };
+	const struct fb_bitfield blue = { 0, 5, 0 };
+
+	var->bits_per_pixel = 16;
+	var->red = red;
+	var->green = green;
+	var->blue = blue;
+}
+
+static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct fb_videomode mode;
+
+	/* TODO: support dynamically changing framebuffer size */
+	if ((var->xres * var->yres * 2) > info->fix.smem_len)
+		return -EINVAL;
+
+	/* set device-specific elements of var unrelated to mode */
+	dlfb_var_color_format(var);
+
+	fb_var_to_videomode(&mode, var);
+
+	if (!dlfb_is_valid_mode(&mode, info))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int dlfb_ops_set_par(struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+	int result;
+	u16 *pix_framebuffer;
+	int i;
+
+	pr_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
+
+	result = dlfb_set_video_mode(dev, &info->var);
+
+	if ((result == 0) && (dev->fb_count == 0)) {
+
+		/* paint greenscreen */
+
+		pix_framebuffer = (u16 *) info->screen_base;
+		for (i = 0; i < info->fix.smem_len / 2; i++)
+			pix_framebuffer[i] = 0x37e6;
+
+		dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
+				   info->screen_base);
+	}
+
+	return result;
+}
+
+/*
+ * In order to come back from full DPMS off, we need to set the mode again
+ */
+static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+
+	if (blank_mode != FB_BLANK_UNBLANK) {
+		char *bufptr;
+		struct urb *urb;
+
+		urb = dlfb_get_urb(dev);
+		if (!urb)
+			return 0;
+
+		bufptr = (char *) urb->transfer_buffer;
+		bufptr = dlfb_vidreg_lock(bufptr);
+		bufptr = dlfb_enable_hvsync(bufptr, false);
+		bufptr = dlfb_vidreg_unlock(bufptr);
+
+		dlfb_submit_urb(dev, urb, bufptr -
+				(char *) urb->transfer_buffer);
+	} else {
+		dlfb_set_video_mode(dev, &info->var);
+	}
+
+	return 0;
+}
+
+static struct fb_ops dlfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_read = fb_sys_read,
+	.fb_write = dlfb_ops_write,
+	.fb_setcolreg = dlfb_ops_setcolreg,
+	.fb_fillrect = dlfb_ops_fillrect,
+	.fb_copyarea = dlfb_ops_copyarea,
+	.fb_imageblit = dlfb_ops_imageblit,
+	.fb_mmap = dlfb_ops_mmap,
+	.fb_ioctl = dlfb_ops_ioctl,
+	.fb_open = dlfb_ops_open,
+	.fb_release = dlfb_ops_release,
+	.fb_blank = dlfb_ops_blank,
+	.fb_check_var = dlfb_ops_check_var,
+	.fb_set_par = dlfb_ops_set_par,
+};
+
+
+/*
+ * Assumes &info->lock held by caller
+ * Assumes no active clients have framebuffer open
+ */
+static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
+{
+	int retval = -ENOMEM;
+	int old_len = info->fix.smem_len;
+	int new_len;
+	unsigned char *old_fb = info->screen_base;
+	unsigned char *new_fb;
+	unsigned char *new_back;
+
+	pr_warn("Reallocating framebuffer. Addresses will change!\n");
+
+	new_len = info->fix.line_length * info->var.yres;
+
+	if (PAGE_ALIGN(new_len) > old_len) {
+		/*
+		 * Alloc system memory for virtual framebuffer
+		 */
+		new_fb = vmalloc(new_len);
+		if (!new_fb) {
+			pr_err("Virtual framebuffer alloc failed\n");
+			goto error;
+		}
+
+		if (info->screen_base) {
+			memcpy(new_fb, old_fb, old_len);
+			vfree(info->screen_base);
+		}
+
+		info->screen_base = new_fb;
+		info->fix.smem_len = PAGE_ALIGN(new_len);
+		info->fix.smem_start = (unsigned long) new_fb;
+		info->flags = udlfb_info_flags;
+
+		/*
+		 * Second framebuffer copy to mirror the framebuffer state
+		 * on the physical USB device. We can function without this.
+		 * But with imperfect damage info we may send pixels over USB
+		 * that were, in fact, unchanged - wasting limited USB bandwidth
+		 */
+		new_back = vmalloc(new_len);
+		if (!new_back)
+			pr_info("No shadow/backing buffer allcoated\n");
+		else {
+			if (dev->backing_buffer)
+				vfree(dev->backing_buffer);
+			dev->backing_buffer = new_back;
+			memset(dev->backing_buffer, 0, new_len);
+		}
+	}
+
+	retval = 0;
+
+error:
+	return retval;
+}
+
+/*
+ * 1) Get EDID from hw, or use sw default
+ * 2) Parse into various fb_info structs
+ * 3) Allocate virtual framebuffer memory to back highest res mode
+ *
+ * Parses EDID into three places used by various parts of fbdev:
+ * fb_var_screeninfo contains the timing of the monitor's preferred mode
+ * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
+ * fb_info.modelist is a linked list of all monitor & VESA modes which work
+ *
+ * If EDID is not readable/valid, then modelist is all VESA modes,
+ * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
+ * Returns 0 if successful
+ */
+static int dlfb_setup_modes(struct dlfb_data *dev,
+			   struct fb_info *info,
+			   char *default_edid, size_t default_edid_size)
+{
+	int i;
+	const struct fb_videomode *default_vmode = NULL;
+	int result = 0;
+	char *edid;
+	int tries = 3;
+
+	if (info->dev) /* only use mutex if info has been registered */
+		mutex_lock(&info->lock);
+
+	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!edid) {
+		result = -ENOMEM;
+		goto error;
+	}
+
+	fb_destroy_modelist(&info->modelist);
+	memset(&info->monspecs, 0, sizeof(info->monspecs));
+
+	/*
+	 * Try to (re)read EDID from hardware first
+	 * EDID data may return, but not parse as valid
+	 * Try again a few times, in case of e.g. analog cable noise
+	 */
+	while (tries--) {
+
+		i = dlfb_get_edid(dev, edid, EDID_LENGTH);
+
+		if (i >= EDID_LENGTH)
+			fb_edid_to_monspecs(edid, &info->monspecs);
+
+		if (info->monspecs.modedb_len > 0) {
+			dev->edid = edid;
+			dev->edid_size = i;
+			break;
+		}
+	}
+
+	/* If that fails, use a previously returned EDID if available */
+	if (info->monspecs.modedb_len == 0) {
+
+		pr_err("Unable to get valid EDID from device/display\n");
+
+		if (dev->edid) {
+			fb_edid_to_monspecs(dev->edid, &info->monspecs);
+			if (info->monspecs.modedb_len > 0)
+				pr_err("Using previously queried EDID\n");
+		}
+	}
+
+	/* If that fails, use the default EDID we were handed */
+	if (info->monspecs.modedb_len == 0) {
+		if (default_edid_size >= EDID_LENGTH) {
+			fb_edid_to_monspecs(default_edid, &info->monspecs);
+			if (info->monspecs.modedb_len > 0) {
+				memcpy(edid, default_edid, default_edid_size);
+				dev->edid = edid;
+				dev->edid_size = default_edid_size;
+				pr_err("Using default/backup EDID\n");
+			}
+		}
+	}
+
+	/* If we've got modes, let's pick a best default mode */
+	if (info->monspecs.modedb_len > 0) {
+
+		for (i = 0; i < info->monspecs.modedb_len; i++) {
+			if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info))
+				fb_add_videomode(&info->monspecs.modedb[i],
+					&info->modelist);
+			else /* if we've removed top/best mode */
+				info->monspecs.misc &= ~FB_MISC_1ST_DETAIL;
+		}
+
+		default_vmode = fb_find_best_display(&info->monspecs,
+						     &info->modelist);
+	}
+
+	/* If everything else has failed, fall back to safe default mode */
+	if (default_vmode == NULL) {
+
+		struct fb_videomode fb_vmode = {0};
+
+		/*
+		 * Add the standard VESA modes to our modelist
+		 * Since we don't have EDID, there may be modes that
+		 * overspec monitor and/or are incorrect aspect ratio, etc.
+		 * But at least the user has a chance to choose
+		 */
+		for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+			if (dlfb_is_valid_mode((struct fb_videomode *)
+						&vesa_modes[i], info))
+				fb_add_videomode(&vesa_modes[i],
+						 &info->modelist);
+		}
+
+		/*
+		 * default to resolution safe for projectors
+		 * (since they are most common case without EDID)
+		 */
+		fb_vmode.xres = 800;
+		fb_vmode.yres = 600;
+		fb_vmode.refresh = 60;
+		default_vmode = fb_find_nearest_mode(&fb_vmode,
+						     &info->modelist);
+	}
+
+	/* If we have good mode and no active clients*/
+	if ((default_vmode != NULL) && (dev->fb_count == 0)) {
+
+		fb_videomode_to_var(&info->var, default_vmode);
+		dlfb_var_color_format(&info->var);
+
+		/*
+		 * with mode size info, we can now alloc our framebuffer.
+		 */
+		memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
+		info->fix.line_length = info->var.xres *
+			(info->var.bits_per_pixel / 8);
+
+		result = dlfb_realloc_framebuffer(dev, info);
+
+	} else
+		result = -EINVAL;
+
+error:
+	if (edid && (dev->edid != edid))
+		kfree(edid);
+
+	if (info->dev)
+		mutex_unlock(&info->lock);
+
+	return result;
+}
+
+static ssize_t metrics_bytes_rendered_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->bytes_rendered));
+}
+
+static ssize_t metrics_bytes_identical_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->bytes_identical));
+}
+
+static ssize_t metrics_bytes_sent_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->bytes_sent));
+}
+
+static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
+				   struct device_attribute *a, char *buf) {
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			atomic_read(&dev->cpu_kcycles_used));
+}
+
+static ssize_t edid_show(
+			struct file *filp,
+			struct kobject *kobj, struct bin_attribute *a,
+			 char *buf, loff_t off, size_t count) {
+	struct device *fbdev = container_of(kobj, struct device, kobj);
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+
+	if (dev->edid == NULL)
+		return 0;
+
+	if ((off >= dev->edid_size) || (count > dev->edid_size))
+		return 0;
+
+	if (off + count > dev->edid_size)
+		count = dev->edid_size - off;
+
+	pr_info("sysfs edid copy %p to %p, %d bytes\n",
+		dev->edid, buf, (int) count);
+
+	memcpy(buf, dev->edid, count);
+
+	return count;
+}
+
+static ssize_t edid_store(
+			struct file *filp,
+			struct kobject *kobj, struct bin_attribute *a,
+			char *src, loff_t src_off, size_t src_size) {
+	struct device *fbdev = container_of(kobj, struct device, kobj);
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+
+	/* We only support write of entire EDID at once, no offset*/
+	if ((src_size != EDID_LENGTH) || (src_off != 0))
+		return 0;
+
+	dlfb_setup_modes(dev, fb_info, src, src_size);
+
+	if (dev->edid && (memcmp(src, dev->edid, src_size) == 0)) {
+		pr_info("sysfs written EDID is new default\n");
+		dlfb_ops_set_par(fb_info);
+		return src_size;
+	} else
+		return 0;
+}
+
+static ssize_t metrics_reset_store(struct device *fbdev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
+
+	atomic_set(&dev->bytes_rendered, 0);
+	atomic_set(&dev->bytes_identical, 0);
+	atomic_set(&dev->bytes_sent, 0);
+	atomic_set(&dev->cpu_kcycles_used, 0);
+
+	return count;
+}
+
+static struct bin_attribute edid_attr = {
+	.attr.name = "edid",
+	.attr.mode = 0666,
+	.size = EDID_LENGTH,
+	.read = edid_show,
+	.write = edid_store
+};
+
+static struct device_attribute fb_device_attrs[] = {
+	__ATTR_RO(metrics_bytes_rendered),
+	__ATTR_RO(metrics_bytes_identical),
+	__ATTR_RO(metrics_bytes_sent),
+	__ATTR_RO(metrics_cpu_kcycles_used),
+	__ATTR(metrics_reset, S_IWUSR, NULL, metrics_reset_store),
+};
+
+/*
+ * This is necessary before we can communicate with the display controller.
+ */
+static int dlfb_select_std_channel(struct dlfb_data *dev)
+{
+	int ret;
+	u8 set_def_chn[] = {	   0x57, 0xCD, 0xDC, 0xA7,
+				0x1C, 0x88, 0x5E, 0x15,
+				0x60, 0xFE, 0xC6, 0x97,
+				0x16, 0x3D, 0x47, 0xF2  };
+
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			NR_USB_REQUEST_CHANNEL,
+			(USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
+			set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
+	return ret;
+}
+
+static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
+					struct usb_device *usbdev)
+{
+	char *desc;
+	char *buf;
+	char *desc_end;
+
+	u8 total_len = 0;
+
+	buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
+	if (!buf)
+		return false;
+	desc = buf;
+
+	total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
+				    0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
+	if (total_len > 5) {
+		pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
+			"%02x %02x %02x %02x %02x %02x %02x\n",
+			total_len, desc[0],
+			desc[1], desc[2], desc[3], desc[4], desc[5], desc[6],
+			desc[7], desc[8], desc[9], desc[10]);
+
+		if ((desc[0] != total_len) || /* descriptor length */
+		    (desc[1] != 0x5f) ||   /* vendor descriptor type */
+		    (desc[2] != 0x01) ||   /* version (2 bytes) */
+		    (desc[3] != 0x00) ||
+		    (desc[4] != total_len - 2)) /* length after type */
+			goto unrecognized;
+
+		desc_end = desc + total_len;
+		desc += 5; /* the fixed header we've already parsed */
+
+		while (desc < desc_end) {
+			u8 length;
+			u16 key;
+
+			key = *((u16 *) desc);
+			desc += sizeof(u16);
+			length = *desc;
+			desc++;
+
+			switch (key) {
+			case 0x0200: { /* max_area */
+				u32 max_area;
+				max_area = le32_to_cpu(*((u32 *)desc));
+				pr_warn("DL chip limited to %d pixel modes\n",
+					max_area);
+				dev->sku_pixel_limit = max_area;
+				break;
+			}
+			default:
+				break;
+			}
+			desc += length;
+		}
+	}
+
+	goto success;
+
+unrecognized:
+	/* allow udlfb to load for now even if firmware unrecognized */
+	pr_err("Unrecognized vendor firmware descriptor\n");
+
+success:
+	kfree(buf);
+	return true;
+}
+static int dlfb_usb_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
+{
+	struct usb_device *usbdev;
+	struct dlfb_data *dev = 0;
+	struct fb_info *info = 0;
+	int retval = -ENOMEM;
+	int i;
+
+	/* usb initialization */
+
+	usbdev = interface_to_usbdev(interface);
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		err("dlfb_usb_probe: failed alloc of dev struct\n");
+		goto error;
+	}
+
+	/* we need to wait for both usb and fbdev to spin down on disconnect */
+	kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
+	kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
+
+	dev->udev = usbdev;
+	dev->gdev = &usbdev->dev; /* our generic struct device * */
+	usb_set_intfdata(interface, dev);
+
+	pr_info("%s %s - serial #%s\n",
+		usbdev->manufacturer, usbdev->product, usbdev->serial);
+	pr_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
+		usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
+		usbdev->descriptor.bcdDevice, dev);
+	pr_info("console enable=%d\n", console);
+	pr_info("fb_defio enable=%d\n", fb_defio);
+
+	dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
+
+	if (!dlfb_parse_vendor_descriptor(dev, usbdev)) {
+		pr_err("firmware not recognized. Assume incompatible device\n");
+		goto error;
+	}
+
+	if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+		retval = -ENOMEM;
+		pr_err("dlfb_alloc_urb_list failed\n");
+		goto error;
+	}
+
+	/* We don't register a new USB class. Our client interface is fbdev */
+
+	/* allocates framebuffer driver structure, not framebuffer memory */
+	info = framebuffer_alloc(0, &usbdev->dev);
+	if (!info) {
+		retval = -ENOMEM;
+		pr_err("framebuffer_alloc failed\n");
+		goto error;
+	}
+
+	dev->info = info;
+	info->par = dev;
+	info->pseudo_palette = dev->pseudo_palette;
+	info->fbops = &dlfb_ops;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0) {
+		pr_err("fb_alloc_cmap failed %x\n", retval);
+		goto error;
+	}
+
+	INIT_DELAYED_WORK(&dev->free_framebuffer_work,
+			  dlfb_free_framebuffer_work);
+
+	INIT_LIST_HEAD(&info->modelist);
+
+	retval = dlfb_setup_modes(dev, info, NULL, 0);
+	if (retval != 0) {
+		pr_err("unable to find common mode for display and adapter\n");
+		goto error;
+	}
+
+	/* ready to begin using device */
+
+	atomic_set(&dev->usb_active, 1);
+	dlfb_select_std_channel(dev);
+
+	dlfb_ops_check_var(&info->var, info);
+	dlfb_ops_set_par(info);
+
+	retval = register_framebuffer(info);
+	if (retval < 0) {
+		pr_err("register_framebuffer failed %d\n", retval);
+		goto error;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+		device_create_file(info->dev, &fb_device_attrs[i]);
+
+	device_create_bin_file(info->dev, &edid_attr);
+
+	pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
+			" Using %dK framebuffer memory\n", info->node,
+			info->var.xres, info->var.yres,
+			((dev->backing_buffer) ?
+			info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
+	return 0;
+
+error:
+	if (dev) {
+
+		if (info) {
+			if (info->cmap.len != 0)
+				fb_dealloc_cmap(&info->cmap);
+			if (info->monspecs.modedb)
+				fb_destroy_modedb(info->monspecs.modedb);
+			if (info->screen_base)
+				vfree(info->screen_base);
+
+			fb_destroy_modelist(&info->modelist);
+
+			framebuffer_release(info);
+		}
+
+		if (dev->backing_buffer)
+			vfree(dev->backing_buffer);
+
+		kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
+		kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
+
+		/* dev has been deallocated. Do not dereference */
+	}
+
+	return retval;
+}
+
+static void dlfb_usb_disconnect(struct usb_interface *interface)
+{
+	struct dlfb_data *dev;
+	struct fb_info *info;
+	int i;
+
+	dev = usb_get_intfdata(interface);
+	info = dev->info;
+
+	pr_info("USB disconnect starting\n");
+
+	/* we virtualize until all fb clients release. Then we free */
+	dev->virtualized = true;
+
+	/* When non-active we'll update virtual framebuffer, but no new urbs */
+	atomic_set(&dev->usb_active, 0);
+
+	/* remove udlfb's sysfs interfaces */
+	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+		device_remove_file(info->dev, &fb_device_attrs[i]);
+	device_remove_bin_file(info->dev, &edid_attr);
+
+	usb_set_intfdata(interface, NULL);
+
+	/* if clients still have us open, will be freed on last close */
+	if (dev->fb_count == 0)
+		schedule_delayed_work(&dev->free_framebuffer_work, 0);
+
+	/* release reference taken by kref_init in probe() */
+	kref_put(&dev->kref, dlfb_free);
+
+	/* consider dlfb_data freed */
+
+	return;
+}
+
+static struct usb_driver dlfb_driver = {
+	.name = "udlfb",
+	.probe = dlfb_usb_probe,
+	.disconnect = dlfb_usb_disconnect,
+	.id_table = id_table,
+};
+
+static int __init dlfb_module_init(void)
+{
+	int res;
+
+	res = usb_register(&dlfb_driver);
+	if (res)
+		err("usb_register failed. Error number %d", res);
+
+	return res;
+}
+
+static void __exit dlfb_module_exit(void)
+{
+	usb_deregister(&dlfb_driver);
+}
+
+module_init(dlfb_module_init);
+module_exit(dlfb_module_exit);
+
+static void dlfb_urb_completion(struct urb *urb)
+{
+	struct urb_node *unode = urb->context;
+	struct dlfb_data *dev = unode->dev;
+	unsigned long flags;
+
+	/* sync/async unlink faults aren't errors */
+	if (urb->status) {
+		if (!(urb->status == -ENOENT ||
+		    urb->status == -ECONNRESET ||
+		    urb->status == -ESHUTDOWN)) {
+			pr_err("%s - nonzero write bulk status received: %d\n",
+				__func__, urb->status);
+			atomic_set(&dev->lost_pixels, 1);
+		}
+	}
+
+	urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
+
+	spin_lock_irqsave(&dev->urbs.lock, flags);
+	list_add_tail(&unode->entry, &dev->urbs.list);
+	dev->urbs.available++;
+	spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+	/*
+	 * When using fb_defio, we deadlock if up() is called
+	 * while another is waiting. So queue to another process.
+	 */
+	if (fb_defio)
+		schedule_delayed_work(&unode->release_urb_work, 0);
+	else
+		up(&dev->urbs.limit_sem);
+}
+
+static void dlfb_free_urb_list(struct dlfb_data *dev)
+{
+	int count = dev->urbs.count;
+	struct list_head *node;
+	struct urb_node *unode;
+	struct urb *urb;
+	int ret;
+	unsigned long flags;
+
+	pr_notice("Waiting for completes and freeing all render urbs\n");
+
+	/* keep waiting and freeing, until we've got 'em all */
+	while (count--) {
+
+		/* Getting interrupted means a leak, but ok at shutdown*/
+		ret = down_interruptible(&dev->urbs.limit_sem);
+		if (ret)
+			break;
+
+		spin_lock_irqsave(&dev->urbs.lock, flags);
+
+		node = dev->urbs.list.next; /* have reserved one with sem */
+		list_del_init(node);
+
+		spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+		unode = list_entry(node, struct urb_node, entry);
+		urb = unode->urb;
+
+		/* Free each separately allocated piece */
+		usb_free_coherent(urb->dev, dev->urbs.size,
+				  urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+		kfree(node);
+	}
+
+}
+
+static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
+{
+	int i = 0;
+	struct urb *urb;
+	struct urb_node *unode;
+	char *buf;
+
+	spin_lock_init(&dev->urbs.lock);
+
+	dev->urbs.size = size;
+	INIT_LIST_HEAD(&dev->urbs.list);
+
+	while (i < count) {
+		unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
+		if (!unode)
+			break;
+		unode->dev = dev;
+
+		INIT_DELAYED_WORK(&unode->release_urb_work,
+			  dlfb_release_urb_work);
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			kfree(unode);
+			break;
+		}
+		unode->urb = urb;
+
+		buf = usb_alloc_coherent(dev->udev, MAX_TRANSFER, GFP_KERNEL,
+					 &urb->transfer_dma);
+		if (!buf) {
+			kfree(unode);
+			usb_free_urb(urb);
+			break;
+		}
+
+		/* urb->transfer_buffer_length set to actual before submit */
+		usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
+			buf, size, dlfb_urb_completion, unode);
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		list_add_tail(&unode->entry, &dev->urbs.list);
+
+		i++;
+	}
+
+	sema_init(&dev->urbs.limit_sem, i);
+	dev->urbs.count = i;
+	dev->urbs.available = i;
+
+	pr_notice("allocated %d %d byte urbs\n", i, (int) size);
+
+	return i;
+}
+
+static struct urb *dlfb_get_urb(struct dlfb_data *dev)
+{
+	int ret = 0;
+	struct list_head *entry;
+	struct urb_node *unode;
+	struct urb *urb = NULL;
+	unsigned long flags;
+
+	/* Wait for an in-flight buffer to complete and get re-queued */
+	ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
+	if (ret) {
+		atomic_set(&dev->lost_pixels, 1);
+		pr_warn("wait for urb interrupted: %x available: %d\n",
+		       ret, dev->urbs.available);
+		goto error;
+	}
+
+	spin_lock_irqsave(&dev->urbs.lock, flags);
+
+	BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
+	entry = dev->urbs.list.next;
+	list_del_init(entry);
+	dev->urbs.available--;
+
+	spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+	unode = list_entry(entry, struct urb_node, entry);
+	urb = unode->urb;
+
+error:
+	return urb;
+}
+
+static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
+{
+	int ret;
+
+	BUG_ON(len > dev->urbs.size);
+
+	urb->transfer_buffer_length = len; /* set to actual payload len */
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret) {
+		dlfb_urb_completion(urb); /* because no one else will */
+		atomic_set(&dev->lost_pixels, 1);
+		pr_err("usb_submit_urb error %x\n", ret);
+	}
+	return ret;
+}
+
+module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found");
+
+module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*");
+
+MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
+	      "Jaya Kumar <jayakumar.lkml@gmail.com>, "
+	      "Bernie Thompson <bernie@plugable.com>");
+MODULE_DESCRIPTION("DisplayLink kernel framebuffer driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index a3aa917..6723d69 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -15,6 +15,9 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/pm.h>
+#include <asm/olpc.h>
 
 /*
  * The default port config.
@@ -29,6 +32,19 @@
 };
 
 /*
+ * The OLPC XO-1.5 puts the camera power and reset lines onto
+ * GPIO 2C.
+ */
+static const struct via_port_cfg olpc_adap_configs[] = {
+	[VIA_PORT_26]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
+	[VIA_PORT_31]	= { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
+	[VIA_PORT_25]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
+	[VIA_PORT_2C]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
+	[VIA_PORT_3D]	= { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
+	{ 0, 0, 0, 0 }
+};
+
+/*
  * We currently only support one viafb device (will there ever be
  * more than one?), so just declare it globally here.
  */
@@ -575,6 +591,78 @@
 		}
 }
 
+/*
+ * Power management functions
+ */
+#ifdef CONFIG_PM
+static LIST_HEAD(viafb_pm_hooks);
+static DEFINE_MUTEX(viafb_pm_hooks_lock);
+
+void viafb_pm_register(struct viafb_pm_hooks *hooks)
+{
+	INIT_LIST_HEAD(&hooks->list);
+
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_add_tail(&hooks->list, &viafb_pm_hooks);
+	mutex_unlock(&viafb_pm_hooks_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_pm_register);
+
+void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
+{
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_del(&hooks->list);
+	mutex_unlock(&viafb_pm_hooks_lock);
+}
+EXPORT_SYMBOL_GPL(viafb_pm_unregister);
+
+static int via_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct viafb_pm_hooks *hooks;
+
+	if (state.event != PM_EVENT_SUSPEND)
+		return 0;
+	/*
+	 * "I've occasionally hit a few drivers that caused suspend
+	 * failures, and each and every time it was a driver bug, and
+	 * the right thing to do was to just ignore the error and suspend
+	 * anyway - returning an error code and trying to undo the suspend
+	 * is not what anybody ever really wants, even if our model
+	 *_allows_ for it."
+	 * -- Linus Torvalds, Dec. 7, 2009
+	 */
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
+		hooks->suspend(hooks->private);
+	mutex_unlock(&viafb_pm_hooks_lock);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return 0;
+}
+
+static int via_resume(struct pci_dev *pdev)
+{
+	struct viafb_pm_hooks *hooks;
+
+	/* Get the bus side powered up */
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	if (pci_enable_device(pdev))
+		return 0;
+
+	pci_set_master(pdev);
+
+	/* Now bring back any subdevs */
+	mutex_lock(&viafb_pm_hooks_lock);
+	list_for_each_entry(hooks, &viafb_pm_hooks, list)
+		hooks->resume(hooks->private);
+	mutex_unlock(&viafb_pm_hooks_lock);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
 
 static int __devinit via_pci_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
@@ -584,6 +672,7 @@
 	ret = pci_enable_device(pdev);
 	if (ret)
 		return ret;
+
 	/*
 	 * Global device initialization.
 	 */
@@ -591,6 +680,9 @@
 	global_dev.pdev = pdev;
 	global_dev.chip_type = ent->driver_data;
 	global_dev.port_cfg = adap_configs;
+	if (machine_is_olpc())
+		global_dev.port_cfg = olpc_adap_configs;
+
 	spin_lock_init(&global_dev.reg_lock);
 	ret = via_pci_setup_mmio(&global_dev);
 	if (ret)
@@ -663,8 +755,8 @@
 	.probe		= via_pci_probe,
 	.remove		= __devexit_p(via_pci_remove),
 #ifdef CONFIG_PM
-	.suspend	= viafb_suspend,
-	.resume		= viafb_resume,
+	.suspend	= via_suspend,
+	.resume		= via_resume,
 #endif
 };
 
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c
index 39acb37..c2a0a1cf 100644
--- a/drivers/video/via/via-gpio.c
+++ b/drivers/video/via/via-gpio.c
@@ -172,6 +172,28 @@
 	via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
 }
 
+#ifdef CONFIG_PM
+
+static int viafb_gpio_suspend(void *private)
+{
+	return 0;
+}
+
+static int viafb_gpio_resume(void *private)
+{
+	int i;
+
+	for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2)
+		viafb_gpio_enable(gpio_config.active_gpios[i]);
+	return 0;
+}
+
+static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
+	.suspend = viafb_gpio_suspend,
+	.resume = viafb_gpio_resume
+};
+#endif /* CONFIG_PM */
+
 /*
  * Look up a specific gpio and return the number it was assigned.
  */
@@ -236,6 +258,9 @@
 		printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
 		gpio_config.gpio_chip.ngpio = 0;
 	}
+#ifdef CONFIG_PM
+	viafb_pm_register(&viafb_gpio_pm_hooks);
+#endif
 	return ret;
 }
 
@@ -245,6 +270,10 @@
 	unsigned long flags;
 	int ret = 0, i;
 
+#ifdef CONFIG_PM
+	viafb_pm_unregister(&viafb_gpio_pm_hooks);
+#endif
+
 	/*
 	 * Get unregistered.
 	 */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index d298cfc..289edd5 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -1672,31 +1672,19 @@
 
 
 #ifdef CONFIG_PM
-int viafb_suspend(struct pci_dev *pdev, pm_message_t state)
+static int viafb_suspend(void *unused)
 {
-	if (state.event == PM_EVENT_SUSPEND) {
-		acquire_console_sem();
-		fb_set_suspend(viafbinfo, 1);
-
-		viafb_sync(viafbinfo);
-
-		pci_save_state(pdev);
-		pci_disable_device(pdev);
-		pci_set_power_state(pdev, pci_choose_state(pdev, state));
-		release_console_sem();
-	}
+	acquire_console_sem();
+	fb_set_suspend(viafbinfo, 1);
+	viafb_sync(viafbinfo);
+	release_console_sem();
 
 	return 0;
 }
 
-int viafb_resume(struct pci_dev *pdev)
+static int viafb_resume(void *unused)
 {
 	acquire_console_sem();
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	if (pci_enable_device(pdev))
-		goto fail;
-	pci_set_master(pdev);
 	if (viaparinfo->shared->vdev->engine_mmio)
 		viafb_reset_engine(viaparinfo);
 	viafb_set_par(viafbinfo);
@@ -1704,11 +1692,15 @@
 		viafb_set_par(viafbinfo1);
 	fb_set_suspend(viafbinfo, 0);
 
-fail:
 	release_console_sem();
 	return 0;
 }
 
+static struct viafb_pm_hooks viafb_fb_pm_hooks = {
+	.suspend = viafb_suspend,
+	.resume = viafb_resume
+};
+
 #endif
 
 
@@ -1899,6 +1891,10 @@
 
 	viafb_init_proc(viaparinfo->shared);
 	viafb_init_dac(IGA2);
+
+#ifdef CONFIG_PM
+	viafb_pm_register(&viafb_fb_pm_hooks);
+#endif
 	return 0;
 
 out_fb_unreg:
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 4960e3d..d66f963 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -108,6 +108,4 @@
 /* Temporary */
 int viafb_init(void);
 void viafb_exit(void);
-int viafb_suspend(struct pci_dev *pdev, pm_message_t state);
-int viafb_resume(struct pci_dev *pdev);
 #endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
new file mode 100644
index 0000000..7617f12
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.c
@@ -0,0 +1,447 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on skeletonfb.c and pxafb.c
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <mach/vt8500fb.h>
+
+#include "vt8500lcdfb.h"
+#include "wmt_ge_rops.h"
+
+#define to_vt8500lcd_info(__info) container_of(__info, \
+						struct vt8500lcd_info, fb)
+
+static int vt8500lcd_set_par(struct fb_info *info)
+{
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+	int reg_bpp = 5; /* 16bpp */
+	int i;
+	unsigned long control0;
+
+	if (!fbi)
+		return -EINVAL;
+
+	if (info->var.bits_per_pixel <= 8) {
+		/* palettized */
+		info->var.red.offset    = 0;
+		info->var.red.length    = info->var.bits_per_pixel;
+		info->var.red.msb_right = 0;
+
+		info->var.green.offset  = 0;
+		info->var.green.length  = info->var.bits_per_pixel;
+		info->var.green.msb_right = 0;
+
+		info->var.blue.offset   = 0;
+		info->var.blue.length   = info->var.bits_per_pixel;
+		info->var.blue.msb_right = 0;
+
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		info->var.transp.msb_right = 0;
+
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		info->fix.line_length = info->var.xres_virtual /
+						(8/info->var.bits_per_pixel);
+	} else {
+		/* non-palettized */
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		info->var.transp.msb_right = 0;
+
+		if (info->var.bits_per_pixel == 16) {
+			/* RGB565 */
+			info->var.red.offset = 11;
+			info->var.red.length = 5;
+			info->var.red.msb_right = 0;
+			info->var.green.offset = 5;
+			info->var.green.length = 6;
+			info->var.green.msb_right = 0;
+			info->var.blue.offset = 0;
+			info->var.blue.length = 5;
+			info->var.blue.msb_right = 0;
+		} else {
+			/* Equal depths per channel */
+			info->var.red.offset = info->var.bits_per_pixel
+							* 2 / 3;
+			info->var.red.length = info->var.bits_per_pixel / 3;
+			info->var.red.msb_right = 0;
+			info->var.green.offset = info->var.bits_per_pixel / 3;
+			info->var.green.length = info->var.bits_per_pixel / 3;
+			info->var.green.msb_right = 0;
+			info->var.blue.offset = 0;
+			info->var.blue.length = info->var.bits_per_pixel / 3;
+			info->var.blue.msb_right = 0;
+		}
+
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.line_length = info->var.bits_per_pixel > 16 ?
+					info->var.xres_virtual << 2 :
+					info->var.xres_virtual << 1;
+	}
+
+	for (i = 0; i < 8; i++) {
+		if (bpp_values[i] == info->var.bits_per_pixel) {
+			reg_bpp = i;
+			continue;
+		}
+	}
+
+	control0 = readl(fbi->regbase) & ~0xf;
+	writel(0, fbi->regbase);
+	while (readl(fbi->regbase + 0x38) & 0x10)
+		/* wait */;
+	writel((((info->var.hsync_len - 1) & 0x3f) << 26)
+		| ((info->var.left_margin & 0xff) << 18)
+		| (((info->var.xres - 1) & 0x3ff) << 8)
+		| (info->var.right_margin & 0xff), fbi->regbase + 0x4);
+	writel((((info->var.vsync_len - 1) & 0x3f) << 26)
+		| ((info->var.upper_margin & 0xff) << 18)
+		| (((info->var.yres - 1) & 0x3ff) << 8)
+		| (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
+	writel((((info->var.yres - 1) & 0x400) << 2)
+		| ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
+	writel(0x80000000, fbi->regbase + 0x20);
+	writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
+
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info) {
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+	int ret = 1;
+	unsigned int val;
+	if (regno >= 256)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			u32 *pal = fbi->fb.pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		writew((red & 0xf800)
+		      | ((green >> 5) & 0x7e0)
+		      | ((blue >> 11) & 0x1f),
+		       fbi->palette_cpu + sizeof(u16) * regno);
+		break;
+	}
+
+	return ret;
+}
+
+static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg)
+{
+	int ret = 0;
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+
+	if (cmd == FBIO_WAITFORVSYNC) {
+		/* Unmask End of Frame interrupt */
+		writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
+		ret = wait_event_interruptible_timeout(fbi->wait,
+			readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
+		/* Mask back to reduce unwanted interrupt traffic */
+		writel(0xffffffff, fbi->regbase + 0x3c);
+		if (ret < 0)
+			return ret;
+		if (ret == 0)
+			return -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
+	unsigned off = pixlen * var->xoffset
+		      + info->fix.line_length * var->yoffset;
+	struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
+
+	writel((1 << 31)
+		| (((var->xres_virtual - var->xres) * pixlen / 4) << 20)
+		| (off >> 2), fbi->regbase + 0x20);
+	return 0;
+}
+
+static struct fb_ops vt8500lcd_ops = {
+	.owner		= THIS_MODULE,
+	.fb_set_par	= vt8500lcd_set_par,
+	.fb_setcolreg	= vt8500lcd_setcolreg,
+	.fb_fillrect	= wmt_ge_fillrect,
+	.fb_copyarea	= wmt_ge_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_sync	= wmt_ge_sync,
+	.fb_ioctl	= vt8500lcd_ioctl,
+	.fb_pan_display	= vt8500lcd_pan_display,
+};
+
+static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
+{
+	struct vt8500lcd_info *fbi = dev_id;
+
+	if (readl(fbi->regbase + 0x38) & (1 << 3))
+		wake_up_interruptible(&fbi->wait);
+
+	writel(0xffffffff, fbi->regbase + 0x38);
+	return IRQ_HANDLED;
+}
+
+static int __devinit vt8500lcd_probe(struct platform_device *pdev)
+{
+	struct vt8500lcd_info *fbi;
+	struct resource *res;
+	struct vt8500fb_platform_data *pdata = pdev->dev.platform_data;
+	void *addr;
+	int irq, ret;
+
+	ret = -ENOMEM;
+	fbi = NULL;
+
+	fbi = kzalloc(sizeof(struct vt8500lcd_info) + sizeof(u32) * 16,
+							GFP_KERNEL);
+	if (!fbi) {
+		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	strcpy(fbi->fb.fix.id, "VT8500 LCD");
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.xpanstep	= 0;
+	fbi->fb.fix.ypanstep	= 1;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.var.nonstd	= 0;
+	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
+	fbi->fb.var.height	= -1;
+	fbi->fb.var.width	= -1;
+	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
+
+	fbi->fb.fbops		= &vt8500lcd_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT
+				| FBINFO_HWACCEL_COPYAREA
+				| FBINFO_HWACCEL_FILLRECT
+				| FBINFO_HWACCEL_YPAN
+				| FBINFO_VIRTFB
+				| FBINFO_PARTIAL_PAN_OK;
+	fbi->fb.node		= -1;
+
+	addr = fbi;
+	addr = addr + sizeof(struct vt8500lcd_info);
+	fbi->fb.pseudo_palette	= addr;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		ret = -ENODEV;
+		goto failed_fbi;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		ret = -EBUSY;
+		goto failed_fbi;
+	}
+
+	fbi->regbase = ioremap(res->start, resource_size(res));
+	if (fbi->regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto failed_free_res;
+	}
+
+	fbi->fb.fix.smem_start	= pdata->video_mem_phys;
+	fbi->fb.fix.smem_len	= pdata->video_mem_len;
+	fbi->fb.screen_base	= pdata->video_mem_virt;
+
+	fbi->palette_size	= PAGE_ALIGN(512);
+	fbi->palette_cpu	= dma_alloc_coherent(&pdev->dev,
+						     fbi->palette_size,
+						     &fbi->palette_phys,
+						     GFP_KERNEL);
+	if (fbi->palette_cpu == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
+		ret = -ENOMEM;
+		goto failed_free_io;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		ret = -ENODEV;
+		goto failed_free_palette;
+	}
+
+	ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi);
+	if (ret) {
+		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
+		ret = -EBUSY;
+		goto failed_free_palette;
+	}
+
+	init_waitqueue_head(&fbi->wait);
+
+	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+		dev_err(&pdev->dev, "Failed to allocate color map\n");
+		ret = -ENOMEM;
+		goto failed_free_irq;
+	}
+
+	fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
+	fbi->fb.var.bits_per_pixel	= pdata->bpp;
+	fbi->fb.var.xres_virtual	= pdata->xres_virtual;
+	fbi->fb.var.yres_virtual	= pdata->yres_virtual;
+
+	ret = vt8500lcd_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set parameters\n");
+		goto failed_free_cmap;
+	}
+
+	writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
+	writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
+
+	platform_set_drvdata(pdev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Failed to register framebuffer device: %d\n", ret);
+		goto failed_free_cmap;
+	}
+
+	/*
+	 * Ok, now enable the LCD controller
+	 */
+	writel(readl(fbi->regbase) | 1, fbi->regbase);
+
+	return 0;
+
+failed_free_cmap:
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_irq:
+	free_irq(irq, fbi);
+failed_free_palette:
+	dma_free_coherent(&pdev->dev, fbi->palette_size,
+			  fbi->palette_cpu, fbi->palette_phys);
+failed_free_io:
+	iounmap(fbi->regbase);
+failed_free_res:
+	release_mem_region(res->start, resource_size(res));
+failed_fbi:
+	platform_set_drvdata(pdev, NULL);
+	kfree(fbi);
+failed:
+	return ret;
+}
+
+static int __devexit vt8500lcd_remove(struct platform_device *pdev)
+{
+	struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
+	struct resource *res;
+	int irq;
+
+	unregister_framebuffer(&fbi->fb);
+
+	writel(0, fbi->regbase);
+
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, fbi);
+
+	dma_free_coherent(&pdev->dev, fbi->palette_size,
+			  fbi->palette_cpu, fbi->palette_phys);
+
+	iounmap(fbi->regbase);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(fbi);
+
+	return 0;
+}
+
+static struct platform_driver vt8500lcd_driver = {
+	.probe		= vt8500lcd_probe,
+	.remove		= __devexit_p(vt8500lcd_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "vt8500-lcd",
+	},
+};
+
+static int __init vt8500lcd_init(void)
+{
+	return platform_driver_register(&vt8500lcd_driver);
+}
+
+static void __exit vt8500lcd_exit(void)
+{
+	platform_driver_unregister(&vt8500lcd_driver);
+}
+
+module_init(vt8500lcd_init);
+module_exit(vt8500lcd_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/vt8500lcdfb.h
new file mode 100644
index 0000000..36ca3ca
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.h
@@ -0,0 +1,34 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.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.
+ */
+
+struct vt8500lcd_info {
+	struct fb_info		fb;
+	void __iomem		*regbase;
+	void __iomem		*palette_cpu;
+	dma_addr_t		palette_phys;
+	size_t			palette_size;
+	wait_queue_head_t	wait;
+};
+
+static int bpp_values[] = {
+	1,
+	2,
+	4,
+	8,
+	12,
+	16,
+	18,
+	24,
+};
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
new file mode 100644
index 0000000..96e34a5
--- /dev/null
+++ b/drivers/video/wm8505fb.c
@@ -0,0 +1,422 @@
+/*
+ *  WonderMedia WM8505 Frame Buffer device driver
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *    Based on vt8500lcdfb.c
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <mach/vt8500fb.h>
+
+#include "wm8505fb_regs.h"
+#include "wmt_ge_rops.h"
+
+#define DRIVER_NAME "wm8505-fb"
+
+#define to_wm8505fb_info(__info) container_of(__info, \
+						struct wm8505fb_info, fb)
+struct wm8505fb_info {
+	struct fb_info		fb;
+	void __iomem		*regbase;
+	unsigned int		contrast;
+};
+
+
+static int wm8505fb_init_hw(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	int i;
+
+	/* I know the purpose only of few registers, so clear unknown */
+	for (i = 0; i < 0x200; i += 4)
+		writel(0, fbi->regbase + i);
+
+	/* Set frame buffer address */
+	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
+	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
+
+	/* Set in-memory picture format to RGB 32bpp */
+	writel(0x1c,		       fbi->regbase + WMT_GOVR_COLORSPACE);
+	writel(1,		       fbi->regbase + WMT_GOVR_COLORSPACE1);
+
+	/* Virtual buffer size */
+	writel(info->var.xres,	       fbi->regbase + WMT_GOVR_XRES);
+	writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
+
+	/* black magic ;) */
+	writel(0xf,		       fbi->regbase + WMT_GOVR_FHI);
+	writel(4,		       fbi->regbase + WMT_GOVR_DVO_SET);
+	writel(1,		       fbi->regbase + WMT_GOVR_MIF_ENABLE);
+	writel(1,		       fbi->regbase + WMT_GOVR_REG_UPDATE);
+
+	return 0;
+}
+
+static int wm8505fb_set_timing(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	int h_start = info->var.left_margin;
+	int h_end = h_start + info->var.xres;
+	int h_all = h_end + info->var.right_margin;
+	int h_sync = info->var.hsync_len;
+
+	int v_start = info->var.upper_margin;
+	int v_end = v_start + info->var.yres;
+	int v_all = v_end + info->var.lower_margin;
+	int v_sync = info->var.vsync_len;
+
+	writel(0, fbi->regbase + WMT_GOVR_TG);
+
+	writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
+	writel(h_end,   fbi->regbase + WMT_GOVR_TIMING_H_END);
+	writel(h_all,   fbi->regbase + WMT_GOVR_TIMING_H_ALL);
+	writel(h_sync,  fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
+
+	writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
+	writel(v_end,   fbi->regbase + WMT_GOVR_TIMING_V_END);
+	writel(v_all,   fbi->regbase + WMT_GOVR_TIMING_V_ALL);
+	writel(v_sync,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+
+	writel(1, fbi->regbase + WMT_GOVR_TG);
+
+	return 0;
+}
+
+
+static int wm8505fb_set_par(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	if (!fbi)
+		return -EINVAL;
+
+	if (info->var.bits_per_pixel == 32) {
+		info->var.red.offset = 16;
+		info->var.red.length = 8;
+		info->var.red.msb_right = 0;
+		info->var.green.offset = 8;
+		info->var.green.length = 8;
+		info->var.green.msb_right = 0;
+		info->var.blue.offset = 0;
+		info->var.blue.length = 8;
+		info->var.blue.msb_right = 0;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.line_length = info->var.xres_virtual << 2;
+	}
+
+	wm8505fb_set_timing(info);
+
+	writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
+		fbi->regbase + WMT_GOVR_CONTRAST);
+
+	return 0;
+}
+
+static ssize_t contrast_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	return sprintf(buf, "%d\n", fbi->contrast);
+}
+
+static ssize_t contrast_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+	unsigned long tmp;
+
+	if (strict_strtoul(buf, 10, &tmp) || (tmp > 0xff))
+		return -EINVAL;
+	fbi->contrast = tmp;
+
+	wm8505fb_set_par(info);
+
+	return count;
+}
+
+static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info) {
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+	int ret = 1;
+	unsigned int val;
+	if (regno >= 256)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
+	writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
+	return 0;
+}
+
+static int wm8505fb_blank(int blank, struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = to_wm8505fb_info(info);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		wm8505fb_set_timing(info);
+		break;
+	default:
+		writel(0,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+		break;
+	}
+
+	return 0;
+}
+
+static struct fb_ops wm8505fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_set_par	= wm8505fb_set_par,
+	.fb_setcolreg	= wm8505fb_setcolreg,
+	.fb_fillrect	= wmt_ge_fillrect,
+	.fb_copyarea	= wmt_ge_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_sync	= wmt_ge_sync,
+	.fb_pan_display	= wm8505fb_pan_display,
+	.fb_blank	= wm8505fb_blank,
+};
+
+static int __devinit wm8505fb_probe(struct platform_device *pdev)
+{
+	struct wm8505fb_info	*fbi;
+	struct resource		*res;
+	void			*addr;
+	struct vt8500fb_platform_data *pdata;
+	int ret;
+
+	pdata = pdev->dev.platform_data;
+
+	ret = -ENOMEM;
+	fbi = NULL;
+
+	fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16,
+							GFP_KERNEL);
+	if (!fbi) {
+		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	strcpy(fbi->fb.fix.id, DRIVER_NAME);
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.xpanstep	= 1;
+	fbi->fb.fix.ypanstep	= 1;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.fbops		= &wm8505fb_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT
+				| FBINFO_HWACCEL_COPYAREA
+				| FBINFO_HWACCEL_FILLRECT
+				| FBINFO_HWACCEL_XPAN
+				| FBINFO_HWACCEL_YPAN
+				| FBINFO_VIRTFB
+				| FBINFO_PARTIAL_PAN_OK;
+	fbi->fb.node		= -1;
+
+	addr = fbi;
+	addr = addr + sizeof(struct wm8505fb_info);
+	fbi->fb.pseudo_palette	= addr;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		ret = -ENODEV;
+		goto failed_fbi;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		ret = -EBUSY;
+		goto failed_fbi;
+	}
+
+	fbi->regbase = ioremap(res->start, resource_size(res));
+	if (fbi->regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto failed_free_res;
+	}
+
+	fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
+
+	fbi->fb.var.nonstd		= 0;
+	fbi->fb.var.activate		= FB_ACTIVATE_NOW;
+
+	fbi->fb.var.height		= -1;
+	fbi->fb.var.width		= -1;
+	fbi->fb.var.xres_virtual	= pdata->xres_virtual;
+	fbi->fb.var.yres_virtual	= pdata->yres_virtual;
+	fbi->fb.var.bits_per_pixel	= pdata->bpp;
+
+	fbi->fb.fix.smem_start	= pdata->video_mem_phys;
+	fbi->fb.fix.smem_len	= pdata->video_mem_len;
+	fbi->fb.screen_base	= pdata->video_mem_virt;
+	fbi->fb.screen_size	= pdata->video_mem_len;
+
+	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+		dev_err(&pdev->dev, "Failed to allocate color map\n");
+		ret = -ENOMEM;
+		goto failed_free_io;
+	}
+
+	wm8505fb_init_hw(&fbi->fb);
+
+	fbi->contrast = 0x80;
+	ret = wm8505fb_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set parameters\n");
+		goto failed_free_cmap;
+	}
+
+	platform_set_drvdata(pdev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Failed to register framebuffer device: %d\n", ret);
+		goto failed_free_cmap;
+	}
+
+	ret = device_create_file(&pdev->dev, &dev_attr_contrast);
+	if (ret < 0) {
+		printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
+			fbi->fb.node, ret);
+	}
+
+	printk(KERN_INFO "fb%d: %s frame buffer at 0x%lx-0x%lx\n",
+	       fbi->fb.node, fbi->fb.fix.id, fbi->fb.fix.smem_start,
+	       fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
+
+	return 0;
+
+failed_free_cmap:
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_io:
+	iounmap(fbi->regbase);
+failed_free_res:
+	release_mem_region(res->start, resource_size(res));
+failed_fbi:
+	platform_set_drvdata(pdev, NULL);
+	kfree(fbi);
+failed:
+	return ret;
+}
+
+static int __devexit wm8505fb_remove(struct platform_device *pdev)
+{
+	struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	device_remove_file(&pdev->dev, &dev_attr_contrast);
+
+	unregister_framebuffer(&fbi->fb);
+
+	writel(0, fbi->regbase);
+
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+
+	iounmap(fbi->regbase);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(fbi);
+
+	return 0;
+}
+
+static struct platform_driver wm8505fb_driver = {
+	.probe		= wm8505fb_probe,
+	.remove		= __devexit_p(wm8505fb_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init wm8505fb_init(void)
+{
+	return platform_driver_register(&wm8505fb_driver);
+}
+
+static void __exit wm8505fb_exit(void)
+{
+	platform_driver_unregister(&wm8505fb_driver);
+}
+
+module_init(wm8505fb_init);
+module_exit(wm8505fb_exit);
+
+MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
+MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/wm8505fb_regs.h
new file mode 100644
index 0000000..4dd4166
--- /dev/null
+++ b/drivers/video/wm8505fb_regs.h
@@ -0,0 +1,76 @@
+/*
+ *  GOVR registers list for WM8505 chips
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *   Based on VIA/WonderMedia wm8510-govrh-reg.h
+ *   http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
+ *         drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
+ *
+ * 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 _WM8505FB_REGS_H
+#define _WM8505FB_REGS_H
+
+/*
+ * Color space select register, default value 0x1c
+ *   BIT0 GOVRH_DVO_YUV2RGB_ENABLE
+ *   BIT1 GOVRH_VGA_YUV2RGB_ENABLE
+ *   BIT2 GOVRH_RGB_MODE
+ *   BIT3 GOVRH_DAC_CLKINV
+ *   BIT4 GOVRH_BLANK_ZERO
+ */
+#define WMT_GOVR_COLORSPACE	0x1e4
+/*
+ * Another colorspace select register, default value 1
+ *   BIT0 GOVRH_DVO_RGB
+ *   BIT1 GOVRH_DVO_YUV422
+ */
+#define WMT_GOVR_COLORSPACE1	 0x30
+
+#define WMT_GOVR_CONTRAST	0x1b8
+#define WMT_GOVR_BRGHTNESS	0x1bc /* incompatible with RGB? */
+
+/* Framubeffer address */
+#define WMT_GOVR_FBADDR		 0x90
+#define WMT_GOVR_FBADDR1	 0x94 /* UV offset in YUV mode */
+
+/* Offset of visible window */
+#define WMT_GOVR_XPAN		 0xa4
+#define WMT_GOVR_YPAN		 0xa0
+
+#define WMT_GOVR_XRES		 0x98
+#define WMT_GOVR_XRES_VIRTUAL	 0x9c
+
+#define WMT_GOVR_MIF_ENABLE	 0x80
+#define WMT_GOVR_FHI		 0xa8
+#define WMT_GOVR_REG_UPDATE	 0xe4
+
+/*
+ *   BIT0 GOVRH_DVO_OUTWIDTH
+ *   BIT1 GOVRH_DVO_SYNC_POLAR
+ *   BIT2 GOVRH_DVO_ENABLE
+ */
+#define WMT_GOVR_DVO_SET	0x148
+
+/* Timing generator? */
+#define WMT_GOVR_TG		0x100
+
+/* Timings */
+#define WMT_GOVR_TIMING_H_ALL	0x108
+#define WMT_GOVR_TIMING_V_ALL	0x10c
+#define WMT_GOVR_TIMING_V_START	0x110
+#define WMT_GOVR_TIMING_V_END	0x114
+#define WMT_GOVR_TIMING_H_START	0x118
+#define WMT_GOVR_TIMING_H_END	0x11c
+#define WMT_GOVR_TIMING_V_SYNC	0x128
+#define WMT_GOVR_TIMING_H_SYNC	0x12c
+
+#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
new file mode 100644
index 0000000..45832b7
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.c
@@ -0,0 +1,186 @@
+/*
+ *  linux/drivers/video/wmt_ge_rops.c
+ *
+ *  Accelerators for raster operations using WonderMedia Graphics Engine
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include "fb_draw.h"
+
+#define GE_COMMAND_OFF		0x00
+#define GE_DEPTH_OFF		0x04
+#define GE_HIGHCOLOR_OFF	0x08
+#define GE_ROPCODE_OFF		0x14
+#define GE_FIRE_OFF		0x18
+#define GE_SRCBASE_OFF		0x20
+#define GE_SRCDISPW_OFF		0x24
+#define GE_SRCDISPH_OFF		0x28
+#define GE_SRCAREAX_OFF		0x2c
+#define GE_SRCAREAY_OFF		0x30
+#define GE_SRCAREAW_OFF		0x34
+#define GE_SRCAREAH_OFF		0x38
+#define GE_DESTBASE_OFF		0x3c
+#define GE_DESTDISPW_OFF	0x40
+#define GE_DESTDISPH_OFF	0x44
+#define GE_DESTAREAX_OFF	0x48
+#define GE_DESTAREAY_OFF	0x4c
+#define GE_DESTAREAW_OFF	0x50
+#define GE_DESTAREAH_OFF	0x54
+#define GE_PAT0C_OFF		0x88	/* Pattern 0 color */
+#define GE_ENABLE_OFF		0xec
+#define GE_INTEN_OFF		0xf0
+#define GE_STATUS_OFF		0xf8
+
+static void __iomem *regbase;
+
+void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	unsigned long fg, pat;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    p->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		fg = ((u32 *) (p->pseudo_palette))[rect->color];
+	else
+		fg = rect->color;
+
+	pat = pixel_to_pat(p->var.bits_per_pixel, fg);
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	writel(p->var.bits_per_pixel == 32 ? 3 :
+	      (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
+	writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
+	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+	writel(rect->dx, regbase + GE_DESTAREAX_OFF);
+	writel(rect->dy, regbase + GE_DESTAREAY_OFF);
+	writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
+	writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
+
+	writel(pat, regbase + GE_PAT0C_OFF);
+	writel(1, regbase + GE_COMMAND_OFF);
+	writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
+	writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
+
+void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	writel(p->var.bits_per_pixel > 16 ? 3 :
+	      (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
+
+	writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
+	writel(area->sx, regbase + GE_SRCAREAX_OFF);
+	writel(area->sy, regbase + GE_SRCAREAY_OFF);
+	writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
+	writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
+
+	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+	writel(area->dx, regbase + GE_DESTAREAX_OFF);
+	writel(area->dy, regbase + GE_DESTAREAY_OFF);
+	writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
+	writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
+
+	writel(0xcc, regbase + GE_ROPCODE_OFF);
+	writel(1, regbase + GE_COMMAND_OFF);
+	writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
+
+int wmt_ge_sync(struct fb_info *p)
+{
+	int loops = 5000000;
+	while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
+		cpu_relax();
+	return loops > 0 ? 0 : -EBUSY;
+}
+EXPORT_SYMBOL_GPL(wmt_ge_sync);
+
+static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		return -ENODEV;
+	}
+
+	/* Only one ROP engine is presently supported. */
+	if (unlikely(regbase)) {
+		WARN_ON(1);
+		return -EBUSY;
+	}
+
+	regbase = ioremap(res->start, resource_size(res));
+	if (regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		return -EBUSY;
+	}
+
+	writel(1, regbase + GE_ENABLE_OFF);
+	printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
+
+	return 0;
+}
+
+static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
+{
+	iounmap(regbase);
+	return 0;
+}
+
+static struct platform_driver wmt_ge_rops_driver = {
+	.probe		= wmt_ge_rops_probe,
+	.remove		= __devexit_p(wmt_ge_rops_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "wmt_ge_rops",
+	},
+};
+
+static int __init wmt_ge_rops_init(void)
+{
+	return platform_driver_register(&wmt_ge_rops_driver);
+}
+
+static void __exit wmt_ge_rops_exit(void)
+{
+	platform_driver_unregister(&wmt_ge_rops_driver);
+}
+
+module_init(wmt_ge_rops_init);
+module_exit(wmt_ge_rops_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
+MODULE_DESCRIPTION("Accelerators for raster operations using "
+		   "WonderMedia Graphics Engine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
new file mode 100644
index 0000000..8738075
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.h
@@ -0,0 +1,5 @@
+extern void wmt_ge_fillrect(struct fb_info *info,
+			    const struct fb_fillrect *rect);
+extern void wmt_ge_copyarea(struct fb_info *info,
+			    const struct fb_copyarea *area);
+extern int wmt_ge_sync(struct fb_info *info);
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 428d273..4abb0b9 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -492,7 +492,7 @@
 		return;
 
 	acquire_console_sem();
-	for (c = console_drivers; c; c = c->next) {
+	for_each_console(c) {
 		if (!strcmp(c->name, "tty") && c->index == 0)
 			break;
 	}
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 3d77116..dea7b5b 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -642,19 +642,14 @@
  */
 
 #ifdef CONFIG_HPWDT_NMI_DECODING
-#ifdef ARCH_HAS_NMI_WATCHDOG
+#ifdef CONFIG_X86_LOCAL_APIC
 static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
 {
 	/*
 	 * If nmi_watchdog is turned off then we can turn on
 	 * our nmi decoding capability.
 	 */
-	if (!nmi_watchdog_active())
-		hpwdt_nmi_decoding = 1;
-	else
-		dev_warn(&dev->dev, "NMI decoding is disabled. To enable this "
-			"functionality you must reboot with nmi_watchdog=0 "
-			"and load the hpwdt driver with priority=1.\n");
+	hpwdt_nmi_decoding = 1;
 }
 #else
 static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
@@ -662,7 +657,7 @@
 	dev_warn(&dev->dev, "NMI decoding is disabled. "
 		"Your kernel does not support a NMI Watchdog.\n");
 }
-#endif /* ARCH_HAS_NMI_WATCHDOG */
+#endif /* CONFIG_X86_LOCAL_APIC */
 
 static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
 {
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 2ee7dac..86f7cac 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -270,7 +270,7 @@
 		return -ENOMEM;
 	}
 
-	imx2_wdt.clk = clk_get_sys("imx-wdt.0", NULL);
+	imx2_wdt.clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(imx2_wdt.clk)) {
 		dev_err(&pdev->dev, "can't get Watchdog clock\n");
 		return PTR_ERR(imx2_wdt.clk);
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 31af0ac..65f8637 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -355,7 +355,7 @@
 		struct evtchn_unmask unmask = { .port = port };
 		(void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
 	} else {
-		struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
+		struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
 
 		sync_clear_bit(port, &s->evtchn_mask[0]);
 
@@ -1101,7 +1101,7 @@
 {
 	int cpu = get_cpu();
 	struct shared_info *s = HYPERVISOR_shared_info;
-	struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
+	struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
  	unsigned count;
 
 	do {
@@ -1109,7 +1109,7 @@
 
 		vcpu_info->evtchn_upcall_pending = 0;
 
-		if (__get_cpu_var(xed_nesting_count)++)
+		if (__this_cpu_inc_return(xed_nesting_count) - 1)
 			goto out;
 
 #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
@@ -1141,8 +1141,8 @@
 
 		BUG_ON(!irqs_disabled());
 
-		count = __get_cpu_var(xed_nesting_count);
-		__get_cpu_var(xed_nesting_count) = 0;
+		count = __this_cpu_read(xed_nesting_count);
+		__this_cpu_write(xed_nesting_count, 0);
 	} while (count != 1 || vcpu_info->evtchn_upcall_pending);
 
 out:
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 12d6023..6e58c4c 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -91,11 +91,14 @@
 	return acl;
 }
 
-int v9fs_check_acl(struct inode *inode, int mask)
+int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
 	struct posix_acl *acl;
 	struct v9fs_session_info *v9ses;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	v9ses = v9fs_inode2v9ses(inode);
 	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) {
 		/*
diff --git a/fs/9p/acl.h b/fs/9p/acl.h
index 59e18c2..7ef3ac9 100644
--- a/fs/9p/acl.h
+++ b/fs/9p/acl.h
@@ -16,7 +16,7 @@
 
 #ifdef CONFIG_9P_FS_POSIX_ACL
 extern int v9fs_get_acl(struct inode *, struct p9_fid *);
-extern int v9fs_check_acl(struct inode *inode, int mask);
+extern int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags);
 extern int v9fs_acl_chmod(struct dentry *);
 extern int v9fs_set_create_acl(struct dentry *,
 			       struct posix_acl *, struct posix_acl *);
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index cbf4e50..466d2a4 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -51,7 +51,7 @@
  *
  */
 
-static int v9fs_dentry_delete(struct dentry *dentry)
+static int v9fs_dentry_delete(const struct dentry *dentry)
 {
 	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
 									dentry);
@@ -68,7 +68,7 @@
  *
  */
 
-static int v9fs_cached_dentry_delete(struct dentry *dentry)
+static int v9fs_cached_dentry_delete(const struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 34bf71b..5978298 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -237,9 +237,16 @@
  *
  */
 
+static void v9fs_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(vcookie_cache, v9fs_inode2cookie(inode));
+}
+
 void v9fs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
+	call_rcu(&inode->i_rcu, v9fs_i_callback);
 }
 #endif
 
@@ -270,11 +277,11 @@
 {
 	struct dentry *dentry;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&inode->i_lock);
 	/* Directory should have only one entry. */
 	BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
 	dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 	return dentry;
 }
 
@@ -628,9 +635,9 @@
 	}
 
 	if (v9ses->cache)
-		dentry->d_op = &v9fs_cached_dentry_operations;
+		d_set_d_op(dentry, &v9fs_cached_dentry_operations);
 	else
-		dentry->d_op = &v9fs_dentry_operations;
+		d_set_d_op(dentry, &v9fs_dentry_operations);
 
 	d_instantiate(dentry, inode);
 	err = v9fs_fid_add(dentry, fid);
@@ -742,7 +749,7 @@
 				err);
 			goto error;
 		}
-		dentry->d_op = &v9fs_cached_dentry_operations;
+		d_set_d_op(dentry, &v9fs_cached_dentry_operations);
 		d_instantiate(dentry, inode);
 		err = v9fs_fid_add(dentry, fid);
 		if (err < 0)
@@ -760,7 +767,7 @@
 			err = PTR_ERR(inode);
 			goto error;
 		}
-		dentry->d_op = &v9fs_dentry_operations;
+		d_set_d_op(dentry, &v9fs_dentry_operations);
 		d_instantiate(dentry, inode);
 	}
 	/* Now set the ACL based on the default value */
@@ -949,7 +956,7 @@
 				err);
 			goto error;
 		}
-		dentry->d_op = &v9fs_cached_dentry_operations;
+		d_set_d_op(dentry, &v9fs_cached_dentry_operations);
 		d_instantiate(dentry, inode);
 		err = v9fs_fid_add(dentry, fid);
 		if (err < 0)
@@ -966,7 +973,7 @@
 			err = PTR_ERR(inode);
 			goto error;
 		}
-		dentry->d_op = &v9fs_dentry_operations;
+		d_set_d_op(dentry, &v9fs_dentry_operations);
 		d_instantiate(dentry, inode);
 	}
 	/* Now set the ACL based on the default value */
@@ -1034,9 +1041,9 @@
 
 inst_out:
 	if (v9ses->cache)
-		dentry->d_op = &v9fs_cached_dentry_operations;
+		d_set_d_op(dentry, &v9fs_cached_dentry_operations);
 	else
-		dentry->d_op = &v9fs_dentry_operations;
+		d_set_d_op(dentry, &v9fs_dentry_operations);
 
 	d_add(dentry, inode);
 	return NULL;
@@ -1702,7 +1709,7 @@
 					err);
 			goto error;
 		}
-		dentry->d_op = &v9fs_cached_dentry_operations;
+		d_set_d_op(dentry, &v9fs_cached_dentry_operations);
 		d_instantiate(dentry, inode);
 		err = v9fs_fid_add(dentry, fid);
 		if (err < 0)
@@ -1715,7 +1722,7 @@
 			err = PTR_ERR(inode);
 			goto error;
 		}
-		dentry->d_op = &v9fs_dentry_operations;
+		d_set_d_op(dentry, &v9fs_dentry_operations);
 		d_instantiate(dentry, inode);
 	}
 
@@ -1849,7 +1856,7 @@
 		ihold(old_dentry->d_inode);
 	}
 
-	dentry->d_op = old_dentry->d_op;
+	d_set_d_op(dentry, old_dentry->d_op);
 	d_instantiate(dentry, old_dentry->d_inode);
 
 	return err;
@@ -1973,7 +1980,7 @@
 				err);
 			goto error;
 		}
-		dentry->d_op = &v9fs_cached_dentry_operations;
+		d_set_d_op(dentry, &v9fs_cached_dentry_operations);
 		d_instantiate(dentry, inode);
 		err = v9fs_fid_add(dentry, fid);
 		if (err < 0)
@@ -1989,7 +1996,7 @@
 			err = PTR_ERR(inode);
 			goto error;
 		}
-		dentry->d_op = &v9fs_dentry_operations;
+		d_set_d_op(dentry, &v9fs_dentry_operations);
 		d_instantiate(dentry, inode);
 	}
 	/* Now set the ACL based on the default value */
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index f4287e4..bf7693c 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -201,7 +201,8 @@
 };
 
 static int
-adfs_hash(struct dentry *parent, struct qstr *qstr)
+adfs_hash(const struct dentry *parent, const struct inode *inode,
+		struct qstr *qstr)
 {
 	const unsigned int name_len = ADFS_SB(parent->d_sb)->s_namelen;
 	const unsigned char *name;
@@ -237,17 +238,19 @@
  * requirements of the underlying filesystem.
  */
 static int
-adfs_compare(struct dentry *parent, struct qstr *entry, struct qstr *name)
+adfs_compare(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
 	int i;
 
-	if (entry->len != name->len)
+	if (len != name->len)
 		return 1;
 
 	for (i = 0; i < name->len; i++) {
 		char a, b;
 
-		a = entry->name[i];
+		a = str[i];
 		b = name->name[i];
 
 		if (a >= 'A' && a <= 'Z')
@@ -273,7 +276,7 @@
 	struct object_info obj;
 	int error;
 
-	dentry->d_op = &adfs_dentry_operations;	
+	d_set_d_op(dentry, &adfs_dentry_operations);
 	lock_kernel();
 	error = adfs_dir_lookup_byname(dir, &dentry->d_name, &obj);
 	if (error == 0) {
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 959dbff..a4041b5 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -240,9 +240,16 @@
 	return &ei->vfs_inode;
 }
 
+static void adfs_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(adfs_inode_cachep, ADFS_I(inode));
+}
+
 static void adfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
+	call_rcu(&inode->i_rcu, adfs_i_callback);
 }
 
 static void init_once(void *foo)
@@ -477,7 +484,7 @@
 		adfs_error(sb, "get root inode failed\n");
 		goto error;
 	} else
-		sb->s_root->d_op = &adfs_dentry_operations;
+		d_set_d_op(sb->s_root, &adfs_dentry_operations);
 	unlock_kernel();
 	return 0;
 
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index 7d0f0a3..3a4557e 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -128,7 +128,7 @@
 	void *data = dentry->d_fsdata;
 	struct list_head *head, *next;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&inode->i_lock);
 	head = &inode->i_dentry;
 	next = head->next;
 	while (next != head) {
@@ -139,7 +139,7 @@
 		}
 		next = next->next;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 }
 
 
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 914d1c0..944a404 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -13,11 +13,19 @@
 typedef int (*toupper_t)(int);
 
 static int	 affs_toupper(int ch);
-static int	 affs_hash_dentry(struct dentry *, struct qstr *);
-static int       affs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
+static int	 affs_hash_dentry(const struct dentry *,
+		const struct inode *, struct qstr *);
+static int       affs_compare_dentry(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
 static int	 affs_intl_toupper(int ch);
-static int	 affs_intl_hash_dentry(struct dentry *, struct qstr *);
-static int       affs_intl_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
+static int	 affs_intl_hash_dentry(const struct dentry *,
+		const struct inode *, struct qstr *);
+static int       affs_intl_compare_dentry(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
 
 const struct dentry_operations affs_dentry_operations = {
 	.d_hash		= affs_hash_dentry,
@@ -58,13 +66,13 @@
  * Note: the dentry argument is the parent dentry.
  */
 static inline int
-__affs_hash_dentry(struct dentry *dentry, struct qstr *qstr, toupper_t toupper)
+__affs_hash_dentry(struct qstr *qstr, toupper_t toupper)
 {
 	const u8 *name = qstr->name;
 	unsigned long hash;
 	int i;
 
-	i = affs_check_name(qstr->name,qstr->len);
+	i = affs_check_name(qstr->name, qstr->len);
 	if (i)
 		return i;
 
@@ -78,39 +86,41 @@
 }
 
 static int
-affs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
+affs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
-	return __affs_hash_dentry(dentry, qstr, affs_toupper);
+	return __affs_hash_dentry(qstr, affs_toupper);
 }
 static int
-affs_intl_hash_dentry(struct dentry *dentry, struct qstr *qstr)
+affs_intl_hash_dentry(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
-	return __affs_hash_dentry(dentry, qstr, affs_intl_toupper);
+	return __affs_hash_dentry(qstr, affs_intl_toupper);
 }
 
-static inline int
-__affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b, toupper_t toupper)
+static inline int __affs_compare_dentry(unsigned int len,
+		const char *str, const struct qstr *name, toupper_t toupper)
 {
-	const u8 *aname = a->name;
-	const u8 *bname = b->name;
-	int len;
+	const u8 *aname = str;
+	const u8 *bname = name->name;
 
-	/* 'a' is the qstr of an already existing dentry, so the name
-	 * must be valid. 'b' must be validated first.
+	/*
+	 * 'str' is the name of an already existing dentry, so the name
+	 * must be valid. 'name' must be validated first.
 	 */
 
-	if (affs_check_name(b->name,b->len))
+	if (affs_check_name(name->name, name->len))
 		return 1;
 
-	/* If the names are longer than the allowed 30 chars,
+	/*
+	 * If the names are longer than the allowed 30 chars,
 	 * the excess is ignored, so their length may differ.
 	 */
-	len = a->len;
 	if (len >= 30) {
-		if (b->len < 30)
+		if (name->len < 30)
 			return 1;
 		len = 30;
-	} else if (len != b->len)
+	} else if (len != name->len)
 		return 1;
 
 	for (; len > 0; len--)
@@ -121,14 +131,18 @@
 }
 
 static int
-affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
+affs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	return __affs_compare_dentry(dentry, a, b, affs_toupper);
+	return __affs_compare_dentry(len, str, name, affs_toupper);
 }
 static int
-affs_intl_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
+affs_intl_compare_dentry(const struct dentry *parent,const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	return __affs_compare_dentry(dentry, a, b, affs_intl_toupper);
+	return __affs_compare_dentry(len, str, name, affs_intl_toupper);
 }
 
 /*
@@ -226,7 +240,7 @@
 		if (IS_ERR(inode))
 			return ERR_CAST(inode);
 	}
-	dentry->d_op = AFFS_SB(sb)->s_flags & SF_INTL ? &affs_intl_dentry_operations : &affs_dentry_operations;
+	d_set_d_op(dentry, AFFS_SB(sb)->s_flags & SF_INTL ? &affs_intl_dentry_operations : &affs_dentry_operations);
 	d_add(dentry, inode);
 	return NULL;
 }
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 0cf7f43..d39081b 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -95,9 +95,16 @@
 	return &i->vfs_inode;
 }
 
+static void affs_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(affs_inode_cachep, AFFS_I(inode));
+}
+
 static void affs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(affs_inode_cachep, AFFS_I(inode));
+	call_rcu(&inode->i_rcu, affs_i_callback);
 }
 
 static void init_once(void *foo)
@@ -475,7 +482,7 @@
 		printk(KERN_ERR "AFFS: Get root inode failed\n");
 		goto out_error;
 	}
-	sb->s_root->d_op = &affs_dentry_operations;
+	d_set_d_op(sb->s_root, &affs_dentry_operations);
 
 	pr_debug("AFFS: s_flags=%lX\n",sb->s_flags);
 	return 0;
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 5439e1b..34a3263 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/namei.h>
 #include <linux/pagemap.h>
 #include <linux/ctype.h>
 #include <linux/sched.h>
@@ -23,7 +24,7 @@
 static int afs_dir_open(struct inode *inode, struct file *file);
 static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
 static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
-static int afs_d_delete(struct dentry *dentry);
+static int afs_d_delete(const struct dentry *dentry);
 static void afs_d_release(struct dentry *dentry);
 static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
 				  loff_t fpos, u64 ino, unsigned dtype);
@@ -581,7 +582,7 @@
 	}
 
 success:
-	dentry->d_op = &afs_fs_dentry_operations;
+	d_set_d_op(dentry, &afs_fs_dentry_operations);
 
 	d_add(dentry, inode);
 	_leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }",
@@ -607,6 +608,9 @@
 	void *dir_version;
 	int ret;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
 	vnode = AFS_FS_I(dentry->d_inode);
 
 	if (dentry->d_inode)
@@ -730,7 +734,7 @@
  * - called from dput() when d_count is going to 0.
  * - return 1 to request dentry be unhashed, 0 otherwise
  */
-static int afs_d_delete(struct dentry *dentry)
+static int afs_d_delete(const struct dentry *dentry)
 {
 	_enter("%s", dentry->d_name.name);
 
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index cca8eef..6d4bc1c 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -624,7 +624,7 @@
 extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
 extern void afs_zap_permits(struct rcu_head *);
 extern struct key *afs_request_key(struct afs_cell *);
-extern int afs_permission(struct inode *, int);
+extern int afs_permission(struct inode *, int, unsigned int);
 
 /*
  * server.c
diff --git a/fs/afs/security.c b/fs/afs/security.c
index bb4ed14..f44b9d3 100644
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -285,13 +285,16 @@
  * - AFS ACLs are attached to directories only, and a file is controlled by its
  *   parent directory's ACL
  */
-int afs_permission(struct inode *inode, int mask)
+int afs_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	struct afs_vnode *vnode = AFS_FS_I(inode);
 	afs_access_t uninitialized_var(access);
 	struct key *key;
 	int ret;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	_enter("{{%x:%u},%lx},%x,",
 	       vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask);
 
@@ -347,7 +350,7 @@
 	}
 
 	key_put(key);
-	ret = generic_permission(inode, mask, NULL);
+	ret = generic_permission(inode, mask, flags, NULL);
 	_leave(" = %d", ret);
 	return ret;
 
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 27201cff..f901a9d 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -498,6 +498,14 @@
 	return &vnode->vfs_inode;
 }
 
+static void afs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	struct afs_vnode *vnode = AFS_FS_I(inode);
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kmem_cache_free(afs_inode_cachep, vnode);
+}
+
 /*
  * destroy an AFS inode struct
  */
@@ -511,7 +519,7 @@
 
 	ASSERTCMP(vnode->server, ==, NULL);
 
-	kmem_cache_free(afs_inode_cachep, vnode);
+	call_rcu(&inode->i_rcu, afs_i_callback);
 	atomic_dec(&afs_count_active_inodes);
 }
 
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 57ce55b..5fd38112a 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -102,7 +102,7 @@
 	this.name = name;
 	this.len = strlen(name);
 	this.hash = 0;
-	path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
+	path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this);
 	if (!path.dentry)
 		goto err_module;
 
@@ -113,7 +113,7 @@
 	 */
 	ihold(anon_inode_inode);
 
-	path.dentry->d_op = &anon_inodefs_dentry_operations;
+	d_set_d_op(path.dentry, &anon_inodefs_dentry_operations);
 	d_instantiate(path.dentry, anon_inode_inode);
 
 	error = -ENFILE;
@@ -232,7 +232,7 @@
 	return 0;
 
 err_mntput:
-	mntput(anon_inode_mnt);
+	mntput_long(anon_inode_mnt);
 err_unregister_filesystem:
 	unregister_filesystem(&anon_inode_fs_type);
 err_exit:
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 3d283ab..0fffe1c 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -16,6 +16,7 @@
 #include <linux/auto_fs4.h>
 #include <linux/auto_dev-ioctl.h>
 #include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/list.h>
 
 /* This is the range of ioctl() numbers we claim as ours */
@@ -60,6 +61,8 @@
 		current->pid, __func__, ##args);	\
 } while (0)
 
+extern spinlock_t autofs4_lock;
+
 /* Unified info structure.  This is pointed to by both the dentry and
    inode structures.  Each file in the filesystem has an instance of this
    structure.  It holds a reference to the dentry, so dentries are never
@@ -254,17 +257,15 @@
 	return dentry->d_inode && !d_unhashed(dentry);
 }
 
-static inline int __simple_empty(struct dentry *dentry)
+static inline void __autofs4_add_expiring(struct dentry *dentry)
 {
-	struct dentry *child;
-	int ret = 0;
-
-	list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
-		if (simple_positive(child))
-			goto out;
-	ret = 1;
-out:
-	return ret;
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	if (ino) {
+		if (list_empty(&ino->expiring))
+			list_add(&ino->expiring, &sbi->expiring_list);
+	}
+	return;
 }
 
 static inline void autofs4_add_expiring(struct dentry *dentry)
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index a796c94..cc1d013 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -91,24 +91,64 @@
 }
 
 /*
- * Calculate next entry in top down tree traversal.
- * From next_mnt in namespace.c - elegant.
+ * Calculate and dget next entry in top down tree traversal.
  */
-static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
+static struct dentry *get_next_positive_dentry(struct dentry *prev,
+						struct dentry *root)
 {
-	struct list_head *next = p->d_subdirs.next;
+	struct list_head *next;
+	struct dentry *p, *ret;
 
+	if (prev == NULL)
+		return dget(prev);
+
+	spin_lock(&autofs4_lock);
+relock:
+	p = prev;
+	spin_lock(&p->d_lock);
+again:
+	next = p->d_subdirs.next;
 	if (next == &p->d_subdirs) {
 		while (1) {
-			if (p == root)
+			struct dentry *parent;
+
+			if (p == root) {
+				spin_unlock(&p->d_lock);
+				spin_unlock(&autofs4_lock);
+				dput(prev);
 				return NULL;
+			}
+
+			parent = p->d_parent;
+			if (!spin_trylock(&parent->d_lock)) {
+				spin_unlock(&p->d_lock);
+				cpu_relax();
+				goto relock;
+			}
+			spin_unlock(&p->d_lock);
 			next = p->d_u.d_child.next;
-			if (next != &p->d_parent->d_subdirs)
+			p = parent;
+			if (next != &parent->d_subdirs)
 				break;
-			p = p->d_parent;
 		}
 	}
-	return list_entry(next, struct dentry, d_u.d_child);
+	ret = list_entry(next, struct dentry, d_u.d_child);
+
+	spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
+	/* Negative dentry - try next */
+	if (!simple_positive(ret)) {
+		spin_unlock(&ret->d_lock);
+		p = ret;
+		goto again;
+	}
+	dget_dlock(ret);
+	spin_unlock(&ret->d_lock);
+	spin_unlock(&p->d_lock);
+	spin_unlock(&autofs4_lock);
+
+	dput(prev);
+
+	return ret;
 }
 
 /*
@@ -158,18 +198,11 @@
 	if (!simple_positive(top))
 		return 1;
 
-	spin_lock(&dcache_lock);
-	for (p = top; p; p = next_dentry(p, top)) {
-		/* Negative dentry - give up */
-		if (!simple_positive(p))
-			continue;
-
+	p = NULL;
+	while ((p = get_next_positive_dentry(p, top))) {
 		DPRINTK("dentry %p %.*s",
 			p, (int) p->d_name.len, p->d_name.name);
 
-		p = dget(p);
-		spin_unlock(&dcache_lock);
-
 		/*
 		 * Is someone visiting anywhere in the subtree ?
 		 * If there's no mount we need to check the usage
@@ -198,16 +231,13 @@
 			else
 				ino_count++;
 
-			if (atomic_read(&p->d_count) > ino_count) {
+			if (p->d_count > ino_count) {
 				top_ino->last_used = jiffies;
 				dput(p);
 				return 1;
 			}
 		}
-		dput(p);
-		spin_lock(&dcache_lock);
 	}
-	spin_unlock(&dcache_lock);
 
 	/* Timeout of a tree mount is ultimately determined by its top dentry */
 	if (!autofs4_can_expire(top, timeout, do_now))
@@ -226,32 +256,21 @@
 	DPRINTK("parent %p %.*s",
 		parent, (int)parent->d_name.len, parent->d_name.name);
 
-	spin_lock(&dcache_lock);
-	for (p = parent; p; p = next_dentry(p, parent)) {
-		/* Negative dentry - give up */
-		if (!simple_positive(p))
-			continue;
-
+	p = NULL;
+	while ((p = get_next_positive_dentry(p, parent))) {
 		DPRINTK("dentry %p %.*s",
 			p, (int) p->d_name.len, p->d_name.name);
 
-		p = dget(p);
-		spin_unlock(&dcache_lock);
-
 		if (d_mountpoint(p)) {
 			/* Can we umount this guy */
 			if (autofs4_mount_busy(mnt, p))
-				goto cont;
+				continue;
 
 			/* Can we expire this guy */
 			if (autofs4_can_expire(p, timeout, do_now))
 				return p;
 		}
-cont:
-		dput(p);
-		spin_lock(&dcache_lock);
 	}
-	spin_unlock(&dcache_lock);
 	return NULL;
 }
 
@@ -276,7 +295,9 @@
 		struct autofs_info *ino = autofs4_dentry_ino(root);
 		if (d_mountpoint(root)) {
 			ino->flags |= AUTOFS_INF_MOUNTPOINT;
-			root->d_mounted--;
+			spin_lock(&root->d_lock);
+			root->d_flags &= ~DCACHE_MOUNTED;
+			spin_unlock(&root->d_lock);
 		}
 		ino->flags |= AUTOFS_INF_EXPIRING;
 		init_completion(&ino->expire_complete);
@@ -302,8 +323,8 @@
 {
 	unsigned long timeout;
 	struct dentry *root = sb->s_root;
+	struct dentry *dentry;
 	struct dentry *expired = NULL;
-	struct list_head *next;
 	int do_now = how & AUTOFS_EXP_IMMEDIATE;
 	int exp_leaves = how & AUTOFS_EXP_LEAVES;
 	struct autofs_info *ino;
@@ -315,23 +336,8 @@
 	now = jiffies;
 	timeout = sbi->exp_timeout;
 
-	spin_lock(&dcache_lock);
-	next = root->d_subdirs.next;
-
-	/* On exit from the loop expire is set to a dgot dentry
-	 * to expire or it's NULL */
-	while ( next != &root->d_subdirs ) {
-		struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
-
-		/* Negative dentry - give up */
-		if (!simple_positive(dentry)) {
-			next = next->next;
-			continue;
-		}
-
-		dentry = dget(dentry);
-		spin_unlock(&dcache_lock);
-
+	dentry = NULL;
+	while ((dentry = get_next_positive_dentry(dentry, root))) {
 		spin_lock(&sbi->fs_lock);
 		ino = autofs4_dentry_ino(dentry);
 
@@ -347,7 +353,7 @@
 
 			/* Path walk currently on this dentry? */
 			ino_count = atomic_read(&ino->count) + 2;
-			if (atomic_read(&dentry->d_count) > ino_count)
+			if (dentry->d_count > ino_count)
 				goto next;
 
 			/* Can we umount this guy */
@@ -369,7 +375,7 @@
 		if (!exp_leaves) {
 			/* Path walk currently on this dentry? */
 			ino_count = atomic_read(&ino->count) + 1;
-			if (atomic_read(&dentry->d_count) > ino_count)
+			if (dentry->d_count > ino_count)
 				goto next;
 
 			if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
@@ -383,7 +389,7 @@
 		} else {
 			/* Path walk currently on this dentry? */
 			ino_count = atomic_read(&ino->count) + 1;
-			if (atomic_read(&dentry->d_count) > ino_count)
+			if (dentry->d_count > ino_count)
 				goto next;
 
 			expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
@@ -394,11 +400,7 @@
 		}
 next:
 		spin_unlock(&sbi->fs_lock);
-		dput(dentry);
-		spin_lock(&dcache_lock);
-		next = next->next;
 	}
-	spin_unlock(&dcache_lock);
 	return NULL;
 
 found:
@@ -408,9 +410,13 @@
 	ino->flags |= AUTOFS_INF_EXPIRING;
 	init_completion(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
+	spin_lock(&expired->d_parent->d_lock);
+	spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
 	list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&expired->d_lock);
+	spin_unlock(&expired->d_parent->d_lock);
+	spin_unlock(&autofs4_lock);
 	return expired;
 }
 
@@ -499,7 +505,14 @@
 
 		spin_lock(&sbi->fs_lock);
 		if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
-			sb->s_root->d_mounted++;
+			spin_lock(&sb->s_root->d_lock);
+			/*
+			 * If we haven't been expired away, then reset
+			 * mounted status.
+			 */
+			if (mnt->mnt_parent != mnt)
+				sb->s_root->d_flags |= DCACHE_MOUNTED;
+			spin_unlock(&sb->s_root->d_lock);
 			ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
 		}
 		ino->flags &= ~AUTOFS_INF_EXPIRING;
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index ac87e49..a7bdb9d 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -309,7 +309,7 @@
 		goto fail_iput;
 	pipe = NULL;
 
-	root->d_op = &autofs4_sb_dentry_operations;
+	d_set_d_op(root, &autofs4_sb_dentry_operations);
 	root->d_fsdata = ino;
 
 	/* Can this call block? */
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index d34896c..651e4ef 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -23,6 +23,8 @@
 
 #include "autofs_i.h"
 
+DEFINE_SPINLOCK(autofs4_lock);
+
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
 static int autofs4_dir_unlink(struct inode *,struct dentry *);
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
@@ -142,12 +144,15 @@
 	 * autofs file system so just let the libfs routines handle
 	 * it.
 	 */
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
+	spin_lock(&dentry->d_lock);
 	if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&dentry->d_lock);
+		spin_unlock(&autofs4_lock);
 		return -ENOENT;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&autofs4_lock);
 
 out:
 	return dcache_dir_open(inode, file);
@@ -252,9 +257,11 @@
 	/* We trigger a mount for almost all flags */
 	lookup_type = autofs4_need_mount(nd->flags);
 	spin_lock(&sbi->fs_lock);
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
+	spin_lock(&dentry->d_lock);
 	if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&dentry->d_lock);
+		spin_unlock(&autofs4_lock);
 		spin_unlock(&sbi->fs_lock);
 		goto follow;
 	}
@@ -266,7 +273,8 @@
 	 */
 	if (ino->flags & AUTOFS_INF_PENDING ||
 	    (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&dentry->d_lock);
+		spin_unlock(&autofs4_lock);
 		spin_unlock(&sbi->fs_lock);
 
 		status = try_to_fill_dentry(dentry, nd->flags);
@@ -275,7 +283,8 @@
 
 		goto follow;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&autofs4_lock);
 	spin_unlock(&sbi->fs_lock);
 follow:
 	/*
@@ -306,12 +315,19 @@
  */
 static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *dir = dentry->d_parent->d_inode;
-	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
-	int oz_mode = autofs4_oz_mode(sbi);
+	struct inode *dir;
+	struct autofs_sb_info *sbi;
+	int oz_mode;
 	int flags = nd ? nd->flags : 0;
 	int status = 1;
 
+	if (flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	dir = dentry->d_parent->d_inode;
+	sbi = autofs4_sbi(dir->i_sb);
+	oz_mode = autofs4_oz_mode(sbi);
+
 	/* Pending dentry */
 	spin_lock(&sbi->fs_lock);
 	if (autofs4_ispending(dentry)) {
@@ -346,12 +362,14 @@
 		return 0;
 
 	/* Check for a non-mountpoint directory with no contents */
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
+	spin_lock(&dentry->d_lock);
 	if (S_ISDIR(dentry->d_inode->i_mode) &&
 	    !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
 		DPRINTK("dentry=%p %.*s, emptydir",
 			 dentry, dentry->d_name.len, dentry->d_name.name);
-		spin_unlock(&dcache_lock);
+		spin_unlock(&dentry->d_lock);
+		spin_unlock(&autofs4_lock);
 
 		/* The daemon never causes a mount to trigger */
 		if (oz_mode)
@@ -367,7 +385,8 @@
 
 		return status;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&autofs4_lock);
 
 	return 1;
 }
@@ -422,7 +441,7 @@
 	const unsigned char *str = name->name;
 	struct list_head *p, *head;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
 	spin_lock(&sbi->lookup_lock);
 	head = &sbi->active_list;
 	list_for_each(p, head) {
@@ -436,7 +455,7 @@
 		spin_lock(&active->d_lock);
 
 		/* Already gone? */
-		if (atomic_read(&active->d_count) == 0)
+		if (active->d_count == 0)
 			goto next;
 
 		qstr = &active->d_name;
@@ -452,17 +471,17 @@
 			goto next;
 
 		if (d_unhashed(active)) {
-			dget(active);
+			dget_dlock(active);
 			spin_unlock(&active->d_lock);
 			spin_unlock(&sbi->lookup_lock);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&autofs4_lock);
 			return active;
 		}
 next:
 		spin_unlock(&active->d_lock);
 	}
 	spin_unlock(&sbi->lookup_lock);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&autofs4_lock);
 
 	return NULL;
 }
@@ -477,7 +496,7 @@
 	const unsigned char *str = name->name;
 	struct list_head *p, *head;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
 	spin_lock(&sbi->lookup_lock);
 	head = &sbi->expiring_list;
 	list_for_each(p, head) {
@@ -507,17 +526,17 @@
 			goto next;
 
 		if (d_unhashed(expiring)) {
-			dget(expiring);
+			dget_dlock(expiring);
 			spin_unlock(&expiring->d_lock);
 			spin_unlock(&sbi->lookup_lock);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&autofs4_lock);
 			return expiring;
 		}
 next:
 		spin_unlock(&expiring->d_lock);
 	}
 	spin_unlock(&sbi->lookup_lock);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&autofs4_lock);
 
 	return NULL;
 }
@@ -559,7 +578,7 @@
 		 * we check for the hashed dentry and return the newly
 		 * hashed dentry.
 		 */
-		dentry->d_op = &autofs4_root_dentry_operations;
+		d_set_d_op(dentry, &autofs4_root_dentry_operations);
 
 		/*
 		 * And we need to ensure that the same dentry is used for
@@ -698,9 +717,9 @@
 	d_add(dentry, inode);
 
 	if (dir == dir->i_sb->s_root->d_inode)
-		dentry->d_op = &autofs4_root_dentry_operations;
+		d_set_d_op(dentry, &autofs4_root_dentry_operations);
 	else
-		dentry->d_op = &autofs4_dentry_operations;
+		d_set_d_op(dentry, &autofs4_dentry_operations);
 
 	dentry->d_fsdata = ino;
 	ino->dentry = dget(dentry);
@@ -753,12 +772,12 @@
 
 	dir->i_mtime = CURRENT_TIME;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
 	autofs4_add_expiring(dentry);
 	spin_lock(&dentry->d_lock);
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&autofs4_lock);
 
 	return 0;
 }
@@ -775,16 +794,20 @@
 	if (!autofs4_oz_mode(sbi))
 		return -EACCES;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&autofs4_lock);
+	spin_lock(&sbi->lookup_lock);
+	spin_lock(&dentry->d_lock);
 	if (!list_empty(&dentry->d_subdirs)) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&dentry->d_lock);
+		spin_unlock(&sbi->lookup_lock);
+		spin_unlock(&autofs4_lock);
 		return -ENOTEMPTY;
 	}
-	autofs4_add_expiring(dentry);
-	spin_lock(&dentry->d_lock);
+	__autofs4_add_expiring(dentry);
+	spin_unlock(&sbi->lookup_lock);
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&autofs4_lock);
 
 	if (atomic_dec_and_test(&ino->count)) {
 		p_ino = autofs4_dentry_ino(dentry->d_parent);
@@ -829,9 +852,9 @@
 	d_add(dentry, inode);
 
 	if (dir == dir->i_sb->s_root->d_inode)
-		dentry->d_op = &autofs4_root_dentry_operations;
+		d_set_d_op(dentry, &autofs4_root_dentry_operations);
 	else
-		dentry->d_op = &autofs4_dentry_operations;
+		d_set_d_op(dentry, &autofs4_dentry_operations);
 
 	dentry->d_fsdata = ino;
 	ino->dentry = dget(dentry);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 2341375..c5f8459 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -186,16 +186,26 @@
 {
 	struct dentry *root = sbi->sb->s_root;
 	struct dentry *tmp;
-	char *buf = *name;
+	char *buf;
 	char *p;
-	int len = 0;
+	int len;
+	unsigned seq;
 
-	spin_lock(&dcache_lock);
+rename_retry:
+	buf = *name;
+	len = 0;
+
+	seq = read_seqbegin(&rename_lock);
+	rcu_read_lock();
+	spin_lock(&autofs4_lock);
 	for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
 		len += tmp->d_name.len + 1;
 
 	if (!len || --len > NAME_MAX) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&autofs4_lock);
+		rcu_read_unlock();
+		if (read_seqretry(&rename_lock, seq))
+			goto rename_retry;
 		return 0;
 	}
 
@@ -208,7 +218,10 @@
 		p -= tmp->d_name.len;
 		strncpy(p, tmp->d_name.name, tmp->d_name.len);
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&autofs4_lock);
+	rcu_read_unlock();
+	if (read_seqretry(&rename_lock, seq))
+		goto rename_retry;
 
 	return len;
 }
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index f024d8a..9ad2369 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -229,8 +229,11 @@
 	return -EIO;
 }
 
-static int bad_inode_permission(struct inode *inode, int mask)
+static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags)
 {
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	return -EIO;
 }
 
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index aa4e7c7..de93581 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -284,12 +284,18 @@
         return &bi->vfs_inode;
 }
 
-static void
-befs_destroy_inode(struct inode *inode)
+static void befs_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(befs_inode_cachep, BEFS_I(inode));
 }
 
+static void befs_destroy_inode(struct inode *inode)
+{
+	call_rcu(&inode->i_rcu, befs_i_callback);
+}
+
 static void init_once(void *foo)
 {
         struct befs_inode_info *bi = (struct befs_inode_info *) foo;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 76db6d7..a8e37f8 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -248,9 +248,16 @@
 	return &bi->vfs_inode;
 }
 
+static void bfs_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(bfs_inode_cachep, BFS_I(inode));
+}
+
 static void bfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(bfs_inode_cachep, BFS_I(inode));
+	call_rcu(&inode->i_rcu, bfs_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 4230252..771f235 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -409,13 +409,20 @@
 	return &ei->vfs_inode;
 }
 
-static void bdev_destroy_inode(struct inode *inode)
+static void bdev_i_callback(struct rcu_head *head)
 {
+	struct inode *inode = container_of(head, struct inode, i_rcu);
 	struct bdev_inode *bdi = BDEV_I(inode);
 
+	INIT_LIST_HEAD(&inode->i_dentry);
 	kmem_cache_free(bdev_cachep, bdi);
 }
 
+static void bdev_destroy_inode(struct inode *inode)
+{
+	call_rcu(&inode->i_rcu, bdev_i_callback);
+}
+
 static void init_once(void *foo)
 {
 	struct bdev_inode *ei = (struct bdev_inode *) foo;
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 2222d16..6ae2c8c 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -185,18 +185,23 @@
 	return ret;
 }
 
-int btrfs_check_acl(struct inode *inode, int mask)
+int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct posix_acl *acl;
 	int error = -EAGAIN;
 
-	acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);
+	if (flags & IPERM_FLAG_RCU) {
+		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
+			error = -ECHILD;
 
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (acl) {
-		error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
+	} else {
+		struct posix_acl *acl;
+		acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		if (acl) {
+			error = posix_acl_permission(inode, acl, mask);
+			posix_acl_release(acl);
+		}
 	}
 
 	return error;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index af52f6d..a142d20 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2544,7 +2544,7 @@
 
 /* acl.c */
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
-int btrfs_check_acl(struct inode *inode, int mask);
+int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags);
 #else
 #define btrfs_check_acl NULL
 #endif
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index 659f532..0ccf9a8 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -110,7 +110,7 @@
 
 	dentry = d_obtain_alias(inode);
 	if (!IS_ERR(dentry))
-		dentry->d_op = &btrfs_dentry_operations;
+		d_set_d_op(dentry, &btrfs_dentry_operations);
 	return dentry;
 fail:
 	srcu_read_unlock(&fs_info->subvol_srcu, index);
@@ -225,7 +225,7 @@
 	key.offset = 0;
 	dentry = d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root, NULL));
 	if (!IS_ERR(dentry))
-		dentry->d_op = &btrfs_dentry_operations;
+		d_set_d_op(dentry, &btrfs_dentry_operations);
 	return dentry;
 fail:
 	btrfs_free_path(path);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 72f31ec..a0ff46a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4084,7 +4084,7 @@
 	int index;
 	int ret;
 
-	dentry->d_op = &btrfs_dentry_operations;
+	d_set_d_op(dentry, &btrfs_dentry_operations);
 
 	if (dentry->d_name.len > BTRFS_NAME_LEN)
 		return ERR_PTR(-ENAMETOOLONG);
@@ -4127,7 +4127,7 @@
 	return inode;
 }
 
-static int btrfs_dentry_delete(struct dentry *dentry)
+static int btrfs_dentry_delete(const struct dentry *dentry)
 {
 	struct btrfs_root *root;
 
@@ -6495,6 +6495,13 @@
 	return inode;
 }
 
+static void btrfs_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(btrfs_inode_cachep, BTRFS_I(inode));
+}
+
 void btrfs_destroy_inode(struct inode *inode)
 {
 	struct btrfs_ordered_extent *ordered;
@@ -6564,7 +6571,7 @@
 	inode_tree_del(inode);
 	btrfs_drop_extent_cache(inode, 0, (u64)-1, 0);
 free:
-	kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
+	call_rcu(&inode->i_rcu, btrfs_i_callback);
 }
 
 int btrfs_drop_inode(struct inode *inode)
@@ -7204,11 +7211,11 @@
 	return __set_page_dirty_nobuffers(page);
 }
 
-static int btrfs_permission(struct inode *inode, int mask)
+static int btrfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE))
 		return -EACCES;
-	return generic_permission(inode, mask, btrfs_check_acl);
+	return generic_permission(inode, mask, flags, btrfs_check_acl);
 }
 
 static const struct inode_operations btrfs_dir_inode_operations = {
diff --git a/fs/buffer.c b/fs/buffer.c
index 5930e38..2219a76 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1270,12 +1270,10 @@
 static void bh_lru_install(struct buffer_head *bh)
 {
 	struct buffer_head *evictee = NULL;
-	struct bh_lru *lru;
 
 	check_irqs_on();
 	bh_lru_lock();
-	lru = &__get_cpu_var(bh_lrus);
-	if (lru->bhs[0] != bh) {
+	if (__this_cpu_read(bh_lrus.bhs[0]) != bh) {
 		struct buffer_head *bhs[BH_LRU_SIZE];
 		int in;
 		int out = 0;
@@ -1283,7 +1281,8 @@
 		get_bh(bh);
 		bhs[out++] = bh;
 		for (in = 0; in < BH_LRU_SIZE; in++) {
-			struct buffer_head *bh2 = lru->bhs[in];
+			struct buffer_head *bh2 =
+				__this_cpu_read(bh_lrus.bhs[in]);
 
 			if (bh2 == bh) {
 				__brelse(bh2);
@@ -1298,7 +1297,7 @@
 		}
 		while (out < BH_LRU_SIZE)
 			bhs[out++] = NULL;
-		memcpy(lru->bhs, bhs, sizeof(bhs));
+		memcpy(__this_cpu_ptr(&bh_lrus.bhs), bhs, sizeof(bhs));
 	}
 	bh_lru_unlock();
 
@@ -1313,23 +1312,22 @@
 lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *ret = NULL;
-	struct bh_lru *lru;
 	unsigned int i;
 
 	check_irqs_on();
 	bh_lru_lock();
-	lru = &__get_cpu_var(bh_lrus);
 	for (i = 0; i < BH_LRU_SIZE; i++) {
-		struct buffer_head *bh = lru->bhs[i];
+		struct buffer_head *bh = __this_cpu_read(bh_lrus.bhs[i]);
 
 		if (bh && bh->b_bdev == bdev &&
 				bh->b_blocknr == block && bh->b_size == size) {
 			if (i) {
 				while (i) {
-					lru->bhs[i] = lru->bhs[i - 1];
+					__this_cpu_write(bh_lrus.bhs[i],
+						__this_cpu_read(bh_lrus.bhs[i - 1]));
 					i--;
 				}
-				lru->bhs[0] = bh;
+				__this_cpu_write(bh_lrus.bhs[0], bh);
 			}
 			get_bh(bh);
 			ret = bh;
@@ -3203,22 +3201,23 @@
 	int i;
 	int tot = 0;
 
-	if (__get_cpu_var(bh_accounting).ratelimit++ < 4096)
+	if (__this_cpu_inc_return(bh_accounting.ratelimit) - 1 < 4096)
 		return;
-	__get_cpu_var(bh_accounting).ratelimit = 0;
+	__this_cpu_write(bh_accounting.ratelimit, 0);
 	for_each_online_cpu(i)
 		tot += per_cpu(bh_accounting, i).nr;
 	buffer_heads_over_limit = (tot > max_buffer_heads);
 }
-	
+
 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
 {
 	struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
 	if (ret) {
 		INIT_LIST_HEAD(&ret->b_assoc_buffers);
-		get_cpu_var(bh_accounting).nr++;
+		preempt_disable();
+		__this_cpu_inc(bh_accounting.nr);
 		recalc_bh_state();
-		put_cpu_var(bh_accounting);
+		preempt_enable();
 	}
 	return ret;
 }
@@ -3228,9 +3227,10 @@
 {
 	BUG_ON(!list_empty(&bh->b_assoc_buffers));
 	kmem_cache_free(bh_cachep, bh);
-	get_cpu_var(bh_accounting).nr--;
+	preempt_disable();
+	__this_cpu_dec(bh_accounting.nr);
 	recalc_bh_state();
-	put_cpu_var(bh_accounting);
+	preempt_enable();
 }
 EXPORT_SYMBOL(free_buffer_head);
 
@@ -3243,9 +3243,8 @@
 		brelse(b->bhs[i]);
 		b->bhs[i] = NULL;
 	}
-	get_cpu_var(bh_accounting).nr += per_cpu(bh_accounting, cpu).nr;
+	this_cpu_add(bh_accounting.nr, per_cpu(bh_accounting, cpu).nr);
 	per_cpu(bh_accounting, cpu).nr = 0;
-	put_cpu_var(bh_accounting);
 }
 
 static int buffer_cpu_notify(struct notifier_block *self,
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index d902948..fa7ca04 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -42,11 +42,11 @@
 
 	if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
 	    ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
-		dentry->d_op = &ceph_dentry_ops;
+		d_set_d_op(dentry, &ceph_dentry_ops);
 	else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
-		dentry->d_op = &ceph_snapdir_dentry_ops;
+		d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
 	else
-		dentry->d_op = &ceph_snap_dentry_ops;
+		d_set_d_op(dentry, &ceph_snap_dentry_ops);
 
 	di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO);
 	if (!di)
@@ -112,7 +112,7 @@
 	dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos,
 	     last);
 
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 
 	/* start at beginning? */
 	if (filp->f_pos == 2 || last == NULL ||
@@ -136,6 +136,7 @@
 			fi->at_end = 1;
 			goto out_unlock;
 		}
+		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
 		if (!d_unhashed(dentry) && dentry->d_inode &&
 		    ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
 		    ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
@@ -145,13 +146,15 @@
 		     dentry->d_name.len, dentry->d_name.name, di->offset,
 		     filp->f_pos, d_unhashed(dentry) ? " unhashed" : "",
 		     !dentry->d_inode ? " null" : "");
+		spin_unlock(&dentry->d_lock);
 		p = p->prev;
 		dentry = list_entry(p, struct dentry, d_u.d_child);
 		di = ceph_dentry(dentry);
 	}
 
-	atomic_inc(&dentry->d_count);
-	spin_unlock(&dcache_lock);
+	dget_dlock(dentry);
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&parent->d_lock);
 
 	dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos,
 	     dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
@@ -177,19 +180,19 @@
 
 	filp->f_pos++;
 
-	/* make sure a dentry wasn't dropped while we didn't have dcache_lock */
+	/* make sure a dentry wasn't dropped while we didn't have parent lock */
 	if (!ceph_i_test(dir, CEPH_I_COMPLETE)) {
 		dout(" lost I_COMPLETE on %p; falling back to mds\n", dir);
 		err = -EAGAIN;
 		goto out;
 	}
 
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 	p = p->prev;	/* advance to next dentry */
 	goto more;
 
 out_unlock:
-	spin_unlock(&dcache_lock);
+	spin_unlock(&parent->d_lock);
 out:
 	if (last)
 		dput(last);
@@ -987,7 +990,12 @@
  */
 static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *dir = dentry->d_parent->d_inode;
+	struct inode *dir;
+
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	dir = dentry->d_parent->d_inode;
 
 	dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
 	     dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index bf12865..e61de4f 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -368,6 +368,15 @@
 	return &ci->vfs_inode;
 }
 
+static void ceph_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	struct ceph_inode_info *ci = ceph_inode(inode);
+
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kmem_cache_free(ceph_inode_cachep, ci);
+}
+
 void ceph_destroy_inode(struct inode *inode)
 {
 	struct ceph_inode_info *ci = ceph_inode(inode);
@@ -407,7 +416,7 @@
 	if (ci->i_xattrs.prealloc_blob)
 		ceph_buffer_put(ci->i_xattrs.prealloc_blob);
 
-	kmem_cache_free(ceph_inode_cachep, ci);
+	call_rcu(&inode->i_rcu, ceph_i_callback);
 }
 
 
@@ -841,13 +850,13 @@
 	di->offset = ceph_inode(inode)->i_max_offset++;
 	spin_unlock(&inode->i_lock);
 
-	spin_lock(&dcache_lock);
-	spin_lock(&dn->d_lock);
+	spin_lock(&dir->d_lock);
+	spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
 	list_move(&dn->d_u.d_child, &dir->d_subdirs);
 	dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
 	     dn->d_u.d_child.prev, dn->d_u.d_child.next);
 	spin_unlock(&dn->d_lock);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dir->d_lock);
 }
 
 /*
@@ -879,8 +888,8 @@
 	} else if (realdn) {
 		dout("dn %p (%d) spliced with %p (%d) "
 		     "inode %p ino %llx.%llx\n",
-		     dn, atomic_read(&dn->d_count),
-		     realdn, atomic_read(&realdn->d_count),
+		     dn, dn->d_count,
+		     realdn, realdn->d_count,
 		     realdn->d_inode, ceph_vinop(realdn->d_inode));
 		dput(dn);
 		dn = realdn;
@@ -1231,11 +1240,11 @@
 			goto retry_lookup;
 		} else {
 			/* reorder parent's d_subdirs */
-			spin_lock(&dcache_lock);
-			spin_lock(&dn->d_lock);
+			spin_lock(&parent->d_lock);
+			spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
 			list_move(&dn->d_u.d_child, &parent->d_subdirs);
 			spin_unlock(&dn->d_lock);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&parent->d_lock);
 		}
 
 		di = dn->d_fsdata;
@@ -1772,12 +1781,17 @@
  * Check inode permissions.  We verify we have a valid value for
  * the AUTH cap, then call the generic handler.
  */
-int ceph_permission(struct inode *inode, int mask)
+int ceph_permission(struct inode *inode, int mask, unsigned int flags)
 {
-	int err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED);
+	int err;
+
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
+	err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED);
 
 	if (!err)
-		err = generic_permission(inode, mask, NULL);
+		err = generic_permission(inode, mask, flags, NULL);
 	return err;
 }
 
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 38800ea..a50fca1 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1486,7 +1486,7 @@
 	*base = ceph_ino(temp->d_inode);
 	*plen = len;
 	dout("build_path on %p %d built %llx '%.*s'\n",
-	     dentry, atomic_read(&dentry->d_count), *base, len, path);
+	     dentry, dentry->d_count, *base, len, path);
 	return path;
 }
 
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 7f01728..4553d88 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -665,7 +665,7 @@
 extern void ceph_queue_writeback(struct inode *inode);
 
 extern int ceph_do_getattr(struct inode *inode, int mask);
-extern int ceph_permission(struct inode *inode, int mask);
+extern int ceph_permission(struct inode *inode, int mask, unsigned int flags);
 extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
 extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
 			struct kstat *stat);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 3936aa7..8e21e0f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -283,10 +283,13 @@
 	return 0;
 }
 
-static int cifs_permission(struct inode *inode, int mask)
+static int cifs_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	struct cifs_sb_info *cifs_sb;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	cifs_sb = CIFS_SB(inode->i_sb);
 
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
@@ -298,7 +301,7 @@
 		on the client (above and beyond ACL on servers) for
 		servers which do not support setting and viewing mode bits,
 		so allowing client to check permissions is useful */
-		return generic_permission(inode, mask, NULL);
+		return generic_permission(inode, mask, flags, NULL);
 }
 
 static struct kmem_cache *cifs_inode_cachep;
@@ -334,10 +337,17 @@
 	return &cifs_inode->vfs_inode;
 }
 
+static void cifs_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(cifs_inode_cachep, CIFS_I(inode));
+}
+
 static void
 cifs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
+	call_rcu(&inode->i_rcu, cifs_i_callback);
 }
 
 static void
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3840edd..db2a58c 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -135,9 +135,9 @@
 			      struct inode *newinode)
 {
 	if (tcon->nocase)
-		direntry->d_op = &cifs_ci_dentry_ops;
+		d_set_d_op(direntry, &cifs_ci_dentry_ops);
 	else
-		direntry->d_op = &cifs_dentry_ops;
+		d_set_d_op(direntry, &cifs_dentry_ops);
 	d_instantiate(direntry, newinode);
 }
 
@@ -421,9 +421,9 @@
 		rc = cifs_get_inode_info_unix(&newinode, full_path,
 						inode->i_sb, xid);
 		if (pTcon->nocase)
-			direntry->d_op = &cifs_ci_dentry_ops;
+			d_set_d_op(direntry, &cifs_ci_dentry_ops);
 		else
-			direntry->d_op = &cifs_dentry_ops;
+			d_set_d_op(direntry, &cifs_dentry_ops);
 
 		if (rc == 0)
 			d_instantiate(direntry, newinode);
@@ -604,9 +604,9 @@
 
 	if ((rc == 0) && (newInode != NULL)) {
 		if (pTcon->nocase)
-			direntry->d_op = &cifs_ci_dentry_ops;
+			d_set_d_op(direntry, &cifs_ci_dentry_ops);
 		else
-			direntry->d_op = &cifs_dentry_ops;
+			d_set_d_op(direntry, &cifs_dentry_ops);
 		d_add(direntry, newInode);
 		if (posix_open) {
 			filp = lookup_instantiate_filp(nd, direntry,
@@ -634,9 +634,9 @@
 		rc = 0;
 		direntry->d_time = jiffies;
 		if (pTcon->nocase)
-			direntry->d_op = &cifs_ci_dentry_ops;
+			d_set_d_op(direntry, &cifs_ci_dentry_ops);
 		else
-			direntry->d_op = &cifs_dentry_ops;
+			d_set_d_op(direntry, &cifs_dentry_ops);
 		d_add(direntry, NULL);
 	/*	if it was once a directory (but how can we tell?) we could do
 		shrink_dcache_parent(direntry); */
@@ -656,22 +656,37 @@
 static int
 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
 {
-	int isValid = 1;
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
 
 	if (direntry->d_inode) {
 		if (cifs_revalidate_dentry(direntry))
 			return 0;
-	} else {
-		cFYI(1, "neg dentry 0x%p name = %s",
-			 direntry, direntry->d_name.name);
-		if (time_after(jiffies, direntry->d_time + HZ) ||
-			!lookupCacheEnabled) {
-			d_drop(direntry);
-			isValid = 0;
-		}
+		else
+			return 1;
 	}
 
-	return isValid;
+	/*
+	 * This may be nfsd (or something), anyway, we can't see the
+	 * intent of this. So, since this can be for creation, drop it.
+	 */
+	if (!nd)
+		return 0;
+
+	/*
+	 * Drop the negative dentry, in order to make sure to use the
+	 * case sensitive name which is specified by user if this is
+	 * for creation.
+	 */
+	if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
+		if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+			return 0;
+	}
+
+	if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
+		return 0;
+
+	return 1;
 }
 
 /* static int cifs_d_delete(struct dentry *direntry)
@@ -688,9 +703,10 @@
 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
 };
 
-static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
+static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *q)
 {
-	struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
+	struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
 	unsigned long hash;
 	int i;
 
@@ -703,21 +719,16 @@
 	return 0;
 }
 
-static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
-			   struct qstr *b)
+static int cifs_ci_compare(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
+	struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
 
-	if ((a->len == b->len) &&
-	    (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
-		/*
-		 * To preserve case, don't let an existing negative dentry's
-		 * case take precedence.  If a is not a negative dentry, this
-		 * should have no side effects
-		 */
-		memcpy((void *)a->name, b->name, a->len);
+	if ((name->len == len) &&
+	    (nls_strnicmp(codepage, name->name, str, len) == 0))
 		return 0;
-	}
 	return 1;
 }
 
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 589f3e3..a853a89 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -809,14 +809,14 @@
 {
 	struct dentry *dentry;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&inode->i_lock);
 	list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
 		if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
-			spin_unlock(&dcache_lock);
+			spin_unlock(&inode->i_lock);
 			return true;
 		}
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 	return false;
 }
 
@@ -1319,9 +1319,9 @@
 	to set uid/gid */
 			inc_nlink(inode);
 			if (pTcon->nocase)
-				direntry->d_op = &cifs_ci_dentry_ops;
+				d_set_d_op(direntry, &cifs_ci_dentry_ops);
 			else
-				direntry->d_op = &cifs_dentry_ops;
+				d_set_d_op(direntry, &cifs_dentry_ops);
 
 			cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
 			cifs_fill_uniqueid(inode->i_sb, &fattr);
@@ -1363,9 +1363,9 @@
 						 inode->i_sb, xid, NULL);
 
 		if (pTcon->nocase)
-			direntry->d_op = &cifs_ci_dentry_ops;
+			d_set_d_op(direntry, &cifs_ci_dentry_ops);
 		else
-			direntry->d_op = &cifs_dentry_ops;
+			d_set_d_op(direntry, &cifs_dentry_ops);
 		d_instantiate(direntry, newinode);
 		 /* setting nlink not necessary except in cases where we
 		  * failed to get it from the server or was set bogus */
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 85cdbf8..fe2f6a9 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -525,9 +525,9 @@
 			      rc);
 		} else {
 			if (pTcon->nocase)
-				direntry->d_op = &cifs_ci_dentry_ops;
+				d_set_d_op(direntry, &cifs_ci_dentry_ops);
 			else
-				direntry->d_op = &cifs_dentry_ops;
+				d_set_d_op(direntry, &cifs_dentry_ops);
 			d_instantiate(direntry, newinode);
 		}
 	}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index a73eb9f..ec5b68e 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -79,7 +79,7 @@
 	cFYI(1, "For %s", name->name);
 
 	if (parent->d_op && parent->d_op->d_hash)
-		parent->d_op->d_hash(parent, name);
+		parent->d_op->d_hash(parent, parent->d_inode, name);
 	else
 		name->hash = full_name_hash(name->name, name->len);
 
@@ -103,9 +103,9 @@
 	}
 
 	if (cifs_sb_master_tcon(CIFS_SB(sb))->nocase)
-		dentry->d_op = &cifs_ci_dentry_ops;
+		d_set_d_op(dentry, &cifs_ci_dentry_ops);
 	else
-		dentry->d_op = &cifs_dentry_ops;
+		d_set_d_op(dentry, &cifs_dentry_ops);
 
 	alias = d_materialise_unique(dentry, inode);
 	if (alias != NULL) {
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 9060f08..5525e1c 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -93,7 +93,7 @@
 	struct list_head *child;
 	struct dentry *de;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 	list_for_each(child, &parent->d_subdirs)
 	{
 		de = list_entry(child, struct dentry, d_u.d_child);
@@ -102,7 +102,7 @@
 			continue;
 		coda_flag_inode(de->d_inode, flag);
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&parent->d_lock);
 	return; 
 }
 
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 5d8b355..29badd9 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/spinlock.h>
+#include <linux/namei.h>
 
 #include <asm/uaccess.h>
 
@@ -47,7 +48,7 @@
 
 /* dentry ops */
 static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
-static int coda_dentry_delete(struct dentry *);
+static int coda_dentry_delete(const struct dentry *);
 
 /* support routines */
 static int coda_venus_readdir(struct file *coda_file, void *buf,
@@ -125,7 +126,7 @@
 		return ERR_PTR(error);
 
 exit:
-	entry->d_op = &coda_dentry_operations;
+	d_set_d_op(entry, &coda_dentry_operations);
 
 	if (inode && (type & CODA_NOCACHE))
 		coda_flag_inode(inode, C_VATTR | C_PURGE);
@@ -134,10 +135,13 @@
 }
 
 
-int coda_permission(struct inode *inode, int mask)
+int coda_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	int error;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
  
 	if (!mask)
@@ -541,9 +545,13 @@
 /* called when a cache lookup succeeds */
 static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
 {
-	struct inode *inode = de->d_inode;
+	struct inode *inode;
 	struct coda_inode_info *cii;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = de->d_inode;
 	if (!inode || coda_isroot(inode))
 		goto out;
 	if (is_bad_inode(inode))
@@ -559,7 +567,7 @@
 	if (cii->c_flags & C_FLUSH) 
 		coda_flag_inode_children(inode, C_FLUSH);
 
-	if (atomic_read(&de->d_count) > 1)
+	if (de->d_count > 1)
 		/* pretend it's valid, but don't change the flags */
 		goto out;
 
@@ -577,7 +585,7 @@
  * This is the callback from dput() when d_count is going to 0.
  * We use this to unhash dentries with bad inodes.
  */
-static int coda_dentry_delete(struct dentry * dentry)
+static int coda_dentry_delete(const struct dentry * dentry)
 {
 	int flags;
 
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 5ea57c8..50dc7d1 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -56,9 +56,16 @@
 	return &ei->vfs_inode;
 }
 
+static void coda_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(coda_inode_cachep, ITOC(inode));
+}
+
 static void coda_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(coda_inode_cachep, ITOC(inode));
+	call_rcu(&inode->i_rcu, coda_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 2fd89b5..741f0bd 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -24,7 +24,7 @@
 #include <linux/coda_psdev.h>
 
 /* pioctl ops */
-static int coda_ioctl_permission(struct inode *inode, int mask);
+static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags);
 static long coda_pioctl(struct file *filp, unsigned int cmd,
 			unsigned long user_data);
 
@@ -41,8 +41,10 @@
 };
 
 /* the coda pioctl inode ops */
-static int coda_ioctl_permission(struct inode *inode, int mask)
+static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags)
 {
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
 	return (mask & MAY_EXEC) ? -EACCES : 0;
 }
 
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index a60579b..61abb63 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -42,7 +42,7 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
 #include <linux/fb.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/netdevice.h>
 #include <linux/raw.h>
 #include <linux/blkdev.h>
@@ -836,6 +836,7 @@
 COMPATIBLE_IOCTL(TCSETSF)
 COMPATIBLE_IOCTL(TIOCLINUX)
 COMPATIBLE_IOCTL(TIOCSBRK)
+COMPATIBLE_IOCTL(TIOCGDEV)
 COMPATIBLE_IOCTL(TIOCCBRK)
 COMPATIBLE_IOCTL(TIOCGSID)
 COMPATIBLE_IOCTL(TIOCGICOUNT)
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index da6061a..026cf68 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -120,7 +120,7 @@
 {
 	struct config_item * item = NULL;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
 	if (!d_unhashed(dentry)) {
 		struct configfs_dirent * sd = dentry->d_fsdata;
 		if (sd->s_type & CONFIGFS_ITEM_LINK) {
@@ -129,7 +129,7 @@
 		} else
 			item = config_item_get(sd->s_element);
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
 
 	return item;
 }
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 0b502f8..36637a8 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -67,7 +67,7 @@
  * We _must_ delete our dentries on last dput, as the chain-to-parent
  * behavior is required to clear the parents of default_groups.
  */
-static int configfs_d_delete(struct dentry *dentry)
+static int configfs_d_delete(const struct dentry *dentry)
 {
 	return 1;
 }
@@ -232,10 +232,8 @@
 
 	sd->s_mode = mode;
 	sd->s_dentry = dentry;
-	if (dentry) {
+	if (dentry)
 		dentry->d_fsdata = configfs_get(sd);
-		dentry->d_op = &configfs_dentry_ops;
-	}
 
 	return 0;
 }
@@ -278,7 +276,6 @@
 		error = configfs_create(d, mode, init_dir);
 		if (!error) {
 			inc_nlink(p->d_inode);
-			(d)->d_op = &configfs_dentry_ops;
 		} else {
 			struct configfs_dirent *sd = d->d_fsdata;
 			if (sd) {
@@ -371,9 +368,7 @@
 				   CONFIGFS_ITEM_LINK);
 	if (!err) {
 		err = configfs_create(dentry, mode, init_symlink);
-		if (!err)
-			dentry->d_op = &configfs_dentry_ops;
-		else {
+		if (err) {
 			struct configfs_dirent *sd = dentry->d_fsdata;
 			if (sd) {
 				spin_lock(&configfs_dirent_lock);
@@ -399,8 +394,7 @@
 	if (d->d_inode)
 		simple_rmdir(parent->d_inode,d);
 
-	pr_debug(" o %s removing done (%d)\n",d->d_name.name,
-		 atomic_read(&d->d_count));
+	pr_debug(" o %s removing done (%d)\n",d->d_name.name, d->d_count);
 
 	dput(parent);
 }
@@ -448,7 +442,7 @@
 		return error;
 	}
 
-	dentry->d_op = &configfs_dentry_ops;
+	d_set_d_op(dentry, &configfs_dentry_ops);
 	d_rehash(dentry);
 
 	return 0;
@@ -493,7 +487,11 @@
 		 * If it doesn't exist and it isn't a NOT_PINNED item,
 		 * it must be negative.
 		 */
-		return simple_lookup(dir, dentry, nd);
+		if (dentry->d_name.len > NAME_MAX)
+			return ERR_PTR(-ENAMETOOLONG);
+		d_set_d_op(dentry, &configfs_dentry_ops);
+		d_add(dentry, NULL);
+		return NULL;
 	}
 
 out:
@@ -685,6 +683,7 @@
 	ret = -ENOMEM;
 	child = d_alloc(parent, &name);
 	if (child) {
+		d_set_d_op(child, &configfs_dentry_ops);
 		d_add(child, NULL);
 
 		ret = configfs_attach_group(&parent_group->cg_item,
@@ -1682,6 +1681,7 @@
 	err = -ENOMEM;
 	dentry = d_alloc(configfs_sb->s_root, &name);
 	if (dentry) {
+		d_set_d_op(dentry, &configfs_dentry_ops);
 		d_add(dentry, NULL);
 
 		err = configfs_attach_group(sd->s_element, &group->cg_item,
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 253476d..c83f476 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -250,18 +250,14 @@
 	struct dentry * dentry = sd->s_dentry;
 
 	if (dentry) {
-		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);
-			spin_unlock(&dcache_lock);
 			simple_unlink(parent->d_inode, dentry);
-		} else {
+		} else
 			spin_unlock(&dentry->d_lock);
-			spin_unlock(&dcache_lock);
-		}
 	}
 }
 
diff --git a/fs/dcache.c b/fs/dcache.c
index 23702a9..5699d4c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -33,20 +33,58 @@
 #include <linux/bootmem.h>
 #include <linux/fs_struct.h>
 #include <linux/hardirq.h>
+#include <linux/bit_spinlock.h>
+#include <linux/rculist_bl.h>
 #include "internal.h"
 
+/*
+ * Usage:
+ * dcache->d_inode->i_lock protects:
+ *   - i_dentry, d_alias, d_inode of aliases
+ * dcache_hash_bucket lock protects:
+ *   - the dcache hash table
+ * s_anon bl list spinlock protects:
+ *   - the s_anon list (see __d_drop)
+ * dcache_lru_lock protects:
+ *   - the dcache lru lists and counters
+ * d_lock protects:
+ *   - d_flags
+ *   - d_name
+ *   - d_lru
+ *   - d_count
+ *   - d_unhashed()
+ *   - d_parent and d_subdirs
+ *   - childrens' d_child and d_parent
+ *   - d_alias, d_inode
+ *
+ * Ordering:
+ * dentry->d_inode->i_lock
+ *   dentry->d_lock
+ *     dcache_lru_lock
+ *     dcache_hash_bucket lock
+ *     s_anon lock
+ *
+ * If there is an ancestor relationship:
+ * dentry->d_parent->...->d_parent->d_lock
+ *   ...
+ *     dentry->d_parent->d_lock
+ *       dentry->d_lock
+ *
+ * If no ancestor relationship:
+ * if (dentry1 < dentry2)
+ *   dentry1->d_lock
+ *     dentry2->d_lock
+ */
 int sysctl_vfs_cache_pressure __read_mostly = 100;
 EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
 
- __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock);
 __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
 
-EXPORT_SYMBOL(dcache_lock);
+EXPORT_SYMBOL(rename_lock);
 
 static struct kmem_cache *dentry_cache __read_mostly;
 
-#define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname))
-
 /*
  * This is the single most critical data structure when it comes
  * to the dcache: the hashtable for lookups. Somebody should try
@@ -60,22 +98,51 @@
 
 static unsigned int d_hash_mask __read_mostly;
 static unsigned int d_hash_shift __read_mostly;
-static struct hlist_head *dentry_hashtable __read_mostly;
+
+struct dcache_hash_bucket {
+	struct hlist_bl_head head;
+};
+static struct dcache_hash_bucket *dentry_hashtable __read_mostly;
+
+static inline struct dcache_hash_bucket *d_hash(struct dentry *parent,
+					unsigned long hash)
+{
+	hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES;
+	hash = hash ^ ((hash ^ GOLDEN_RATIO_PRIME) >> D_HASHBITS);
+	return dentry_hashtable + (hash & D_HASHMASK);
+}
+
+static inline void spin_lock_bucket(struct dcache_hash_bucket *b)
+{
+	bit_spin_lock(0, (unsigned long *)&b->head.first);
+}
+
+static inline void spin_unlock_bucket(struct dcache_hash_bucket *b)
+{
+	__bit_spin_unlock(0, (unsigned long *)&b->head.first);
+}
 
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {
 	.age_limit = 45,
 };
 
-static struct percpu_counter nr_dentry __cacheline_aligned_in_smp;
-static struct percpu_counter nr_dentry_unused __cacheline_aligned_in_smp;
+static DEFINE_PER_CPU(unsigned int, nr_dentry);
 
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
+static int get_nr_dentry(void)
+{
+	int i;
+	int sum = 0;
+	for_each_possible_cpu(i)
+		sum += per_cpu(nr_dentry, i);
+	return sum < 0 ? 0 : sum;
+}
+
 int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
 		   size_t *lenp, loff_t *ppos)
 {
-	dentry_stat.nr_dentry = percpu_counter_sum_positive(&nr_dentry);
-	dentry_stat.nr_unused = percpu_counter_sum_positive(&nr_dentry_unused);
+	dentry_stat.nr_dentry = get_nr_dentry();
 	return proc_dointvec(table, write, buffer, lenp, ppos);
 }
 #endif
@@ -91,35 +158,50 @@
 }
 
 /*
- * no dcache_lock, please.
+ * no locks, please.
  */
 static void d_free(struct dentry *dentry)
 {
-	percpu_counter_dec(&nr_dentry);
+	BUG_ON(dentry->d_count);
+	this_cpu_dec(nr_dentry);
 	if (dentry->d_op && dentry->d_op->d_release)
 		dentry->d_op->d_release(dentry);
 
 	/* if dentry was never inserted into hash, immediate free is OK */
-	if (hlist_unhashed(&dentry->d_hash))
+	if (hlist_bl_unhashed(&dentry->d_hash))
 		__d_free(&dentry->d_u.d_rcu);
 	else
 		call_rcu(&dentry->d_u.d_rcu, __d_free);
 }
 
+/**
+ * dentry_rcuwalk_barrier - invalidate in-progress rcu-walk lookups
+ * After this call, in-progress rcu-walk path lookup will fail. This
+ * should be called after unhashing, and after changing d_inode (if
+ * the dentry has not already been unhashed).
+ */
+static inline void dentry_rcuwalk_barrier(struct dentry *dentry)
+{
+	assert_spin_locked(&dentry->d_lock);
+	/* Go through a barrier */
+	write_seqcount_barrier(&dentry->d_seq);
+}
+
 /*
  * Release the dentry's inode, using the filesystem
- * d_iput() operation if defined.
+ * d_iput() operation if defined. Dentry has no refcount
+ * and is unhashed.
  */
 static void dentry_iput(struct dentry * dentry)
 	__releases(dentry->d_lock)
-	__releases(dcache_lock)
+	__releases(dentry->d_inode->i_lock)
 {
 	struct inode *inode = dentry->d_inode;
 	if (inode) {
 		dentry->d_inode = NULL;
 		list_del_init(&dentry->d_alias);
 		spin_unlock(&dentry->d_lock);
-		spin_unlock(&dcache_lock);
+		spin_unlock(&inode->i_lock);
 		if (!inode->i_nlink)
 			fsnotify_inoderemove(inode);
 		if (dentry->d_op && dentry->d_op->d_iput)
@@ -128,40 +210,72 @@
 			iput(inode);
 	} else {
 		spin_unlock(&dentry->d_lock);
-		spin_unlock(&dcache_lock);
 	}
 }
 
 /*
- * dentry_lru_(add|del|move_tail) must be called with dcache_lock held.
+ * Release the dentry's inode, using the filesystem
+ * d_iput() operation if defined. dentry remains in-use.
+ */
+static void dentry_unlink_inode(struct dentry * dentry)
+	__releases(dentry->d_lock)
+	__releases(dentry->d_inode->i_lock)
+{
+	struct inode *inode = dentry->d_inode;
+	dentry->d_inode = NULL;
+	list_del_init(&dentry->d_alias);
+	dentry_rcuwalk_barrier(dentry);
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&inode->i_lock);
+	if (!inode->i_nlink)
+		fsnotify_inoderemove(inode);
+	if (dentry->d_op && dentry->d_op->d_iput)
+		dentry->d_op->d_iput(dentry, inode);
+	else
+		iput(inode);
+}
+
+/*
+ * dentry_lru_(add|del|move_tail) must be called with d_lock held.
  */
 static void dentry_lru_add(struct dentry *dentry)
 {
 	if (list_empty(&dentry->d_lru)) {
+		spin_lock(&dcache_lru_lock);
 		list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
 		dentry->d_sb->s_nr_dentry_unused++;
-		percpu_counter_inc(&nr_dentry_unused);
+		dentry_stat.nr_unused++;
+		spin_unlock(&dcache_lru_lock);
 	}
 }
 
+static void __dentry_lru_del(struct dentry *dentry)
+{
+	list_del_init(&dentry->d_lru);
+	dentry->d_sb->s_nr_dentry_unused--;
+	dentry_stat.nr_unused--;
+}
+
 static void dentry_lru_del(struct dentry *dentry)
 {
 	if (!list_empty(&dentry->d_lru)) {
-		list_del_init(&dentry->d_lru);
-		dentry->d_sb->s_nr_dentry_unused--;
-		percpu_counter_dec(&nr_dentry_unused);
+		spin_lock(&dcache_lru_lock);
+		__dentry_lru_del(dentry);
+		spin_unlock(&dcache_lru_lock);
 	}
 }
 
 static void dentry_lru_move_tail(struct dentry *dentry)
 {
+	spin_lock(&dcache_lru_lock);
 	if (list_empty(&dentry->d_lru)) {
 		list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
 		dentry->d_sb->s_nr_dentry_unused++;
-		percpu_counter_inc(&nr_dentry_unused);
+		dentry_stat.nr_unused++;
 	} else {
 		list_move_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
 	}
+	spin_unlock(&dcache_lru_lock);
 }
 
 /**
@@ -171,22 +285,115 @@
  * The dentry must already be unhashed and removed from the LRU.
  *
  * If this is the root of the dentry tree, return NULL.
+ *
+ * dentry->d_lock and parent->d_lock must be held by caller, and are dropped by
+ * d_kill.
  */
-static struct dentry *d_kill(struct dentry *dentry)
+static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
 	__releases(dentry->d_lock)
-	__releases(dcache_lock)
+	__releases(parent->d_lock)
+	__releases(dentry->d_inode->i_lock)
 {
+	dentry->d_parent = NULL;
+	list_del(&dentry->d_u.d_child);
+	if (parent)
+		spin_unlock(&parent->d_lock);
+	dentry_iput(dentry);
+	/*
+	 * dentry_iput drops the locks, at which point nobody (except
+	 * transient RCU lookups) can reach this dentry.
+	 */
+	d_free(dentry);
+	return parent;
+}
+
+/**
+ * d_drop - drop a dentry
+ * @dentry: dentry to drop
+ *
+ * d_drop() unhashes the entry from the parent dentry hashes, so that it won't
+ * be found through a VFS lookup any more. Note that this is different from
+ * deleting the dentry - d_delete will try to mark the dentry negative if
+ * possible, giving a successful _negative_ lookup, while d_drop will
+ * just make the cache lookup fail.
+ *
+ * d_drop() is used mainly for stuff that wants to invalidate a dentry for some
+ * reason (NFS timeouts or autofs deletes).
+ *
+ * __d_drop requires dentry->d_lock.
+ */
+void __d_drop(struct dentry *dentry)
+{
+	if (!(dentry->d_flags & DCACHE_UNHASHED)) {
+		if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) {
+			bit_spin_lock(0,
+				(unsigned long *)&dentry->d_sb->s_anon.first);
+			dentry->d_flags |= DCACHE_UNHASHED;
+			hlist_bl_del_init(&dentry->d_hash);
+			__bit_spin_unlock(0,
+				(unsigned long *)&dentry->d_sb->s_anon.first);
+		} else {
+			struct dcache_hash_bucket *b;
+			b = d_hash(dentry->d_parent, dentry->d_name.hash);
+			spin_lock_bucket(b);
+			/*
+			 * We may not actually need to put DCACHE_UNHASHED
+			 * manipulations under the hash lock, but follow
+			 * the principle of least surprise.
+			 */
+			dentry->d_flags |= DCACHE_UNHASHED;
+			hlist_bl_del_rcu(&dentry->d_hash);
+			spin_unlock_bucket(b);
+			dentry_rcuwalk_barrier(dentry);
+		}
+	}
+}
+EXPORT_SYMBOL(__d_drop);
+
+void d_drop(struct dentry *dentry)
+{
+	spin_lock(&dentry->d_lock);
+	__d_drop(dentry);
+	spin_unlock(&dentry->d_lock);
+}
+EXPORT_SYMBOL(d_drop);
+
+/*
+ * Finish off a dentry we've decided to kill.
+ * dentry->d_lock must be held, returns with it unlocked.
+ * If ref is non-zero, then decrement the refcount too.
+ * Returns dentry requiring refcount drop, or NULL if we're done.
+ */
+static inline struct dentry *dentry_kill(struct dentry *dentry, int ref)
+	__releases(dentry->d_lock)
+{
+	struct inode *inode;
 	struct dentry *parent;
 
-	list_del(&dentry->d_u.d_child);
-	/*drops the locks, at that point nobody can reach this dentry */
-	dentry_iput(dentry);
+	inode = dentry->d_inode;
+	if (inode && !spin_trylock(&inode->i_lock)) {
+relock:
+		spin_unlock(&dentry->d_lock);
+		cpu_relax();
+		return dentry; /* try again with same dentry */
+	}
 	if (IS_ROOT(dentry))
 		parent = NULL;
 	else
 		parent = dentry->d_parent;
-	d_free(dentry);
-	return parent;
+	if (parent && !spin_trylock(&parent->d_lock)) {
+		if (inode)
+			spin_unlock(&inode->i_lock);
+		goto relock;
+	}
+
+	if (ref)
+		dentry->d_count--;
+	/* if dentry was on the d_lru list delete it from there */
+	dentry_lru_del(dentry);
+	/* if it was on the hash then remove it */
+	__d_drop(dentry);
+	return d_kill(dentry, parent);
 }
 
 /* 
@@ -214,34 +421,26 @@
  * call the dentry unlink method as well as removing it from the queues and
  * releasing its resources. If the parent dentries were scheduled for release
  * they too may now get deleted.
- *
- * no dcache lock, please.
  */
-
 void dput(struct dentry *dentry)
 {
 	if (!dentry)
 		return;
 
 repeat:
-	if (atomic_read(&dentry->d_count) == 1)
+	if (dentry->d_count == 1)
 		might_sleep();
-	if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
-		return;
-
 	spin_lock(&dentry->d_lock);
-	if (atomic_read(&dentry->d_count)) {
+	BUG_ON(!dentry->d_count);
+	if (dentry->d_count > 1) {
+		dentry->d_count--;
 		spin_unlock(&dentry->d_lock);
-		spin_unlock(&dcache_lock);
 		return;
 	}
 
-	/*
-	 * AV: ->d_delete() is _NOT_ allowed to block now.
-	 */
-	if (dentry->d_op && dentry->d_op->d_delete) {
+	if (dentry->d_flags & DCACHE_OP_DELETE) {
 		if (dentry->d_op->d_delete(dentry))
-			goto unhash_it;
+			goto kill_it;
 	}
 
 	/* Unreachable? Get rid of it */
@@ -252,16 +451,12 @@
 	dentry->d_flags |= DCACHE_REFERENCED;
 	dentry_lru_add(dentry);
 
- 	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
+	dentry->d_count--;
+	spin_unlock(&dentry->d_lock);
 	return;
 
-unhash_it:
-	__d_drop(dentry);
 kill_it:
-	/* if dentry was on the d_lru list delete it from there */
-	dentry_lru_del(dentry);
-	dentry = d_kill(dentry);
+	dentry = dentry_kill(dentry, 1);
 	if (dentry)
 		goto repeat;
 }
@@ -284,9 +479,9 @@
 	/*
 	 * If it's already been dropped, return OK.
 	 */
-	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
 	if (d_unhashed(dentry)) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&dentry->d_lock);
 		return 0;
 	}
 	/*
@@ -294,9 +489,9 @@
 	 * to get rid of unused child entries.
 	 */
 	if (!list_empty(&dentry->d_subdirs)) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&dentry->d_lock);
 		shrink_dcache_parent(dentry);
-		spin_lock(&dcache_lock);
+		spin_lock(&dentry->d_lock);
 	}
 
 	/*
@@ -309,35 +504,61 @@
 	 * we might still populate it if it was a
 	 * working directory or similar).
 	 */
-	spin_lock(&dentry->d_lock);
-	if (atomic_read(&dentry->d_count) > 1) {
+	if (dentry->d_count > 1) {
 		if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
 			spin_unlock(&dentry->d_lock);
-			spin_unlock(&dcache_lock);
 			return -EBUSY;
 		}
 	}
 
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
 	return 0;
 }
 EXPORT_SYMBOL(d_invalidate);
 
-/* This should be called _only_ with dcache_lock held */
-static inline struct dentry * __dget_locked(struct dentry *dentry)
+/* This must be called with d_lock held */
+static inline void __dget_dlock(struct dentry *dentry)
 {
-	atomic_inc(&dentry->d_count);
-	dentry_lru_del(dentry);
-	return dentry;
+	dentry->d_count++;
 }
 
-struct dentry * dget_locked(struct dentry *dentry)
+static inline void __dget(struct dentry *dentry)
 {
-	return __dget_locked(dentry);
+	spin_lock(&dentry->d_lock);
+	__dget_dlock(dentry);
+	spin_unlock(&dentry->d_lock);
 }
-EXPORT_SYMBOL(dget_locked);
+
+struct dentry *dget_parent(struct dentry *dentry)
+{
+	struct dentry *ret;
+
+repeat:
+	/*
+	 * Don't need rcu_dereference because we re-check it was correct under
+	 * the lock.
+	 */
+	rcu_read_lock();
+	ret = dentry->d_parent;
+	if (!ret) {
+		rcu_read_unlock();
+		goto out;
+	}
+	spin_lock(&ret->d_lock);
+	if (unlikely(ret != dentry->d_parent)) {
+		spin_unlock(&ret->d_lock);
+		rcu_read_unlock();
+		goto repeat;
+	}
+	rcu_read_unlock();
+	BUG_ON(!ret->d_count);
+	ret->d_count++;
+	spin_unlock(&ret->d_lock);
+out:
+	return ret;
+}
+EXPORT_SYMBOL(dget_parent);
 
 /**
  * d_find_alias - grab a hashed alias of inode
@@ -355,42 +576,51 @@
  * any other hashed alias over that one unless @want_discon is set,
  * in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias.
  */
-
-static struct dentry * __d_find_alias(struct inode *inode, int want_discon)
+static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
 {
-	struct list_head *head, *next, *tmp;
-	struct dentry *alias, *discon_alias=NULL;
+	struct dentry *alias, *discon_alias;
 
-	head = &inode->i_dentry;
-	next = inode->i_dentry.next;
-	while (next != head) {
-		tmp = next;
-		next = tmp->next;
-		prefetch(next);
-		alias = list_entry(tmp, struct dentry, d_alias);
+again:
+	discon_alias = NULL;
+	list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+		spin_lock(&alias->d_lock);
  		if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
 			if (IS_ROOT(alias) &&
-			    (alias->d_flags & DCACHE_DISCONNECTED))
+			    (alias->d_flags & DCACHE_DISCONNECTED)) {
 				discon_alias = alias;
-			else if (!want_discon) {
-				__dget_locked(alias);
+			} else if (!want_discon) {
+				__dget_dlock(alias);
+				spin_unlock(&alias->d_lock);
 				return alias;
 			}
 		}
+		spin_unlock(&alias->d_lock);
 	}
-	if (discon_alias)
-		__dget_locked(discon_alias);
-	return discon_alias;
+	if (discon_alias) {
+		alias = discon_alias;
+		spin_lock(&alias->d_lock);
+		if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
+			if (IS_ROOT(alias) &&
+			    (alias->d_flags & DCACHE_DISCONNECTED)) {
+				__dget_dlock(alias);
+				spin_unlock(&alias->d_lock);
+				return alias;
+			}
+		}
+		spin_unlock(&alias->d_lock);
+		goto again;
+	}
+	return NULL;
 }
 
-struct dentry * d_find_alias(struct inode *inode)
+struct dentry *d_find_alias(struct inode *inode)
 {
 	struct dentry *de = NULL;
 
 	if (!list_empty(&inode->i_dentry)) {
-		spin_lock(&dcache_lock);
+		spin_lock(&inode->i_lock);
 		de = __d_find_alias(inode, 0);
-		spin_unlock(&dcache_lock);
+		spin_unlock(&inode->i_lock);
 	}
 	return de;
 }
@@ -404,54 +634,61 @@
 {
 	struct dentry *dentry;
 restart:
-	spin_lock(&dcache_lock);
+	spin_lock(&inode->i_lock);
 	list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
 		spin_lock(&dentry->d_lock);
-		if (!atomic_read(&dentry->d_count)) {
-			__dget_locked(dentry);
+		if (!dentry->d_count) {
+			__dget_dlock(dentry);
 			__d_drop(dentry);
 			spin_unlock(&dentry->d_lock);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&inode->i_lock);
 			dput(dentry);
 			goto restart;
 		}
 		spin_unlock(&dentry->d_lock);
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 }
 EXPORT_SYMBOL(d_prune_aliases);
 
 /*
- * Throw away a dentry - free the inode, dput the parent.  This requires that
- * the LRU list has already been removed.
+ * Try to throw away a dentry - free the inode, dput the parent.
+ * Requires dentry->d_lock is held, and dentry->d_count == 0.
+ * Releases dentry->d_lock.
  *
- * Try to prune ancestors as well.  This is necessary to prevent
- * quadratic behavior of shrink_dcache_parent(), but is also expected
- * to be beneficial in reducing dentry cache fragmentation.
+ * This may fail if locks cannot be acquired no problem, just try again.
  */
-static void prune_one_dentry(struct dentry * dentry)
+static void try_prune_one_dentry(struct dentry *dentry)
 	__releases(dentry->d_lock)
-	__releases(dcache_lock)
-	__acquires(dcache_lock)
 {
-	__d_drop(dentry);
-	dentry = d_kill(dentry);
+	struct dentry *parent;
 
+	parent = dentry_kill(dentry, 0);
 	/*
-	 * Prune ancestors.  Locking is simpler than in dput(),
-	 * because dcache_lock needs to be taken anyway.
+	 * If dentry_kill returns NULL, we have nothing more to do.
+	 * if it returns the same dentry, trylocks failed. In either
+	 * case, just loop again.
+	 *
+	 * Otherwise, we need to prune ancestors too. This is necessary
+	 * to prevent quadratic behavior of shrink_dcache_parent(), but
+	 * is also expected to be beneficial in reducing dentry cache
+	 * fragmentation.
 	 */
-	spin_lock(&dcache_lock);
-	while (dentry) {
-		if (!atomic_dec_and_lock(&dentry->d_count, &dentry->d_lock))
-			return;
+	if (!parent)
+		return;
+	if (parent == dentry)
+		return;
 
-		if (dentry->d_op && dentry->d_op->d_delete)
-			dentry->d_op->d_delete(dentry);
-		dentry_lru_del(dentry);
-		__d_drop(dentry);
-		dentry = d_kill(dentry);
-		spin_lock(&dcache_lock);
+	/* Prune ancestors. */
+	dentry = parent;
+	while (dentry) {
+		spin_lock(&dentry->d_lock);
+		if (dentry->d_count > 1) {
+			dentry->d_count--;
+			spin_unlock(&dentry->d_lock);
+			return;
+		}
+		dentry = dentry_kill(dentry, 1);
 	}
 }
 
@@ -459,24 +696,35 @@
 {
 	struct dentry *dentry;
 
-	while (!list_empty(list)) {
-		dentry = list_entry(list->prev, struct dentry, d_lru);
-		dentry_lru_del(dentry);
+	rcu_read_lock();
+	for (;;) {
+		dentry = list_entry_rcu(list->prev, struct dentry, d_lru);
+		if (&dentry->d_lru == list)
+			break; /* empty */
+		spin_lock(&dentry->d_lock);
+		if (dentry != list_entry(list->prev, struct dentry, d_lru)) {
+			spin_unlock(&dentry->d_lock);
+			continue;
+		}
 
 		/*
 		 * We found an inuse dentry which was not removed from
 		 * the LRU because of laziness during lookup.  Do not free
 		 * it - just keep it off the LRU list.
 		 */
-		spin_lock(&dentry->d_lock);
-		if (atomic_read(&dentry->d_count)) {
+		if (dentry->d_count) {
+			dentry_lru_del(dentry);
 			spin_unlock(&dentry->d_lock);
 			continue;
 		}
-		prune_one_dentry(dentry);
-		/* dentry->d_lock was dropped in prune_one_dentry() */
-		cond_resched_lock(&dcache_lock);
+
+		rcu_read_unlock();
+
+		try_prune_one_dentry(dentry);
+
+		rcu_read_lock();
 	}
+	rcu_read_unlock();
 }
 
 /**
@@ -495,42 +743,44 @@
 	LIST_HEAD(tmp);
 	int cnt = *count;
 
-	spin_lock(&dcache_lock);
+relock:
+	spin_lock(&dcache_lru_lock);
 	while (!list_empty(&sb->s_dentry_lru)) {
 		dentry = list_entry(sb->s_dentry_lru.prev,
 				struct dentry, d_lru);
 		BUG_ON(dentry->d_sb != sb);
 
+		if (!spin_trylock(&dentry->d_lock)) {
+			spin_unlock(&dcache_lru_lock);
+			cpu_relax();
+			goto relock;
+		}
+
 		/*
 		 * If we are honouring the DCACHE_REFERENCED flag and the
 		 * dentry has this flag set, don't free it.  Clear the flag
 		 * and put it back on the LRU.
 		 */
-		if (flags & DCACHE_REFERENCED) {
-			spin_lock(&dentry->d_lock);
-			if (dentry->d_flags & DCACHE_REFERENCED) {
-				dentry->d_flags &= ~DCACHE_REFERENCED;
-				list_move(&dentry->d_lru, &referenced);
-				spin_unlock(&dentry->d_lock);
-				cond_resched_lock(&dcache_lock);
-				continue;
-			}
+		if (flags & DCACHE_REFERENCED &&
+				dentry->d_flags & DCACHE_REFERENCED) {
+			dentry->d_flags &= ~DCACHE_REFERENCED;
+			list_move(&dentry->d_lru, &referenced);
 			spin_unlock(&dentry->d_lock);
+		} else {
+			list_move_tail(&dentry->d_lru, &tmp);
+			spin_unlock(&dentry->d_lock);
+			if (!--cnt)
+				break;
 		}
-
-		list_move_tail(&dentry->d_lru, &tmp);
-		if (!--cnt)
-			break;
-		cond_resched_lock(&dcache_lock);
+		cond_resched_lock(&dcache_lru_lock);
 	}
-
-	*count = cnt;
-	shrink_dentry_list(&tmp);
-
 	if (!list_empty(&referenced))
 		list_splice(&referenced, &sb->s_dentry_lru);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dcache_lru_lock);
 
+	shrink_dentry_list(&tmp);
+
+	*count = cnt;
 }
 
 /**
@@ -546,13 +796,12 @@
 {
 	struct super_block *sb, *p = NULL;
 	int w_count;
-	int unused = percpu_counter_sum_positive(&nr_dentry_unused);
+	int unused = dentry_stat.nr_unused;
 	int prune_ratio;
 	int pruned;
 
 	if (unused == 0 || count == 0)
 		return;
-	spin_lock(&dcache_lock);
 	if (count >= unused)
 		prune_ratio = 1;
 	else
@@ -589,11 +838,9 @@
 		if (down_read_trylock(&sb->s_umount)) {
 			if ((sb->s_root != NULL) &&
 			    (!list_empty(&sb->s_dentry_lru))) {
-				spin_unlock(&dcache_lock);
 				__shrink_dcache_sb(sb, &w_count,
 						DCACHE_REFERENCED);
 				pruned -= w_count;
-				spin_lock(&dcache_lock);
 			}
 			up_read(&sb->s_umount);
 		}
@@ -609,7 +856,6 @@
 	if (p)
 		__put_super(p);
 	spin_unlock(&sb_lock);
-	spin_unlock(&dcache_lock);
 }
 
 /**
@@ -623,12 +869,14 @@
 {
 	LIST_HEAD(tmp);
 
-	spin_lock(&dcache_lock);
+	spin_lock(&dcache_lru_lock);
 	while (!list_empty(&sb->s_dentry_lru)) {
 		list_splice_init(&sb->s_dentry_lru, &tmp);
+		spin_unlock(&dcache_lru_lock);
 		shrink_dentry_list(&tmp);
+		spin_lock(&dcache_lru_lock);
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dcache_lru_lock);
 }
 EXPORT_SYMBOL(shrink_dcache_sb);
 
@@ -645,10 +893,10 @@
 	BUG_ON(!IS_ROOT(dentry));
 
 	/* detach this root from the system */
-	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
 	dentry_lru_del(dentry);
 	__d_drop(dentry);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
 
 	for (;;) {
 		/* descend to the first leaf in the current subtree */
@@ -657,14 +905,16 @@
 
 			/* this is a branch with children - detach all of them
 			 * from the system in one go */
-			spin_lock(&dcache_lock);
+			spin_lock(&dentry->d_lock);
 			list_for_each_entry(loop, &dentry->d_subdirs,
 					    d_u.d_child) {
+				spin_lock_nested(&loop->d_lock,
+						DENTRY_D_LOCK_NESTED);
 				dentry_lru_del(loop);
 				__d_drop(loop);
-				cond_resched_lock(&dcache_lock);
+				spin_unlock(&loop->d_lock);
 			}
-			spin_unlock(&dcache_lock);
+			spin_unlock(&dentry->d_lock);
 
 			/* move to the first child */
 			dentry = list_entry(dentry->d_subdirs.next,
@@ -676,7 +926,7 @@
 		do {
 			struct inode *inode;
 
-			if (atomic_read(&dentry->d_count) != 0) {
+			if (dentry->d_count != 0) {
 				printk(KERN_ERR
 				       "BUG: Dentry %p{i=%lx,n=%s}"
 				       " still in use (%d)"
@@ -685,20 +935,23 @@
 				       dentry->d_inode ?
 				       dentry->d_inode->i_ino : 0UL,
 				       dentry->d_name.name,
-				       atomic_read(&dentry->d_count),
+				       dentry->d_count,
 				       dentry->d_sb->s_type->name,
 				       dentry->d_sb->s_id);
 				BUG();
 			}
 
-			if (IS_ROOT(dentry))
+			if (IS_ROOT(dentry)) {
 				parent = NULL;
-			else {
+				list_del(&dentry->d_u.d_child);
+			} else {
 				parent = dentry->d_parent;
-				atomic_dec(&parent->d_count);
+				spin_lock(&parent->d_lock);
+				parent->d_count--;
+				list_del(&dentry->d_u.d_child);
+				spin_unlock(&parent->d_lock);
 			}
 
-			list_del(&dentry->d_u.d_child);
 			detached++;
 
 			inode = dentry->d_inode;
@@ -728,8 +981,7 @@
 
 /*
  * destroy the dentries attached to a superblock on unmounting
- * - we don't need to use dentry->d_lock, and only need dcache_lock when
- *   removing the dentry from the system lists and hashes because:
+ * - we don't need to use dentry->d_lock because:
  *   - the superblock is detached from all mountings and open files, so the
  *     dentry trees will not be rearranged by the VFS
  *   - s_umount is write-locked, so the memory pressure shrinker will ignore
@@ -746,11 +998,13 @@
 
 	dentry = sb->s_root;
 	sb->s_root = NULL;
-	atomic_dec(&dentry->d_count);
+	spin_lock(&dentry->d_lock);
+	dentry->d_count--;
+	spin_unlock(&dentry->d_lock);
 	shrink_dcache_for_umount_subtree(dentry);
 
-	while (!hlist_empty(&sb->s_anon)) {
-		dentry = hlist_entry(sb->s_anon.first, struct dentry, d_hash);
+	while (!hlist_bl_empty(&sb->s_anon)) {
+		dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash);
 		shrink_dcache_for_umount_subtree(dentry);
 	}
 }
@@ -768,15 +1022,20 @@
  * Return true if the parent or its subdirectories contain
  * a mount point
  */
- 
 int have_submounts(struct dentry *parent)
 {
-	struct dentry *this_parent = parent;
+	struct dentry *this_parent;
 	struct list_head *next;
+	unsigned seq;
+	int locked = 0;
 
-	spin_lock(&dcache_lock);
+	seq = read_seqbegin(&rename_lock);
+again:
+	this_parent = parent;
+
 	if (d_mountpoint(parent))
 		goto positive;
+	spin_lock(&this_parent->d_lock);
 repeat:
 	next = this_parent->d_subdirs.next;
 resume:
@@ -784,27 +1043,65 @@
 		struct list_head *tmp = next;
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
 		next = tmp->next;
+
+		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
 		/* Have we found a mount point ? */
-		if (d_mountpoint(dentry))
+		if (d_mountpoint(dentry)) {
+			spin_unlock(&dentry->d_lock);
+			spin_unlock(&this_parent->d_lock);
 			goto positive;
+		}
 		if (!list_empty(&dentry->d_subdirs)) {
+			spin_unlock(&this_parent->d_lock);
+			spin_release(&dentry->d_lock.dep_map, 1, _RET_IP_);
 			this_parent = dentry;
+			spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_);
 			goto repeat;
 		}
+		spin_unlock(&dentry->d_lock);
 	}
 	/*
 	 * All done at this level ... ascend and resume the search.
 	 */
 	if (this_parent != parent) {
-		next = this_parent->d_u.d_child.next;
-		this_parent = this_parent->d_parent;
+		struct dentry *tmp;
+		struct dentry *child;
+
+		tmp = this_parent->d_parent;
+		rcu_read_lock();
+		spin_unlock(&this_parent->d_lock);
+		child = this_parent;
+		this_parent = tmp;
+		spin_lock(&this_parent->d_lock);
+		/* might go back up the wrong parent if we have had a rename
+		 * or deletion */
+		if (this_parent != child->d_parent ||
+			 (!locked && read_seqretry(&rename_lock, seq))) {
+			spin_unlock(&this_parent->d_lock);
+			rcu_read_unlock();
+			goto rename_retry;
+		}
+		rcu_read_unlock();
+		next = child->d_u.d_child.next;
 		goto resume;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&this_parent->d_lock);
+	if (!locked && read_seqretry(&rename_lock, seq))
+		goto rename_retry;
+	if (locked)
+		write_sequnlock(&rename_lock);
 	return 0; /* No mount points found in tree */
 positive:
-	spin_unlock(&dcache_lock);
+	if (!locked && read_seqretry(&rename_lock, seq))
+		goto rename_retry;
+	if (locked)
+		write_sequnlock(&rename_lock);
 	return 1;
+
+rename_retry:
+	locked = 1;
+	write_seqlock(&rename_lock);
+	goto again;
 }
 EXPORT_SYMBOL(have_submounts);
 
@@ -824,11 +1121,16 @@
  */
 static int select_parent(struct dentry * parent)
 {
-	struct dentry *this_parent = parent;
+	struct dentry *this_parent;
 	struct list_head *next;
+	unsigned seq;
 	int found = 0;
+	int locked = 0;
 
-	spin_lock(&dcache_lock);
+	seq = read_seqbegin(&rename_lock);
+again:
+	this_parent = parent;
+	spin_lock(&this_parent->d_lock);
 repeat:
 	next = this_parent->d_subdirs.next;
 resume:
@@ -837,11 +1139,13 @@
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
 		next = tmp->next;
 
+		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
+
 		/* 
 		 * move only zero ref count dentries to the end 
 		 * of the unused list for prune_dcache
 		 */
-		if (!atomic_read(&dentry->d_count)) {
+		if (!dentry->d_count) {
 			dentry_lru_move_tail(dentry);
 			found++;
 		} else {
@@ -853,28 +1157,63 @@
 		 * ensures forward progress). We'll be coming back to find
 		 * the rest.
 		 */
-		if (found && need_resched())
+		if (found && need_resched()) {
+			spin_unlock(&dentry->d_lock);
 			goto out;
+		}
 
 		/*
 		 * Descend a level if the d_subdirs list is non-empty.
 		 */
 		if (!list_empty(&dentry->d_subdirs)) {
+			spin_unlock(&this_parent->d_lock);
+			spin_release(&dentry->d_lock.dep_map, 1, _RET_IP_);
 			this_parent = dentry;
+			spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_);
 			goto repeat;
 		}
+
+		spin_unlock(&dentry->d_lock);
 	}
 	/*
 	 * All done at this level ... ascend and resume the search.
 	 */
 	if (this_parent != parent) {
-		next = this_parent->d_u.d_child.next;
-		this_parent = this_parent->d_parent;
+		struct dentry *tmp;
+		struct dentry *child;
+
+		tmp = this_parent->d_parent;
+		rcu_read_lock();
+		spin_unlock(&this_parent->d_lock);
+		child = this_parent;
+		this_parent = tmp;
+		spin_lock(&this_parent->d_lock);
+		/* might go back up the wrong parent if we have had a rename
+		 * or deletion */
+		if (this_parent != child->d_parent ||
+			(!locked && read_seqretry(&rename_lock, seq))) {
+			spin_unlock(&this_parent->d_lock);
+			rcu_read_unlock();
+			goto rename_retry;
+		}
+		rcu_read_unlock();
+		next = child->d_u.d_child.next;
 		goto resume;
 	}
 out:
-	spin_unlock(&dcache_lock);
+	spin_unlock(&this_parent->d_lock);
+	if (!locked && read_seqretry(&rename_lock, seq))
+		goto rename_retry;
+	if (locked)
+		write_sequnlock(&rename_lock);
 	return found;
+
+rename_retry:
+	if (found)
+		return found;
+	locked = 1;
+	write_seqlock(&rename_lock);
+	goto again;
 }
 
 /**
@@ -908,16 +1247,13 @@
  */
 static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
 {
-	int nr_unused;
-
 	if (nr) {
 		if (!(gfp_mask & __GFP_FS))
 			return -1;
 		prune_dcache(nr);
 	}
 
-	nr_unused = percpu_counter_sum_positive(&nr_dentry_unused);
-	return (nr_unused / 100) * sysctl_vfs_cache_pressure;
+	return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
 
 static struct shrinker dcache_shrinker = {
@@ -960,38 +1296,52 @@
 	memcpy(dname, name->name, name->len);
 	dname[name->len] = 0;
 
-	atomic_set(&dentry->d_count, 1);
+	dentry->d_count = 1;
 	dentry->d_flags = DCACHE_UNHASHED;
 	spin_lock_init(&dentry->d_lock);
+	seqcount_init(&dentry->d_seq);
 	dentry->d_inode = NULL;
 	dentry->d_parent = NULL;
 	dentry->d_sb = NULL;
 	dentry->d_op = NULL;
 	dentry->d_fsdata = NULL;
-	dentry->d_mounted = 0;
-	INIT_HLIST_NODE(&dentry->d_hash);
+	INIT_HLIST_BL_NODE(&dentry->d_hash);
 	INIT_LIST_HEAD(&dentry->d_lru);
 	INIT_LIST_HEAD(&dentry->d_subdirs);
 	INIT_LIST_HEAD(&dentry->d_alias);
+	INIT_LIST_HEAD(&dentry->d_u.d_child);
 
 	if (parent) {
-		dentry->d_parent = dget(parent);
+		spin_lock(&parent->d_lock);
+		/*
+		 * don't need child lock because it is not subject
+		 * to concurrency here
+		 */
+		__dget_dlock(parent);
+		dentry->d_parent = parent;
 		dentry->d_sb = parent->d_sb;
-	} else {
-		INIT_LIST_HEAD(&dentry->d_u.d_child);
+		list_add(&dentry->d_u.d_child, &parent->d_subdirs);
+		spin_unlock(&parent->d_lock);
 	}
 
-	spin_lock(&dcache_lock);
-	if (parent)
-		list_add(&dentry->d_u.d_child, &parent->d_subdirs);
-	spin_unlock(&dcache_lock);
-
-	percpu_counter_inc(&nr_dentry);
+	this_cpu_inc(nr_dentry);
 
 	return dentry;
 }
 EXPORT_SYMBOL(d_alloc);
 
+struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
+{
+	struct dentry *dentry = d_alloc(NULL, name);
+	if (dentry) {
+		dentry->d_sb = sb;
+		dentry->d_parent = dentry;
+		dentry->d_flags |= DCACHE_DISCONNECTED;
+	}
+	return dentry;
+}
+EXPORT_SYMBOL(d_alloc_pseudo);
+
 struct dentry *d_alloc_name(struct dentry *parent, const char *name)
 {
 	struct qstr q;
@@ -1003,12 +1353,36 @@
 }
 EXPORT_SYMBOL(d_alloc_name);
 
-/* the caller must hold dcache_lock */
+void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
+{
+	BUG_ON(dentry->d_op);
+	BUG_ON(dentry->d_flags & (DCACHE_OP_HASH	|
+				DCACHE_OP_COMPARE	|
+				DCACHE_OP_REVALIDATE	|
+				DCACHE_OP_DELETE ));
+	dentry->d_op = op;
+	if (!op)
+		return;
+	if (op->d_hash)
+		dentry->d_flags |= DCACHE_OP_HASH;
+	if (op->d_compare)
+		dentry->d_flags |= DCACHE_OP_COMPARE;
+	if (op->d_revalidate)
+		dentry->d_flags |= DCACHE_OP_REVALIDATE;
+	if (op->d_delete)
+		dentry->d_flags |= DCACHE_OP_DELETE;
+
+}
+EXPORT_SYMBOL(d_set_d_op);
+
 static void __d_instantiate(struct dentry *dentry, struct inode *inode)
 {
+	spin_lock(&dentry->d_lock);
 	if (inode)
 		list_add(&dentry->d_alias, &inode->i_dentry);
 	dentry->d_inode = inode;
+	dentry_rcuwalk_barrier(dentry);
+	spin_unlock(&dentry->d_lock);
 	fsnotify_d_instantiate(dentry, inode);
 }
 
@@ -1030,9 +1404,11 @@
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
 	BUG_ON(!list_empty(&entry->d_alias));
-	spin_lock(&dcache_lock);
+	if (inode)
+		spin_lock(&inode->i_lock);
 	__d_instantiate(entry, inode);
-	spin_unlock(&dcache_lock);
+	if (inode)
+		spin_unlock(&inode->i_lock);
 	security_d_instantiate(entry, inode);
 }
 EXPORT_SYMBOL(d_instantiate);
@@ -1069,15 +1445,18 @@
 	list_for_each_entry(alias, &inode->i_dentry, d_alias) {
 		struct qstr *qstr = &alias->d_name;
 
+		/*
+		 * Don't need alias->d_lock here, because aliases with
+		 * d_parent == entry->d_parent are not subject to name or
+		 * parent changes, because the parent inode i_mutex is held.
+		 */
 		if (qstr->hash != hash)
 			continue;
 		if (alias->d_parent != entry->d_parent)
 			continue;
-		if (qstr->len != len)
+		if (dentry_cmp(qstr->name, qstr->len, name, len))
 			continue;
-		if (memcmp(qstr->name, name, len))
-			continue;
-		dget_locked(alias);
+		__dget(alias);
 		return alias;
 	}
 
@@ -1091,9 +1470,11 @@
 
 	BUG_ON(!list_empty(&entry->d_alias));
 
-	spin_lock(&dcache_lock);
+	if (inode)
+		spin_lock(&inode->i_lock);
 	result = __d_instantiate_unique(entry, inode);
-	spin_unlock(&dcache_lock);
+	if (inode)
+		spin_unlock(&inode->i_lock);
 
 	if (!result) {
 		security_d_instantiate(entry, inode);
@@ -1134,14 +1515,6 @@
 }
 EXPORT_SYMBOL(d_alloc_root);
 
-static inline struct hlist_head *d_hash(struct dentry *parent,
-					unsigned long hash)
-{
-	hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES;
-	hash = hash ^ ((hash ^ GOLDEN_RATIO_PRIME) >> D_HASHBITS);
-	return dentry_hashtable + (hash & D_HASHMASK);
-}
-
 /**
  * d_obtain_alias - find or allocate a dentry for a given inode
  * @inode: inode to allocate the dentry for
@@ -1182,10 +1555,11 @@
 	}
 	tmp->d_parent = tmp; /* make sure dput doesn't croak */
 
-	spin_lock(&dcache_lock);
+
+	spin_lock(&inode->i_lock);
 	res = __d_find_alias(inode, 0);
 	if (res) {
-		spin_unlock(&dcache_lock);
+		spin_unlock(&inode->i_lock);
 		dput(tmp);
 		goto out_iput;
 	}
@@ -1195,12 +1569,14 @@
 	tmp->d_sb = inode->i_sb;
 	tmp->d_inode = inode;
 	tmp->d_flags |= DCACHE_DISCONNECTED;
-	tmp->d_flags &= ~DCACHE_UNHASHED;
 	list_add(&tmp->d_alias, &inode->i_dentry);
-	hlist_add_head(&tmp->d_hash, &inode->i_sb->s_anon);
+	bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
+	tmp->d_flags &= ~DCACHE_UNHASHED;
+	hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
+	__bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
 	spin_unlock(&tmp->d_lock);
+	spin_unlock(&inode->i_lock);
 
-	spin_unlock(&dcache_lock);
 	return tmp;
 
  out_iput:
@@ -1230,18 +1606,18 @@
 	struct dentry *new = NULL;
 
 	if (inode && S_ISDIR(inode->i_mode)) {
-		spin_lock(&dcache_lock);
+		spin_lock(&inode->i_lock);
 		new = __d_find_alias(inode, 1);
 		if (new) {
 			BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
-			spin_unlock(&dcache_lock);
+			spin_unlock(&inode->i_lock);
 			security_d_instantiate(new, inode);
 			d_move(new, dentry);
 			iput(inode);
 		} else {
-			/* already taking dcache_lock, so d_add() by hand */
+			/* already taking inode->i_lock, so d_add() by hand */
 			__d_instantiate(dentry, inode);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&inode->i_lock);
 			security_d_instantiate(dentry, inode);
 			d_rehash(dentry);
 		}
@@ -1314,10 +1690,10 @@
 	 * Negative dentry: instantiate it unless the inode is a directory and
 	 * already has a dentry.
 	 */
-	spin_lock(&dcache_lock);
+	spin_lock(&inode->i_lock);
 	if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) {
 		__d_instantiate(found, inode);
-		spin_unlock(&dcache_lock);
+		spin_unlock(&inode->i_lock);
 		security_d_instantiate(found, inode);
 		return found;
 	}
@@ -1327,8 +1703,8 @@
 	 * reference to it, move it in place and use it.
 	 */
 	new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-	dget_locked(new);
-	spin_unlock(&dcache_lock);
+	__dget(new);
+	spin_unlock(&inode->i_lock);
 	security_d_instantiate(found, inode);
 	d_move(new, found);
 	iput(inode);
@@ -1342,6 +1718,112 @@
 EXPORT_SYMBOL(d_add_ci);
 
 /**
+ * __d_lookup_rcu - search for a dentry (racy, store-free)
+ * @parent: parent dentry
+ * @name: qstr of name we wish to find
+ * @seq: returns d_seq value at the point where the dentry was found
+ * @inode: returns dentry->d_inode when the inode was found valid.
+ * Returns: dentry, or NULL
+ *
+ * __d_lookup_rcu is the dcache lookup function for rcu-walk name
+ * resolution (store-free path walking) design described in
+ * Documentation/filesystems/path-lookup.txt.
+ *
+ * This is not to be used outside core vfs.
+ *
+ * __d_lookup_rcu must only be used in rcu-walk mode, ie. with vfsmount lock
+ * held, and rcu_read_lock held. The returned dentry must not be stored into
+ * without taking d_lock and checking d_seq sequence count against @seq
+ * returned here.
+ *
+ * A refcount may be taken on the found dentry with the __d_rcu_to_refcount
+ * function.
+ *
+ * Alternatively, __d_lookup_rcu may be called again to look up the child of
+ * the returned dentry, so long as its parent's seqlock is checked after the
+ * child is looked up. Thus, an interlocking stepping of sequence lock checks
+ * is formed, giving integrity down the path walk.
+ */
+struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
+				unsigned *seq, struct inode **inode)
+{
+	unsigned int len = name->len;
+	unsigned int hash = name->hash;
+	const unsigned char *str = name->name;
+	struct dcache_hash_bucket *b = d_hash(parent, hash);
+	struct hlist_bl_node *node;
+	struct dentry *dentry;
+
+	/*
+	 * Note: There is significant duplication with __d_lookup_rcu which is
+	 * required to prevent single threaded performance regressions
+	 * especially on architectures where smp_rmb (in seqcounts) are costly.
+	 * Keep the two functions in sync.
+	 */
+
+	/*
+	 * The hash list is protected using RCU.
+	 *
+	 * Carefully use d_seq when comparing a candidate dentry, to avoid
+	 * races with d_move().
+	 *
+	 * It is possible that concurrent renames can mess up our list
+	 * walk here and result in missing our dentry, resulting in the
+	 * false-negative result. d_lookup() protects against concurrent
+	 * renames using rename_lock seqlock.
+	 *
+	 * See Documentation/vfs/dcache-locking.txt for more details.
+	 */
+	hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+		struct inode *i;
+		const char *tname;
+		int tlen;
+
+		if (dentry->d_name.hash != hash)
+			continue;
+
+seqretry:
+		*seq = read_seqcount_begin(&dentry->d_seq);
+		if (dentry->d_parent != parent)
+			continue;
+		if (d_unhashed(dentry))
+			continue;
+		tlen = dentry->d_name.len;
+		tname = dentry->d_name.name;
+		i = dentry->d_inode;
+		prefetch(tname);
+		if (i)
+			prefetch(i);
+		/*
+		 * This seqcount check is required to ensure name and
+		 * len are loaded atomically, so as not to walk off the
+		 * edge of memory when walking. If we could load this
+		 * atomically some other way, we could drop this check.
+		 */
+		if (read_seqcount_retry(&dentry->d_seq, *seq))
+			goto seqretry;
+		if (parent->d_flags & DCACHE_OP_COMPARE) {
+			if (parent->d_op->d_compare(parent, *inode,
+						dentry, i,
+						tlen, tname, name))
+				continue;
+		} else {
+			if (dentry_cmp(tname, tlen, str, len))
+				continue;
+		}
+		/*
+		 * No extra seqcount check is required after the name
+		 * compare. The caller must perform a seqcount check in
+		 * order to do anything useful with the returned dentry
+		 * anyway.
+		 */
+		*inode = i;
+		return dentry;
+	}
+	return NULL;
+}
+
+/**
  * d_lookup - search for a dentry
  * @parent: parent dentry
  * @name: qstr of name we wish to find
@@ -1352,10 +1834,10 @@
  * dentry is returned. The caller must use dput to free the entry when it has
  * finished using it. %NULL is returned if the dentry does not exist.
  */
-struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
+struct dentry *d_lookup(struct dentry *parent, struct qstr *name)
 {
-	struct dentry * dentry = NULL;
-	unsigned long seq;
+	struct dentry *dentry;
+	unsigned seq;
 
         do {
                 seq = read_seqbegin(&rename_lock);
@@ -1367,7 +1849,7 @@
 }
 EXPORT_SYMBOL(d_lookup);
 
-/*
+/**
  * __d_lookup - search for a dentry (racy)
  * @parent: parent dentry
  * @name: qstr of name we wish to find
@@ -1382,17 +1864,24 @@
  *
  * __d_lookup callers must be commented.
  */
-struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
+struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
 {
 	unsigned int len = name->len;
 	unsigned int hash = name->hash;
 	const unsigned char *str = name->name;
-	struct hlist_head *head = d_hash(parent,hash);
+	struct dcache_hash_bucket *b = d_hash(parent, hash);
+	struct hlist_bl_node *node;
 	struct dentry *found = NULL;
-	struct hlist_node *node;
 	struct dentry *dentry;
 
 	/*
+	 * Note: There is significant duplication with __d_lookup_rcu which is
+	 * required to prevent single threaded performance regressions
+	 * especially on architectures where smp_rmb (in seqcounts) are costly.
+	 * Keep the two functions in sync.
+	 */
+
+	/*
 	 * The hash list is protected using RCU.
 	 *
 	 * Take d_lock when comparing a candidate dentry, to avoid races
@@ -1407,25 +1896,16 @@
 	 */
 	rcu_read_lock();
 	
-	hlist_for_each_entry_rcu(dentry, node, head, d_hash) {
-		struct qstr *qstr;
+	hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+		const char *tname;
+		int tlen;
 
 		if (dentry->d_name.hash != hash)
 			continue;
-		if (dentry->d_parent != parent)
-			continue;
 
 		spin_lock(&dentry->d_lock);
-
-		/*
-		 * Recheck the dentry after taking the lock - d_move may have
-		 * changed things. Don't bother checking the hash because
-		 * we're about to compare the whole name anyway.
-		 */
 		if (dentry->d_parent != parent)
 			goto next;
-
-		/* non-existing due to RCU? */
 		if (d_unhashed(dentry))
 			goto next;
 
@@ -1433,18 +1913,19 @@
 		 * It is safe to compare names since d_move() cannot
 		 * change the qstr (protected by d_lock).
 		 */
-		qstr = &dentry->d_name;
-		if (parent->d_op && parent->d_op->d_compare) {
-			if (parent->d_op->d_compare(parent, qstr, name))
+		tlen = dentry->d_name.len;
+		tname = dentry->d_name.name;
+		if (parent->d_flags & DCACHE_OP_COMPARE) {
+			if (parent->d_op->d_compare(parent, parent->d_inode,
+						dentry, dentry->d_inode,
+						tlen, tname, name))
 				goto next;
 		} else {
-			if (qstr->len != len)
-				goto next;
-			if (memcmp(qstr->name, str, len))
+			if (dentry_cmp(tname, tlen, str, len))
 				goto next;
 		}
 
-		atomic_inc(&dentry->d_count);
+		dentry->d_count++;
 		found = dentry;
 		spin_unlock(&dentry->d_lock);
 		break;
@@ -1473,8 +1954,8 @@
 	 * routine may choose to leave the hash value unchanged.
 	 */
 	name->hash = full_name_hash(name->name, name->len);
-	if (dir->d_op && dir->d_op->d_hash) {
-		if (dir->d_op->d_hash(dir, name) < 0)
+	if (dir->d_flags & DCACHE_OP_HASH) {
+		if (dir->d_op->d_hash(dir, dir->d_inode, name) < 0)
 			goto out;
 	}
 	dentry = d_lookup(dir, name);
@@ -1483,34 +1964,32 @@
 }
 
 /**
- * d_validate - verify dentry provided from insecure source
+ * d_validate - verify dentry provided from insecure source (deprecated)
  * @dentry: The dentry alleged to be valid child of @dparent
  * @dparent: The parent dentry (known to be valid)
  *
  * An insecure source has sent us a dentry, here we verify it and dget() it.
  * This is used by ncpfs in its readdir implementation.
  * Zero is returned in the dentry is invalid.
+ *
+ * This function is slow for big directories, and deprecated, do not use it.
  */
-int d_validate(struct dentry *dentry, struct dentry *parent)
+int d_validate(struct dentry *dentry, struct dentry *dparent)
 {
-	struct hlist_head *head = d_hash(parent, dentry->d_name.hash);
-	struct hlist_node *node;
-	struct dentry *d;
+	struct dentry *child;
 
-	/* Check whether the ptr might be valid at all.. */
-	if (!kmem_ptr_validate(dentry_cache, dentry))
-		return 0;
-	if (dentry->d_parent != parent)
-		return 0;
-
-	rcu_read_lock();
-	hlist_for_each_entry_rcu(d, node, head, d_hash) {
-		if (d == dentry) {
-			dget(dentry);
+	spin_lock(&dparent->d_lock);
+	list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) {
+		if (dentry == child) {
+			spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
+			__dget_dlock(dentry);
+			spin_unlock(&dentry->d_lock);
+			spin_unlock(&dparent->d_lock);
 			return 1;
 		}
 	}
-	rcu_read_unlock();
+	spin_unlock(&dparent->d_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(d_validate);
@@ -1538,16 +2017,23 @@
  
 void d_delete(struct dentry * dentry)
 {
+	struct inode *inode;
 	int isdir = 0;
 	/*
 	 * Are we the only user?
 	 */
-	spin_lock(&dcache_lock);
+again:
 	spin_lock(&dentry->d_lock);
-	isdir = S_ISDIR(dentry->d_inode->i_mode);
-	if (atomic_read(&dentry->d_count) == 1) {
+	inode = dentry->d_inode;
+	isdir = S_ISDIR(inode->i_mode);
+	if (dentry->d_count == 1) {
+		if (inode && !spin_trylock(&inode->i_lock)) {
+			spin_unlock(&dentry->d_lock);
+			cpu_relax();
+			goto again;
+		}
 		dentry->d_flags &= ~DCACHE_CANT_MOUNT;
-		dentry_iput(dentry);
+		dentry_unlink_inode(dentry);
 		fsnotify_nameremove(dentry, isdir);
 		return;
 	}
@@ -1556,17 +2042,18 @@
 		__d_drop(dentry);
 
 	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
 
 	fsnotify_nameremove(dentry, isdir);
 }
 EXPORT_SYMBOL(d_delete);
 
-static void __d_rehash(struct dentry * entry, struct hlist_head *list)
+static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b)
 {
-
+	BUG_ON(!d_unhashed(entry));
+	spin_lock_bucket(b);
  	entry->d_flags &= ~DCACHE_UNHASHED;
- 	hlist_add_head_rcu(&entry->d_hash, list);
+	hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
+	spin_unlock_bucket(b);
 }
 
 static void _d_rehash(struct dentry * entry)
@@ -1583,25 +2070,39 @@
  
 void d_rehash(struct dentry * entry)
 {
-	spin_lock(&dcache_lock);
 	spin_lock(&entry->d_lock);
 	_d_rehash(entry);
 	spin_unlock(&entry->d_lock);
-	spin_unlock(&dcache_lock);
 }
 EXPORT_SYMBOL(d_rehash);
 
-/*
- * When switching names, the actual string doesn't strictly have to
- * be preserved in the target - because we're dropping the target
- * anyway. As such, we can just do a simple memcpy() to copy over
- * the new name before we switch.
+/**
+ * dentry_update_name_case - update case insensitive dentry with a new name
+ * @dentry: dentry to be updated
+ * @name: new name
  *
- * Note that we have to be a lot more careful about getting the hash
- * switched - we have to switch the hash value properly even if it
- * then no longer matches the actual (corrupted) string of the target.
- * The hash value has to match the hash queue that the dentry is on..
+ * Update a case insensitive dentry with new case of name.
+ *
+ * dentry must have been returned by d_lookup with name @name. Old and new
+ * name lengths must match (ie. no d_compare which allows mismatched name
+ * lengths).
+ *
+ * Parent inode i_mutex must be held over d_lookup and into this call (to
+ * keep renames and concurrent inserts, and readdir(2) away).
  */
+void dentry_update_name_case(struct dentry *dentry, struct qstr *name)
+{
+	BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+	BUG_ON(dentry->d_name.len != name->len); /* d_lookup gives this */
+
+	spin_lock(&dentry->d_lock);
+	write_seqcount_begin(&dentry->d_seq);
+	memcpy((unsigned char *)dentry->d_name.name, name->name, name->len);
+	write_seqcount_end(&dentry->d_seq);
+	spin_unlock(&dentry->d_lock);
+}
+EXPORT_SYMBOL(dentry_update_name_case);
+
 static void switch_names(struct dentry *dentry, struct dentry *target)
 {
 	if (dname_external(target)) {
@@ -1643,54 +2144,84 @@
 	swap(dentry->d_name.len, target->d_name.len);
 }
 
+static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
+{
+	/*
+	 * XXXX: do we really need to take target->d_lock?
+	 */
+	if (IS_ROOT(dentry) || dentry->d_parent == target->d_parent)
+		spin_lock(&target->d_parent->d_lock);
+	else {
+		if (d_ancestor(dentry->d_parent, target->d_parent)) {
+			spin_lock(&dentry->d_parent->d_lock);
+			spin_lock_nested(&target->d_parent->d_lock,
+						DENTRY_D_LOCK_NESTED);
+		} else {
+			spin_lock(&target->d_parent->d_lock);
+			spin_lock_nested(&dentry->d_parent->d_lock,
+						DENTRY_D_LOCK_NESTED);
+		}
+	}
+	if (target < dentry) {
+		spin_lock_nested(&target->d_lock, 2);
+		spin_lock_nested(&dentry->d_lock, 3);
+	} else {
+		spin_lock_nested(&dentry->d_lock, 2);
+		spin_lock_nested(&target->d_lock, 3);
+	}
+}
+
+static void dentry_unlock_parents_for_move(struct dentry *dentry,
+					struct dentry *target)
+{
+	if (target->d_parent != dentry->d_parent)
+		spin_unlock(&dentry->d_parent->d_lock);
+	if (target->d_parent != target)
+		spin_unlock(&target->d_parent->d_lock);
+}
+
 /*
- * We cannibalize "target" when moving dentry on top of it,
- * because it's going to be thrown away anyway. We could be more
- * polite about it, though.
+ * When switching names, the actual string doesn't strictly have to
+ * be preserved in the target - because we're dropping the target
+ * anyway. As such, we can just do a simple memcpy() to copy over
+ * the new name before we switch.
  *
- * This forceful removal will result in ugly /proc output if
- * somebody holds a file open that got deleted due to a rename.
- * We could be nicer about the deleted file, and let it show
- * up under the name it had before it was deleted rather than
- * under the original name of the file that was moved on top of it.
+ * Note that we have to be a lot more careful about getting the hash
+ * switched - we have to switch the hash value properly even if it
+ * then no longer matches the actual (corrupted) string of the target.
+ * The hash value has to match the hash queue that the dentry is on..
  */
- 
 /*
- * d_move_locked - move a dentry
+ * d_move - move a dentry
  * @dentry: entry to move
  * @target: new dentry
  *
  * Update the dcache to reflect the move of a file name. Negative
  * dcache entries should not be moved in this way.
  */
-static void d_move_locked(struct dentry * dentry, struct dentry * target)
+void d_move(struct dentry * dentry, struct dentry * target)
 {
-	struct hlist_head *list;
-
 	if (!dentry->d_inode)
 		printk(KERN_WARNING "VFS: moving negative dcache entry\n");
 
+	BUG_ON(d_ancestor(dentry, target));
+	BUG_ON(d_ancestor(target, dentry));
+
 	write_seqlock(&rename_lock);
+
+	dentry_lock_for_move(dentry, target);
+
+	write_seqcount_begin(&dentry->d_seq);
+	write_seqcount_begin(&target->d_seq);
+
+	/* __d_drop does write_seqcount_barrier, but they're OK to nest. */
+
 	/*
-	 * XXXX: do we really need to take target->d_lock?
+	 * Move the dentry to the target hash queue. Don't bother checking
+	 * for the same hash queue because of how unlikely it is.
 	 */
-	if (target < dentry) {
-		spin_lock(&target->d_lock);
-		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-	} else {
-		spin_lock(&dentry->d_lock);
-		spin_lock_nested(&target->d_lock, DENTRY_D_LOCK_NESTED);
-	}
-
-	/* Move the dentry to the target hash queue, if on different bucket */
-	if (d_unhashed(dentry))
-		goto already_unhashed;
-
-	hlist_del_rcu(&dentry->d_hash);
-
-already_unhashed:
-	list = d_hash(target->d_parent, target->d_name.hash);
-	__d_rehash(dentry, list);
+	__d_drop(dentry);
+	__d_rehash(dentry, d_hash(target->d_parent, target->d_name.hash));
 
 	/* Unhash the target: dput() will then get rid of it */
 	__d_drop(target);
@@ -1715,27 +2246,16 @@
 	}
 
 	list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
+
+	write_seqcount_end(&target->d_seq);
+	write_seqcount_end(&dentry->d_seq);
+
+	dentry_unlock_parents_for_move(dentry, target);
 	spin_unlock(&target->d_lock);
 	fsnotify_d_move(dentry);
 	spin_unlock(&dentry->d_lock);
 	write_sequnlock(&rename_lock);
 }
-
-/**
- * d_move - move a dentry
- * @dentry: entry to move
- * @target: new dentry
- *
- * Update the dcache to reflect the move of a file name. Negative
- * dcache entries should not be moved in this way.
- */
-
-void d_move(struct dentry * dentry, struct dentry * target)
-{
-	spin_lock(&dcache_lock);
-	d_move_locked(dentry, target);
-	spin_unlock(&dcache_lock);
-}
 EXPORT_SYMBOL(d_move);
 
 /**
@@ -1761,13 +2281,13 @@
  * This helper attempts to cope with remotely renamed directories
  *
  * It assumes that the caller is already holding
- * dentry->d_parent->d_inode->i_mutex and the dcache_lock
+ * dentry->d_parent->d_inode->i_mutex and the inode->i_lock
  *
  * Note: If ever the locking in lock_rename() changes, then please
  * remember to update this too...
  */
-static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias)
-	__releases(dcache_lock)
+static struct dentry *__d_unalias(struct inode *inode,
+		struct dentry *dentry, struct dentry *alias)
 {
 	struct mutex *m1 = NULL, *m2 = NULL;
 	struct dentry *ret;
@@ -1790,10 +2310,10 @@
 		goto out_err;
 	m2 = &alias->d_parent->d_inode->i_mutex;
 out_unalias:
-	d_move_locked(alias, dentry);
+	d_move(alias, dentry);
 	ret = alias;
 out_err:
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 	if (m2)
 		mutex_unlock(m2);
 	if (m1)
@@ -1804,17 +2324,23 @@
 /*
  * Prepare an anonymous dentry for life in the superblock's dentry tree as a
  * named dentry in place of the dentry to be replaced.
+ * returns with anon->d_lock held!
  */
 static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
 {
 	struct dentry *dparent, *aparent;
 
-	switch_names(dentry, anon);
-	swap(dentry->d_name.hash, anon->d_name.hash);
+	dentry_lock_for_move(anon, dentry);
+
+	write_seqcount_begin(&dentry->d_seq);
+	write_seqcount_begin(&anon->d_seq);
 
 	dparent = dentry->d_parent;
 	aparent = anon->d_parent;
 
+	switch_names(dentry, anon);
+	swap(dentry->d_name.hash, anon->d_name.hash);
+
 	dentry->d_parent = (aparent == anon) ? dentry : aparent;
 	list_del(&dentry->d_u.d_child);
 	if (!IS_ROOT(dentry))
@@ -1829,6 +2355,13 @@
 	else
 		INIT_LIST_HEAD(&anon->d_u.d_child);
 
+	write_seqcount_end(&dentry->d_seq);
+	write_seqcount_end(&anon->d_seq);
+
+	dentry_unlock_parents_for_move(anon, dentry);
+	spin_unlock(&dentry->d_lock);
+
+	/* anon->d_lock still locked, returns locked */
 	anon->d_flags &= ~DCACHE_DISCONNECTED;
 }
 
@@ -1846,14 +2379,15 @@
 
 	BUG_ON(!d_unhashed(dentry));
 
-	spin_lock(&dcache_lock);
-
 	if (!inode) {
 		actual = dentry;
 		__d_instantiate(dentry, NULL);
-		goto found_lock;
+		d_rehash(actual);
+		goto out_nolock;
 	}
 
+	spin_lock(&inode->i_lock);
+
 	if (S_ISDIR(inode->i_mode)) {
 		struct dentry *alias;
 
@@ -1864,13 +2398,12 @@
 			/* Is this an anonymous mountpoint that we could splice
 			 * into our tree? */
 			if (IS_ROOT(alias)) {
-				spin_lock(&alias->d_lock);
 				__d_materialise_dentry(dentry, alias);
 				__d_drop(alias);
 				goto found;
 			}
 			/* Nope, but we must(!) avoid directory aliasing */
-			actual = __d_unalias(dentry, alias);
+			actual = __d_unalias(inode, dentry, alias);
 			if (IS_ERR(actual))
 				dput(alias);
 			goto out_nolock;
@@ -1881,15 +2414,14 @@
 	actual = __d_instantiate_unique(dentry, inode);
 	if (!actual)
 		actual = dentry;
-	else if (unlikely(!d_unhashed(actual)))
-		goto shouldnt_be_hashed;
+	else
+		BUG_ON(!d_unhashed(actual));
 
-found_lock:
 	spin_lock(&actual->d_lock);
 found:
 	_d_rehash(actual);
 	spin_unlock(&actual->d_lock);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 out_nolock:
 	if (actual == dentry) {
 		security_d_instantiate(dentry, inode);
@@ -1898,10 +2430,6 @@
 
 	iput(inode);
 	return actual;
-
-shouldnt_be_hashed:
-	spin_unlock(&dcache_lock);
-	BUG();
 }
 EXPORT_SYMBOL_GPL(d_materialise_unique);
 
@@ -1928,7 +2456,7 @@
  * @buffer: pointer to the end of the buffer
  * @buflen: pointer to buffer length
  *
- * Caller holds the dcache_lock.
+ * Caller holds the rename_lock.
  *
  * If path is not reachable from the supplied root, then the value of
  * root is changed (without modifying refcounts).
@@ -1956,7 +2484,9 @@
 		}
 		parent = dentry->d_parent;
 		prefetch(parent);
+		spin_lock(&dentry->d_lock);
 		error = prepend_name(buffer, buflen, &dentry->d_name);
+		spin_unlock(&dentry->d_lock);
 		if (!error)
 			error = prepend(buffer, buflen, "/", 1);
 		if (error)
@@ -2012,9 +2542,9 @@
 	int error;
 
 	prepend(&res, &buflen, "\0", 1);
-	spin_lock(&dcache_lock);
+	write_seqlock(&rename_lock);
 	error = prepend_path(path, root, &res, &buflen);
-	spin_unlock(&dcache_lock);
+	write_sequnlock(&rename_lock);
 
 	if (error)
 		return ERR_PTR(error);
@@ -2076,12 +2606,12 @@
 		return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 
 	get_fs_root(current->fs, &root);
-	spin_lock(&dcache_lock);
+	write_seqlock(&rename_lock);
 	tmp = root;
 	error = path_with_deleted(path, &tmp, &res, &buflen);
 	if (error)
 		res = ERR_PTR(error);
-	spin_unlock(&dcache_lock);
+	write_sequnlock(&rename_lock);
 	path_put(&root);
 	return res;
 }
@@ -2107,12 +2637,12 @@
 		return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 
 	get_fs_root(current->fs, &root);
-	spin_lock(&dcache_lock);
+	write_seqlock(&rename_lock);
 	tmp = root;
 	error = path_with_deleted(path, &tmp, &res, &buflen);
 	if (!error && !path_equal(&tmp, &root))
 		error = prepend_unreachable(&res, &buflen);
-	spin_unlock(&dcache_lock);
+	write_sequnlock(&rename_lock);
 	path_put(&root);
 	if (error)
 		res =  ERR_PTR(error);
@@ -2144,7 +2674,7 @@
 /*
  * Write full pathname from the root of the filesystem into the buffer.
  */
-char *__dentry_path(struct dentry *dentry, char *buf, int buflen)
+static char *__dentry_path(struct dentry *dentry, char *buf, int buflen)
 {
 	char *end = buf + buflen;
 	char *retval;
@@ -2158,10 +2688,13 @@
 
 	while (!IS_ROOT(dentry)) {
 		struct dentry *parent = dentry->d_parent;
+		int error;
 
 		prefetch(parent);
-		if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
-		    (prepend(&end, &buflen, "/", 1) != 0))
+		spin_lock(&dentry->d_lock);
+		error = prepend_name(&end, &buflen, &dentry->d_name);
+		spin_unlock(&dentry->d_lock);
+		if (error != 0 || prepend(&end, &buflen, "/", 1) != 0)
 			goto Elong;
 
 		retval = end;
@@ -2171,14 +2704,25 @@
 Elong:
 	return ERR_PTR(-ENAMETOOLONG);
 }
-EXPORT_SYMBOL(__dentry_path);
+
+char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen)
+{
+	char *retval;
+
+	write_seqlock(&rename_lock);
+	retval = __dentry_path(dentry, buf, buflen);
+	write_sequnlock(&rename_lock);
+
+	return retval;
+}
+EXPORT_SYMBOL(dentry_path_raw);
 
 char *dentry_path(struct dentry *dentry, char *buf, int buflen)
 {
 	char *p = NULL;
 	char *retval;
 
-	spin_lock(&dcache_lock);
+	write_seqlock(&rename_lock);
 	if (d_unlinked(dentry)) {
 		p = buf + buflen;
 		if (prepend(&p, &buflen, "//deleted", 10) != 0)
@@ -2186,12 +2730,11 @@
 		buflen++;
 	}
 	retval = __dentry_path(dentry, buf, buflen);
-	spin_unlock(&dcache_lock);
+	write_sequnlock(&rename_lock);
 	if (!IS_ERR(retval) && p)
 		*p = '/';	/* restore '/' overriden with '\0' */
 	return retval;
 Elong:
-	spin_unlock(&dcache_lock);
 	return ERR_PTR(-ENAMETOOLONG);
 }
 
@@ -2225,7 +2768,7 @@
 	get_fs_root_and_pwd(current->fs, &root, &pwd);
 
 	error = -ENOENT;
-	spin_lock(&dcache_lock);
+	write_seqlock(&rename_lock);
 	if (!d_unlinked(pwd.dentry)) {
 		unsigned long len;
 		struct path tmp = root;
@@ -2234,7 +2777,7 @@
 
 		prepend(&cwd, &buflen, "\0", 1);
 		error = prepend_path(&pwd, &tmp, &cwd, &buflen);
-		spin_unlock(&dcache_lock);
+		write_sequnlock(&rename_lock);
 
 		if (error)
 			goto out;
@@ -2253,8 +2796,9 @@
 			if (copy_to_user(buf, cwd, len))
 				error = -EFAULT;
 		}
-	} else
-		spin_unlock(&dcache_lock);
+	} else {
+		write_sequnlock(&rename_lock);
+	}
 
 out:
 	path_put(&pwd);
@@ -2282,25 +2826,25 @@
 int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
 {
 	int result;
-	unsigned long seq;
+	unsigned seq;
 
 	if (new_dentry == old_dentry)
 		return 1;
 
-	/*
-	 * Need rcu_readlock to protect against the d_parent trashing
-	 * due to d_move
-	 */
-	rcu_read_lock();
 	do {
 		/* for restarting inner loop in case of seq retry */
 		seq = read_seqbegin(&rename_lock);
+		/*
+		 * Need rcu_readlock to protect against the d_parent trashing
+		 * due to d_move
+		 */
+		rcu_read_lock();
 		if (d_ancestor(old_dentry, new_dentry))
 			result = 1;
 		else
 			result = 0;
+		rcu_read_unlock();
 	} while (read_seqretry(&rename_lock, seq));
-	rcu_read_unlock();
 
 	return result;
 }
@@ -2332,10 +2876,15 @@
 
 void d_genocide(struct dentry *root)
 {
-	struct dentry *this_parent = root;
+	struct dentry *this_parent;
 	struct list_head *next;
+	unsigned seq;
+	int locked = 0;
 
-	spin_lock(&dcache_lock);
+	seq = read_seqbegin(&rename_lock);
+again:
+	this_parent = root;
+	spin_lock(&this_parent->d_lock);
 repeat:
 	next = this_parent->d_subdirs.next;
 resume:
@@ -2343,21 +2892,62 @@
 		struct list_head *tmp = next;
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
 		next = tmp->next;
-		if (d_unhashed(dentry)||!dentry->d_inode)
+
+		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
+		if (d_unhashed(dentry) || !dentry->d_inode) {
+			spin_unlock(&dentry->d_lock);
 			continue;
+		}
 		if (!list_empty(&dentry->d_subdirs)) {
+			spin_unlock(&this_parent->d_lock);
+			spin_release(&dentry->d_lock.dep_map, 1, _RET_IP_);
 			this_parent = dentry;
+			spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_);
 			goto repeat;
 		}
-		atomic_dec(&dentry->d_count);
+		if (!(dentry->d_flags & DCACHE_GENOCIDE)) {
+			dentry->d_flags |= DCACHE_GENOCIDE;
+			dentry->d_count--;
+		}
+		spin_unlock(&dentry->d_lock);
 	}
 	if (this_parent != root) {
-		next = this_parent->d_u.d_child.next;
-		atomic_dec(&this_parent->d_count);
-		this_parent = this_parent->d_parent;
+		struct dentry *tmp;
+		struct dentry *child;
+
+		tmp = this_parent->d_parent;
+		if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
+			this_parent->d_flags |= DCACHE_GENOCIDE;
+			this_parent->d_count--;
+		}
+		rcu_read_lock();
+		spin_unlock(&this_parent->d_lock);
+		child = this_parent;
+		this_parent = tmp;
+		spin_lock(&this_parent->d_lock);
+		/* might go back up the wrong parent if we have had a rename
+		 * or deletion */
+		if (this_parent != child->d_parent ||
+			 (!locked && read_seqretry(&rename_lock, seq))) {
+			spin_unlock(&this_parent->d_lock);
+			rcu_read_unlock();
+			goto rename_retry;
+		}
+		rcu_read_unlock();
+		next = child->d_u.d_child.next;
 		goto resume;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&this_parent->d_lock);
+	if (!locked && read_seqretry(&rename_lock, seq))
+		goto rename_retry;
+	if (locked)
+		write_sequnlock(&rename_lock);
+	return;
+
+rename_retry:
+	locked = 1;
+	write_seqlock(&rename_lock);
+	goto again;
 }
 
 /**
@@ -2411,7 +3001,7 @@
 
 	dentry_hashtable =
 		alloc_large_system_hash("Dentry cache",
-					sizeof(struct hlist_head),
+					sizeof(struct dcache_hash_bucket),
 					dhash_entries,
 					13,
 					HASH_EARLY,
@@ -2420,16 +3010,13 @@
 					0);
 
 	for (loop = 0; loop < (1 << d_hash_shift); loop++)
-		INIT_HLIST_HEAD(&dentry_hashtable[loop]);
+		INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
 }
 
 static void __init dcache_init(void)
 {
 	int loop;
 
-	percpu_counter_init(&nr_dentry, 0);
-	percpu_counter_init(&nr_dentry_unused, 0);
-
 	/* 
 	 * A constructor could be added for stable state like the lists,
 	 * but it is probably not worth it because of the cache nature
@@ -2446,7 +3033,7 @@
 
 	dentry_hashtable =
 		alloc_large_system_hash("Dentry cache",
-					sizeof(struct hlist_head),
+					sizeof(struct dcache_hash_bucket),
 					dhash_entries,
 					13,
 					0,
@@ -2455,7 +3042,7 @@
 					0);
 
 	for (loop = 0; loop < (1 << d_hash_shift); loop++)
-		INIT_HLIST_HEAD(&dentry_hashtable[loop]);
+		INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
 }
 
 /* SLAB cache for __getname() consumers */
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index 906e803..6fc4f31 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -44,12 +44,17 @@
  */
 static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-	struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+	struct dentry *lower_dentry;
+	struct vfsmount *lower_mnt;
 	struct dentry *dentry_save;
 	struct vfsmount *vfsmount_save;
 	int rc = 1;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
 		goto out;
 	dentry_save = nd->path.dentry;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 9d1a22d..337352a 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -260,7 +260,7 @@
 				   ecryptfs_dentry->d_parent));
 	lower_inode = lower_dentry->d_inode;
 	fsstack_copy_attr_atime(ecryptfs_dir_inode, lower_dir_dentry->d_inode);
-	BUG_ON(!atomic_read(&lower_dentry->d_count));
+	BUG_ON(!lower_dentry->d_count);
 	ecryptfs_set_dentry_private(ecryptfs_dentry,
 				    kmem_cache_alloc(ecryptfs_dentry_info_cache,
 						     GFP_KERNEL));
@@ -441,7 +441,7 @@
 	struct qstr lower_name;
 	int rc = 0;
 
-	ecryptfs_dentry->d_op = &ecryptfs_dops;
+	d_set_d_op(ecryptfs_dentry, &ecryptfs_dops);
 	if ((ecryptfs_dentry->d_name.len == 1
 	     && !strcmp(ecryptfs_dentry->d_name.name, "."))
 	    || (ecryptfs_dentry->d_name.len == 2
@@ -454,7 +454,7 @@
 	lower_name.hash = ecryptfs_dentry->d_name.hash;
 	if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) {
 		rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry,
-						    &lower_name);
+				lower_dir_dentry->d_inode, &lower_name);
 		if (rc < 0)
 			goto out_d_drop;
 	}
@@ -489,7 +489,7 @@
 	lower_name.hash = full_name_hash(lower_name.name, lower_name.len);
 	if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) {
 		rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry,
-						    &lower_name);
+				lower_dir_dentry->d_inode, &lower_name);
 		if (rc < 0)
 			goto out_d_drop;
 	}
@@ -980,8 +980,10 @@
 }
 
 static int
-ecryptfs_permission(struct inode *inode, int mask)
+ecryptfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
 	return inode_permission(ecryptfs_inode_to_lower(inode), mask);
 }
 
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index a9dbd62..3510386 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -189,7 +189,7 @@
 	if (special_file(lower_inode->i_mode))
 		init_special_inode(inode, lower_inode->i_mode,
 				   lower_inode->i_rdev);
-	dentry->d_op = &ecryptfs_dops;
+	d_set_d_op(dentry, &ecryptfs_dops);
 	fsstack_copy_attr_all(inode, lower_inode);
 	/* This size will be overwritten for real files w/ headers and
 	 * other metadata */
@@ -594,7 +594,7 @@
 		deactivate_locked_super(s);
 		goto out;
 	}
-	s->s_root->d_op = &ecryptfs_dops;
+	d_set_d_op(s->s_root, &ecryptfs_dops);
 	s->s_root->d_sb = s;
 	s->s_root->d_parent = s->s_root;
 
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index 2720178..3042fe1 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -62,6 +62,16 @@
 	return inode;
 }
 
+static void ecryptfs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	struct ecryptfs_inode_info *inode_info;
+	inode_info = ecryptfs_inode_to_private(inode);
+
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kmem_cache_free(ecryptfs_inode_info_cache, inode_info);
+}
+
 /**
  * ecryptfs_destroy_inode
  * @inode: The ecryptfs inode
@@ -88,7 +98,7 @@
 		}
 	}
 	ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
-	kmem_cache_free(ecryptfs_inode_info_cache, inode_info);
+	call_rcu(&inode->i_rcu, ecryptfs_i_callback);
 }
 
 /**
diff --git a/fs/efs/super.c b/fs/efs/super.c
index 5073a07..0f31acb 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -65,9 +65,16 @@
 	return &ei->vfs_inode;
 }
 
+static void efs_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(efs_inode_cachep, INODE_INFO(inode));
+}
+
 static void efs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
+	call_rcu(&inode->i_rcu, efs_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index 79c3ae6..8c6c466 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -150,12 +150,19 @@
 	return &oi->vfs_inode;
 }
 
+static void exofs_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(exofs_inode_cachep, exofs_i(inode));
+}
+
 /*
  * Remove an inode from the cache
  */
 static void exofs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(exofs_inode_cachep, exofs_i(inode));
+	call_rcu(&inode->i_rcu, exofs_i_callback);
 }
 
 /*
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 51b3040..4b68257 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -43,24 +43,26 @@
 		void *context)
 {
 	struct dentry *dentry, *toput = NULL;
+	struct inode *inode;
 
 	if (acceptable(context, result))
 		return result;
 
-	spin_lock(&dcache_lock);
-	list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
-		dget_locked(dentry);
-		spin_unlock(&dcache_lock);
+	inode = result->d_inode;
+	spin_lock(&inode->i_lock);
+	list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+		dget(dentry);
+		spin_unlock(&inode->i_lock);
 		if (toput)
 			dput(toput);
 		if (dentry != result && acceptable(context, dentry)) {
 			dput(result);
 			return dentry;
 		}
-		spin_lock(&dcache_lock);
+		spin_lock(&inode->i_lock);
 		toput = dentry;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 
 	if (toput)
 		dput(toput);
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 2bcc043..7b41805 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -232,10 +232,17 @@
 }
 
 int
-ext2_check_acl(struct inode *inode, int mask)
+ext2_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct posix_acl *acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
+	struct posix_acl *acl;
 
+	if (flags & IPERM_FLAG_RCU) {
+		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
+			return -ECHILD;
+		return -EAGAIN;
+	}
+
+	acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl) {
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index 3ff6cbb..c939b7b 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -54,7 +54,7 @@
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 
 /* acl.c */
-extern int ext2_check_acl (struct inode *, int);
+extern int ext2_check_acl (struct inode *, int, unsigned int);
 extern int ext2_acl_chmod (struct inode *);
 extern int ext2_init_acl (struct inode *, struct inode *);
 
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index d89e0b6..e0c6380 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -161,9 +161,16 @@
 	return &ei->vfs_inode;
 }
 
+static void ext2_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(ext2_inode_cachep, EXT2_I(inode));
+}
+
 static void ext2_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(ext2_inode_cachep, EXT2_I(inode));
+	call_rcu(&inode->i_rcu, ext2_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 8a11fe2..e4fa49e 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -240,10 +240,17 @@
 }
 
 int
-ext3_check_acl(struct inode *inode, int mask)
+ext3_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct posix_acl *acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
+	struct posix_acl *acl;
 
+	if (flags & IPERM_FLAG_RCU) {
+		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
+			return -ECHILD;
+		return -EAGAIN;
+	}
+
+	acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl) {
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 5973346..5faf8048 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -54,7 +54,7 @@
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 
 /* acl.c */
-extern int ext3_check_acl (struct inode *, int);
+extern int ext3_check_acl (struct inode *, int, unsigned int);
 extern int ext3_acl_chmod (struct inode *);
 extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
 
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index acf8695..77ce161 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -479,6 +479,13 @@
 	return &ei->vfs_inode;
 }
 
+static void ext3_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(ext3_inode_cachep, EXT3_I(inode));
+}
+
 static void ext3_destroy_inode(struct inode *inode)
 {
 	if (!list_empty(&(EXT3_I(inode)->i_orphan))) {
@@ -489,7 +496,7 @@
 				false);
 		dump_stack();
 	}
-	kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
+	call_rcu(&inode->i_rcu, ext3_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 5e2ed45..e0270d1 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -238,10 +238,17 @@
 }
 
 int
-ext4_check_acl(struct inode *inode, int mask)
+ext4_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct posix_acl *acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
+	struct posix_acl *acl;
 
+	if (flags & IPERM_FLAG_RCU) {
+		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
+			return -ECHILD;
+		return -EAGAIN;
+	}
+
+	acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl) {
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
index 9d843d5..dec8211 100644
--- a/fs/ext4/acl.h
+++ b/fs/ext4/acl.h
@@ -54,7 +54,7 @@
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
 
 /* acl.c */
-extern int ext4_check_acl(struct inode *, int);
+extern int ext4_check_acl(struct inode *, int, unsigned int);
 extern int ext4_acl_chmod(struct inode *);
 extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index fb15c9c..cd37f9d 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -841,6 +841,13 @@
 	return drop;
 }
 
+static void ext4_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(ext4_inode_cachep, EXT4_I(inode));
+}
+
 static void ext4_destroy_inode(struct inode *inode)
 {
 	ext4_ioend_wait(inode);
@@ -853,7 +860,7 @@
 				true);
 		dump_stack();
 	}
-	kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
+	call_rcu(&inode->i_rcu, ext4_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index ad6998a..206351a 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -514,9 +514,16 @@
 	return &ei->vfs_inode;
 }
 
+static void fat_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(fat_inode_cachep, MSDOS_I(inode));
+}
+
 static void fat_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
+	call_rcu(&inode->i_rcu, fat_i_callback);
 }
 
 static void init_once(void *foo)
@@ -743,7 +750,7 @@
 	 */
 	result = d_obtain_alias(inode);
 	if (!IS_ERR(result))
-		result->d_op = sb->s_root->d_op;
+		d_set_d_op(result, sb->s_root->d_op);
 	return result;
 }
 
@@ -793,7 +800,7 @@
 
 	parent = d_obtain_alias(inode);
 	if (!IS_ERR(parent))
-		parent->d_op = sb->s_root->d_op;
+		d_set_d_op(parent, sb->s_root->d_op);
 out:
 	unlock_super(sb);
 
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 3345aab..35ffe43 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -148,7 +148,8 @@
  * that the existing dentry can be used. The msdos fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
+static int msdos_hash(const struct dentry *dentry, const struct inode *inode,
+	       struct qstr *qstr)
 {
 	struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
 	unsigned char msdos_name[MSDOS_NAME];
@@ -164,16 +165,18 @@
  * Compare two msdos names. If either of the names are invalid,
  * we fall back to doing the standard name comparison.
  */
-static int msdos_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int msdos_cmp(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
+	struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
 	unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
 	int error;
 
-	error = msdos_format_name(a->name, a->len, a_msdos_name, options);
+	error = msdos_format_name(name->name, name->len, a_msdos_name, options);
 	if (error)
 		goto old_compare;
-	error = msdos_format_name(b->name, b->len, b_msdos_name, options);
+	error = msdos_format_name(str, len, b_msdos_name, options);
 	if (error)
 		goto old_compare;
 	error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
@@ -182,8 +185,8 @@
 
 old_compare:
 	error = 1;
-	if (a->len == b->len)
-		error = memcmp(a->name, b->name, a->len);
+	if (name->len == len)
+		error = memcmp(name->name, str, len);
 	goto out;
 }
 
@@ -224,10 +227,10 @@
 	}
 out:
 	unlock_super(sb);
-	dentry->d_op = &msdos_dentry_operations;
+	d_set_d_op(dentry, &msdos_dentry_operations);
 	dentry = d_splice_alias(inode, dentry);
 	if (dentry)
-		dentry->d_op = &msdos_dentry_operations;
+		d_set_d_op(dentry, &msdos_dentry_operations);
 	return dentry;
 
 error:
@@ -670,7 +673,7 @@
 	}
 
 	sb->s_flags |= MS_NOATIME;
-	sb->s_root->d_op = &msdos_dentry_operations;
+	d_set_d_op(sb->s_root, &msdos_dentry_operations);
 	unlock_super(sb);
 	return 0;
 }
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index b936703..e3ffc5e 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -43,6 +43,9 @@
 
 static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
 	/* This is not negative dentry. Always valid. */
 	if (dentry->d_inode)
 		return 1;
@@ -51,6 +54,9 @@
 
 static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
 {
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
 	/*
 	 * This is not negative dentry. Always valid.
 	 *
@@ -85,22 +91,26 @@
 }
 
 /* returns the length of a struct qstr, ignoring trailing dots */
-static unsigned int vfat_striptail_len(struct qstr *qstr)
+static unsigned int __vfat_striptail_len(unsigned int len, const char *name)
 {
-	unsigned int len = qstr->len;
-
-	while (len && qstr->name[len - 1] == '.')
+	while (len && name[len - 1] == '.')
 		len--;
 	return len;
 }
 
+static unsigned int vfat_striptail_len(const struct qstr *qstr)
+{
+	return __vfat_striptail_len(qstr->len, qstr->name);
+}
+
 /*
  * Compute the hash for the vfat name corresponding to the dentry.
  * Note: if the name is invalid, we leave the hash code unchanged so
  * that the existing dentry can be used. The vfat fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
+static int vfat_hash(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
 	qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr));
 	return 0;
@@ -112,9 +122,10 @@
  * that the existing dentry can be used. The vfat fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
+static int vfat_hashi(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
-	struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
+	struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
 	const unsigned char *name;
 	unsigned int len;
 	unsigned long hash;
@@ -133,16 +144,18 @@
 /*
  * Case insensitive compare of two vfat names.
  */
-static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int vfat_cmpi(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
+	struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
 	unsigned int alen, blen;
 
 	/* A filename cannot end in '.' or we treat it like it has none */
-	alen = vfat_striptail_len(a);
-	blen = vfat_striptail_len(b);
+	alen = vfat_striptail_len(name);
+	blen = __vfat_striptail_len(len, str);
 	if (alen == blen) {
-		if (nls_strnicmp(t, a->name, b->name, alen) == 0)
+		if (nls_strnicmp(t, name->name, str, alen) == 0)
 			return 0;
 	}
 	return 1;
@@ -151,15 +164,17 @@
 /*
  * Case sensitive compare of two vfat names.
  */
-static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int vfat_cmp(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
 	unsigned int alen, blen;
 
 	/* A filename cannot end in '.' or we treat it like it has none */
-	alen = vfat_striptail_len(a);
-	blen = vfat_striptail_len(b);
+	alen = vfat_striptail_len(name);
+	blen = __vfat_striptail_len(len, str);
 	if (alen == blen) {
-		if (strncmp(a->name, b->name, alen) == 0)
+		if (strncmp(name->name, str, alen) == 0)
 			return 0;
 	}
 	return 1;
@@ -757,11 +772,11 @@
 
 out:
 	unlock_super(sb);
-	dentry->d_op = sb->s_root->d_op;
+	d_set_d_op(dentry, sb->s_root->d_op);
 	dentry->d_time = dentry->d_parent->d_inode->i_version;
 	dentry = d_splice_alias(inode, dentry);
 	if (dentry) {
-		dentry->d_op = sb->s_root->d_op;
+		d_set_d_op(dentry, sb->s_root->d_op);
 		dentry->d_time = dentry->d_parent->d_inode->i_version;
 	}
 	return dentry;
@@ -1063,9 +1078,9 @@
 	}
 
 	if (MSDOS_SB(sb)->options.name_check != 's')
-		sb->s_root->d_op = &vfat_ci_dentry_ops;
+		d_set_d_op(sb->s_root, &vfat_ci_dentry_ops);
 	else
-		sb->s_root->d_op = &vfat_dentry_ops;
+		d_set_d_op(sb->s_root, &vfat_dentry_ops);
 
 	unlock_super(sb);
 	return 0;
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 68ba492..751d6b2 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -115,6 +115,9 @@
 		tmp = &(*tmp)->next;
 	}
 	write_unlock(&file_systems_lock);
+
+	synchronize_rcu();
+
 	return -EINVAL;
 }
 
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 8c04eac..2ba6719 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -337,6 +337,13 @@
 	return ip;
 }
 
+static void vxfs_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(vxfs_inode_cachep, inode->i_private);
+}
+
 /**
  * vxfs_evict_inode - remove inode from main memory
  * @ip:		inode to discard.
@@ -350,5 +357,5 @@
 {
 	truncate_inode_pages(&ip->i_data, 0);
 	end_writeback(ip);
-	kmem_cache_free(vxfs_inode_cachep, ip->i_private);
+	call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index ed45a9c..68ca487 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -14,12 +14,14 @@
 	struct path old_root;
 
 	spin_lock(&fs->lock);
+	write_seqcount_begin(&fs->seq);
 	old_root = fs->root;
 	fs->root = *path;
-	path_get(path);
+	path_get_long(path);
+	write_seqcount_end(&fs->seq);
 	spin_unlock(&fs->lock);
 	if (old_root.dentry)
-		path_put(&old_root);
+		path_put_long(&old_root);
 }
 
 /*
@@ -31,13 +33,15 @@
 	struct path old_pwd;
 
 	spin_lock(&fs->lock);
+	write_seqcount_begin(&fs->seq);
 	old_pwd = fs->pwd;
 	fs->pwd = *path;
-	path_get(path);
+	path_get_long(path);
+	write_seqcount_end(&fs->seq);
 	spin_unlock(&fs->lock);
 
 	if (old_pwd.dentry)
-		path_put(&old_pwd);
+		path_put_long(&old_pwd);
 }
 
 void chroot_fs_refs(struct path *old_root, struct path *new_root)
@@ -52,31 +56,33 @@
 		fs = p->fs;
 		if (fs) {
 			spin_lock(&fs->lock);
+			write_seqcount_begin(&fs->seq);
 			if (fs->root.dentry == old_root->dentry
 			    && fs->root.mnt == old_root->mnt) {
-				path_get(new_root);
+				path_get_long(new_root);
 				fs->root = *new_root;
 				count++;
 			}
 			if (fs->pwd.dentry == old_root->dentry
 			    && fs->pwd.mnt == old_root->mnt) {
-				path_get(new_root);
+				path_get_long(new_root);
 				fs->pwd = *new_root;
 				count++;
 			}
+			write_seqcount_end(&fs->seq);
 			spin_unlock(&fs->lock);
 		}
 		task_unlock(p);
 	} while_each_thread(g, p);
 	read_unlock(&tasklist_lock);
 	while (count--)
-		path_put(old_root);
+		path_put_long(old_root);
 }
 
 void free_fs_struct(struct fs_struct *fs)
 {
-	path_put(&fs->root);
-	path_put(&fs->pwd);
+	path_put_long(&fs->root);
+	path_put_long(&fs->pwd);
 	kmem_cache_free(fs_cachep, fs);
 }
 
@@ -88,8 +94,10 @@
 		int kill;
 		task_lock(tsk);
 		spin_lock(&fs->lock);
+		write_seqcount_begin(&fs->seq);
 		tsk->fs = NULL;
 		kill = !--fs->users;
+		write_seqcount_end(&fs->seq);
 		spin_unlock(&fs->lock);
 		task_unlock(tsk);
 		if (kill)
@@ -105,8 +113,15 @@
 		fs->users = 1;
 		fs->in_exec = 0;
 		spin_lock_init(&fs->lock);
+		seqcount_init(&fs->seq);
 		fs->umask = old->umask;
-		get_fs_root_and_pwd(old, &fs->root, &fs->pwd);
+
+		spin_lock(&old->lock);
+		fs->root = old->root;
+		path_get_long(&fs->root);
+		fs->pwd = old->pwd;
+		path_get_long(&fs->pwd);
+		spin_unlock(&old->lock);
 	}
 	return fs;
 }
@@ -144,6 +159,7 @@
 struct fs_struct init_fs = {
 	.users		= 1,
 	.lock		= __SPIN_LOCK_UNLOCKED(init_fs.lock),
+	.seq		= SEQCNT_ZERO,
 	.umask		= 0022,
 };
 
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index c9627c9..f738599 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -156,8 +156,12 @@
  */
 static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
 {
-	struct inode *inode = entry->d_inode;
+	struct inode *inode;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = entry->d_inode;
 	if (inode && is_bad_inode(inode))
 		return 0;
 	else if (fuse_dentry_time(entry) < get_jiffies_64()) {
@@ -347,7 +351,7 @@
 	}
 
 	entry = newent ? newent : entry;
-	entry->d_op = &fuse_dentry_operations;
+	d_set_d_op(entry, &fuse_dentry_operations);
 	if (outarg_valid)
 		fuse_change_entry_timeout(entry, &outarg);
 	else
@@ -981,12 +985,15 @@
  * access request is sent.  Execute permission is still checked
  * locally based on file mode.
  */
-static int fuse_permission(struct inode *inode, int mask)
+static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	bool refreshed = false;
 	int err = 0;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	if (!fuse_allow_task(fc, current))
 		return -EACCES;
 
@@ -1001,7 +1008,7 @@
 	}
 
 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
-		err = generic_permission(inode, mask, NULL);
+		err = generic_permission(inode, mask, flags, NULL);
 
 		/* If permission is denied, try to refresh file
 		   attributes.  This is also needed, because the root
@@ -1009,7 +1016,8 @@
 		if (err == -EACCES && !refreshed) {
 			err = fuse_do_getattr(inode, NULL, NULL);
 			if (!err)
-				err = generic_permission(inode, mask, NULL);
+				err = generic_permission(inode, mask,
+							flags, NULL);
 		}
 
 		/* Note: the opposite of the above test does not
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index cfce3ad..a8b31da 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -99,6 +99,13 @@
 	return inode;
 }
 
+static void fuse_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(fuse_inode_cachep, inode);
+}
+
 static void fuse_destroy_inode(struct inode *inode)
 {
 	struct fuse_inode *fi = get_fuse_inode(inode);
@@ -106,7 +113,7 @@
 	BUG_ON(!list_empty(&fi->queued_writes));
 	if (fi->forget_req)
 		fuse_request_free(fi->forget_req);
-	kmem_cache_free(fuse_inode_cachep, inode);
+	call_rcu(&inode->i_rcu, fuse_i_callback);
 }
 
 void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
@@ -619,7 +626,7 @@
 
 	entry = d_obtain_alias(inode);
 	if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) {
-		entry->d_op = &fuse_dentry_operations;
+		d_set_d_op(entry, &fuse_dentry_operations);
 		fuse_invalidate_entry_cache(entry);
 	}
 
@@ -721,7 +728,7 @@
 
 	parent = d_obtain_alias(inode);
 	if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) {
-		parent->d_op = &fuse_dentry_operations;
+		d_set_d_op(parent, &fuse_dentry_operations);
 		fuse_invalidate_entry_cache(parent);
 	}
 
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index 6bc9e3a..06c48a8 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -190,14 +190,20 @@
 }
 
 int
-generic_check_acl(struct inode *inode, int mask)
+generic_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct posix_acl *acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
+	if (flags & IPERM_FLAG_RCU) {
+		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
+			return -ECHILD;
+	} else {
+		struct posix_acl *acl;
 
-	if (acl) {
-		int error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
+		acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
+		if (acl) {
+			int error = posix_acl_permission(inode, acl, mask);
+			posix_acl_release(acl);
+			return error;
+		}
 	}
 	return -EAGAIN;
 }
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 48171f4..7118f1a 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -75,11 +75,14 @@
  * Returns: errno
  */
 
-int gfs2_check_acl(struct inode *inode, int mask)
+int gfs2_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
 	struct posix_acl *acl;
 	int error;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index b522b0c..a93907c 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -16,7 +16,7 @@
 #define GFS2_POSIX_ACL_DEFAULT		"posix_acl_default"
 #define GFS2_ACL_MAX_ENTRIES		25
 
-extern int gfs2_check_acl(struct inode *inode, int mask);
+extern int gfs2_check_acl(struct inode *inode, int mask, unsigned int);
 extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode);
 extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
 extern const struct xattr_handler gfs2_xattr_system_handler;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 5476c06..3c4039d 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -763,7 +763,7 @@
 	int metadata;
 	unsigned int revokes = 0;
 	int x;
-	int error;
+	int error = 0;
 
 	if (!*top)
 		sm->sm_first = 0;
@@ -780,7 +780,11 @@
 	if (metadata)
 		revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
 
-	error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
+	if (ip != GFS2_I(sdp->sd_rindex))
+		error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
+	else if (!sdp->sd_rgrps)
+		error = gfs2_ri_update(ip);
+
 	if (error)
 		return error;
 
@@ -879,7 +883,8 @@
 out_rlist:
 	gfs2_rlist_free(&rlist);
 out:
-	gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
+	if (ip != GFS2_I(sdp->sd_rindex))
+		gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
 	return error;
 }
 
diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c
index 6798755..4a45633 100644
--- a/fs/gfs2/dentry.c
+++ b/fs/gfs2/dentry.c
@@ -11,6 +11,7 @@
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
 #include <linux/gfs2_ondisk.h>
+#include <linux/namei.h>
 #include <linux/crc32.h>
 
 #include "gfs2.h"
@@ -34,15 +35,23 @@
 
 static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct dentry *parent = dget_parent(dentry);
-	struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode);
-	struct gfs2_inode *dip = GFS2_I(parent->d_inode);
-	struct inode *inode = dentry->d_inode;
+	struct dentry *parent;
+	struct gfs2_sbd *sdp;
+	struct gfs2_inode *dip;
+	struct inode *inode;
 	struct gfs2_holder d_gh;
 	struct gfs2_inode *ip = NULL;
 	int error;
 	int had_lock = 0;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	parent = dget_parent(dentry);
+	sdp = GFS2_SB(parent->d_inode);
+	dip = GFS2_I(parent->d_inode);
+	inode = dentry->d_inode;
+
 	if (inode) {
 		if (is_bad_inode(inode))
 			goto invalid;
@@ -100,13 +109,14 @@
 	return 0;
 }
 
-static int gfs2_dhash(struct dentry *dentry, struct qstr *str)
+static int gfs2_dhash(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *str)
 {
 	str->hash = gfs2_disk_hash(str->name, str->len);
 	return 0;
 }
 
-static int gfs2_dentry_delete(struct dentry *dentry)
+static int gfs2_dentry_delete(const struct dentry *dentry)
 {
 	struct gfs2_inode *ginode;
 
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c
index 5ab3839..97012ec 100644
--- a/fs/gfs2/export.c
+++ b/fs/gfs2/export.c
@@ -130,7 +130,7 @@
 
 	dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
 	if (!IS_ERR(dentry))
-		dentry->d_op = &gfs2_dops;
+		d_set_d_op(dentry, &gfs2_dops);
 	return dentry;
 }
 
@@ -158,7 +158,7 @@
 out_inode:
 	dentry = d_obtain_alias(inode);
 	if (!IS_ERR(dentry))
-		dentry->d_op = &gfs2_dops;
+		d_set_d_op(dentry, &gfs2_dops);
 	return dentry;
 }
 
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index aa99647..fca6689 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -241,7 +241,7 @@
 	    !capable(CAP_LINUX_IMMUTABLE))
 		goto out;
 	if (!IS_IMMUTABLE(inode)) {
-		error = gfs2_permission(inode, MAY_WRITE);
+		error = gfs2_permission(inode, MAY_WRITE, 0);
 		if (error)
 			goto out;
 	}
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index f92c177..08a8beb 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -541,21 +541,6 @@
 	spin_unlock(&gl->gl_spin);
 }
 
-static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
-				 unsigned int req_state,
-				 unsigned int flags)
-{
-	int ret = LM_OUT_ERROR;
-
-	if (!sdp->sd_lockstruct.ls_ops->lm_lock)
-		return req_state == LM_ST_UNLOCKED ? 0 : req_state;
-
-	if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
-		ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock,
-							 req_state, flags);
-	return ret;
-}
-
 /**
  * do_xmote - Calls the DLM to change the state of a lock
  * @gl: The lock state
@@ -575,13 +560,14 @@
 
 	lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP |
 		      LM_FLAG_PRIORITY);
-	BUG_ON(gl->gl_state == target);
-	BUG_ON(gl->gl_state == gl->gl_target);
+	GLOCK_BUG_ON(gl, gl->gl_state == target);
+	GLOCK_BUG_ON(gl, gl->gl_state == gl->gl_target);
 	if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) &&
 	    glops->go_inval) {
 		set_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
 		do_error(gl, 0); /* Fail queued try locks */
 	}
+	gl->gl_req = target;
 	spin_unlock(&gl->gl_spin);
 	if (glops->go_xmote_th)
 		glops->go_xmote_th(gl);
@@ -594,15 +580,17 @@
 	    gl->gl_state == LM_ST_DEFERRED) &&
 	    !(lck_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
 		lck_flags |= LM_FLAG_TRY_1CB;
-	ret = gfs2_lm_lock(sdp, gl, target, lck_flags);
 
-	if (!(ret & LM_OUT_ASYNC)) {
-		finish_xmote(gl, ret);
+	if (sdp->sd_lockstruct.ls_ops->lm_lock)	{
+		/* lock_dlm */
+		ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
+		GLOCK_BUG_ON(gl, ret);
+	} else { /* lock_nolock */
+		finish_xmote(gl, target);
 		if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
 			gfs2_glock_put(gl);
-	} else {
-		GLOCK_BUG_ON(gl, ret != LM_OUT_ASYNC);
 	}
+
 	spin_lock(&gl->gl_spin);
 }
 
@@ -951,17 +939,22 @@
 
 void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	va_start(args, fmt);
+
 	if (seq) {
 		struct gfs2_glock_iter *gi = seq->private;
 		vsprintf(gi->string, fmt, args);
 		seq_printf(seq, gi->string);
 	} else {
-		printk(KERN_ERR " ");
-		vprintk(fmt, args);
+		vaf.fmt = fmt;
+		vaf.va = &args;
+
+		printk(KERN_ERR " %pV", &vaf);
 	}
+
 	va_end(args);
 }
 
@@ -1361,24 +1354,28 @@
  * @gl: Pointer to the glock
  * @ret: The return value from the dlm
  *
+ * The gl_reply field is under the gl_spin lock so that it is ok
+ * to use a bitfield shared with other glock state fields.
  */
 
 void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
 {
 	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
 
+	spin_lock(&gl->gl_spin);
 	gl->gl_reply = ret;
 
 	if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) {
-		spin_lock(&gl->gl_spin);
 		if (gfs2_should_freeze(gl)) {
 			set_bit(GLF_FROZEN, &gl->gl_flags);
 			spin_unlock(&gl->gl_spin);
 			return;
 		}
-		spin_unlock(&gl->gl_spin);
 	}
+
+	spin_unlock(&gl->gl_spin);
 	set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
+	smp_wmb();
 	gfs2_glock_hold(gl);
 	if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
 		gfs2_glock_put(gl);
@@ -1626,18 +1623,17 @@
 static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
 {
 	struct task_struct *gh_owner = NULL;
-	char buffer[KSYM_SYMBOL_LEN];
 	char flags_buf[32];
 
-	sprint_symbol(buffer, gh->gh_ip);
 	if (gh->gh_owner_pid)
 		gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID);
-	gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %s\n",
-		  state2str(gh->gh_state),
-		  hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags),
-		  gh->gh_error, 
-		  gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
-		  gh_owner ? gh_owner->comm : "(ended)", buffer);
+	gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n",
+		       state2str(gh->gh_state),
+		       hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags),
+		       gh->gh_error,
+		       gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
+		       gh_owner ? gh_owner->comm : "(ended)",
+		       (void *)gh->gh_ip);
 	return 0;
 }
 
@@ -1782,12 +1778,13 @@
 	}
 #endif
 
-	glock_workqueue = alloc_workqueue("glock_workqueue", WQ_RESCUER |
+	glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
 					  WQ_HIGHPRI | WQ_FREEZEABLE, 0);
 	if (IS_ERR(glock_workqueue))
 		return PTR_ERR(glock_workqueue);
-	gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", WQ_RESCUER |
-						WQ_FREEZEABLE, 0);
+	gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
+						WQ_MEM_RECLAIM | WQ_FREEZEABLE,
+						0);
 	if (IS_ERR(gfs2_delete_workqueue)) {
 		destroy_workqueue(glock_workqueue);
 		return PTR_ERR(gfs2_delete_workqueue);
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index db1c26d..691851c 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -87,11 +87,10 @@
 #define GL_ASYNC		0x00000040
 #define GL_EXACT		0x00000080
 #define GL_SKIP			0x00000100
-#define GL_ATIME		0x00000200
 #define GL_NOCACHE		0x00000400
   
 /*
- * lm_lock() and lm_async_cb return flags
+ * lm_async_cb return flags
  *
  * LM_OUT_ST_MASK
  * Masks the lower two bits of lock state in the returned value.
@@ -99,15 +98,11 @@
  * LM_OUT_CANCELED
  * The lock request was canceled.
  *
- * LM_OUT_ASYNC
- * The result of the request will be returned in an LM_CB_ASYNC callback.
- *
  */
 
 #define LM_OUT_ST_MASK		0x00000003
 #define LM_OUT_CANCELED		0x00000008
-#define LM_OUT_ASYNC		0x00000080
-#define LM_OUT_ERROR		0x00000100
+#define LM_OUT_ERROR		0x00000004
 
 /*
  * lm_recovery_done() messages
@@ -124,25 +119,12 @@
  	void (*lm_unmount) (struct gfs2_sbd *sdp);
 	void (*lm_withdraw) (struct gfs2_sbd *sdp);
 	void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl);
-	unsigned int (*lm_lock) (struct gfs2_glock *gl,
-				 unsigned int req_state, unsigned int flags);
+	int (*lm_lock) (struct gfs2_glock *gl, unsigned int req_state,
+			unsigned int flags);
 	void (*lm_cancel) (struct gfs2_glock *gl);
 	const match_table_t *lm_tokens;
 };
 
-#define LM_FLAG_TRY		0x00000001
-#define LM_FLAG_TRY_1CB		0x00000002
-#define LM_FLAG_NOEXP		0x00000004
-#define LM_FLAG_ANY		0x00000008
-#define LM_FLAG_PRIORITY	0x00000010
-
-#define GL_ASYNC		0x00000040
-#define GL_EXACT		0x00000080
-#define GL_SKIP			0x00000100
-#define GL_NOCACHE		0x00000400
-
-#define GLR_TRYFAILED		13
-
 extern struct workqueue_struct *gfs2_delete_workqueue;
 static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
 {
@@ -212,6 +194,8 @@
 int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
 void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
 void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
+
+__attribute__ ((format(printf, 2, 3)))
 void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
 
 /**
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 0d149dc..263561b 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -325,7 +325,6 @@
 
 	if (gl->gl_state != LM_ST_UNLOCKED &&
 	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
-		flush_workqueue(gfs2_delete_workqueue);
 		gfs2_meta_syncfs(sdp);
 		gfs2_log_shutdown(sdp);
 	}
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 764fbb4..8d3d2b4 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -207,12 +207,14 @@
 
 	spinlock_t gl_spin;
 
-	unsigned int gl_state;
-	unsigned int gl_target;
-	unsigned int gl_reply;
+	/* State fields protected by gl_spin */
+	unsigned int gl_state:2,	/* Current state */
+		     gl_target:2,	/* Target state */
+		     gl_demote_state:2,	/* State requested by remote node */
+		     gl_req:2,		/* State in last dlm request */
+		     gl_reply:8;	/* Last reply from the dlm */
+
 	unsigned int gl_hash;
-	unsigned int gl_req;
-	unsigned int gl_demote_state; /* state requested by remote node */
 	unsigned long gl_demote_time; /* time of first demote request */
 	struct list_head gl_holders;
 
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index e1213f7..2232b3c 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -509,7 +509,7 @@
 	}
 
 	if (!is_root) {
-		error = gfs2_permission(dir, MAY_EXEC);
+		error = gfs2_permission(dir, MAY_EXEC, 0);
 		if (error)
 			goto out;
 	}
@@ -539,7 +539,7 @@
 {
 	int error;
 
-	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC);
+	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0);
 	if (error)
 		return error;
 
@@ -916,17 +916,8 @@
 	if (error)
 		return error;
 
-	if ((attr->ia_valid & ATTR_SIZE) &&
-	    attr->ia_size != i_size_read(inode)) {
-		error = vmtruncate(inode, attr->ia_size);
-		if (error)
-			return error;
-	}
-
 	setattr_copy(inode, attr);
 	mark_inode_dirty(inode);
-
-	gfs2_assert_warn(GFS2_SB(inode), !error);
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
 	brelse(dibh);
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index d8499fa..732a183 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -113,7 +113,7 @@
 extern struct inode *gfs2_createi(struct gfs2_holder *ghs,
 				  const struct qstr *name,
 				  unsigned int mode, dev_t dev);
-extern int gfs2_permission(struct inode *inode, int mask);
+extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags);
 extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
 extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
 extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 1c09425..6e493ae 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -146,15 +146,13 @@
 	return lkf;
 }
 
-static unsigned int gdlm_lock(struct gfs2_glock *gl,
-			      unsigned int req_state, unsigned int flags)
+static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
+		     unsigned int flags)
 {
 	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
-	int error;
 	int req;
 	u32 lkf;
 
-	gl->gl_req = req_state;
 	req = make_mode(req_state);
 	lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req);
 
@@ -162,13 +160,8 @@
 	 * Submit the actual lock request.
 	 */
 
-	error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname,
-			 GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
-	if (error == -EAGAIN)
-		return 0;
-	if (error)
-		return LM_OUT_ERROR;
-	return LM_OUT_ASYNC;
+	return dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname,
+			GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
 }
 
 static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 3eb1393..2aeabd4 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -440,7 +440,7 @@
 		iput(inode);
 		return -ENOMEM;
 	}
-	dentry->d_op = &gfs2_dops;
+	d_set_d_op(dentry, &gfs2_dops);
 	*dptr = dentry;
 	return 0;
 }
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 12cbea7..1501db4 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -106,7 +106,7 @@
 {
 	struct inode *inode = NULL;
 
-	dentry->d_op = &gfs2_dops;
+	d_set_d_op(dentry, &gfs2_dops);
 
 	inode = gfs2_lookupi(dir, &dentry->d_name, 0);
 	if (inode && IS_ERR(inode))
@@ -166,7 +166,7 @@
 	if (error)
 		goto out_child;
 
-	error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC);
+	error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0);
 	if (error)
 		goto out_gunlock;
 
@@ -289,7 +289,7 @@
 	if (IS_APPEND(&dip->i_inode))
 		return -EPERM;
 
-	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC);
+	error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0);
 	if (error)
 		return error;
 
@@ -822,7 +822,7 @@
 			}
 		}
 	} else {
-		error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC);
+		error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC, 0);
 		if (error)
 			goto out_gunlock;
 
@@ -857,7 +857,7 @@
 	/* Check out the dir to be renamed */
 
 	if (dir_rename) {
-		error = gfs2_permission(odentry->d_inode, MAY_WRITE);
+		error = gfs2_permission(odentry->d_inode, MAY_WRITE, 0);
 		if (error)
 			goto out_gunlock;
 	}
@@ -1041,13 +1041,17 @@
  * Returns: errno
  */
 
-int gfs2_permission(struct inode *inode, int mask)
+int gfs2_permission(struct inode *inode, int mask, unsigned int flags)
 {
-	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_inode *ip;
 	struct gfs2_holder i_gh;
 	int error;
 	int unlock = 0;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
+	ip = GFS2_I(inode);
 	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
 		if (error)
@@ -1058,7 +1062,7 @@
 	if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
 		error = -EACCES;
 	else
-		error = generic_permission(inode, mask, gfs2_check_acl);
+		error = generic_permission(inode, mask, flags, gfs2_check_acl);
 	if (unlock)
 		gfs2_glock_dq_uninit(&i_gh);
 
@@ -1069,7 +1073,6 @@
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
-	struct buffer_head *dibh;
 	u32 ouid, ogid, nuid, ngid;
 	int error;
 
@@ -1100,25 +1103,10 @@
 	if (error)
 		goto out_gunlock_q;
 
-	error = gfs2_meta_inode_buffer(ip, &dibh);
+	error = gfs2_setattr_simple(ip, attr);
 	if (error)
 		goto out_end_trans;
 
-	if ((attr->ia_valid & ATTR_SIZE) &&
-	    attr->ia_size != i_size_read(inode)) {
-		int error;
-
-		error = vmtruncate(inode, attr->ia_size);
-		gfs2_assert_warn(sdp, !error);
-	}
-
-	setattr_copy(inode, attr);
-	mark_inode_dirty(inode);
-
-	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-	gfs2_dinode_out(ip, dibh->b_data);
-	brelse(dibh);
-
 	if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
 		u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
 		gfs2_quota_change(ip, -blocks, ouid, ogid);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index f606baf..a689901 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -666,6 +666,10 @@
 			qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift);
 			qd->qd_qb.qb_limit = qp->qu_limit;
 		}
+		if (fdq->d_fieldmask & FS_DQ_BCOUNT) {
+			qp->qu_value = cpu_to_be64(fdq->d_bcount >> sdp->sd_fsb2bb_shift);
+			qd->qd_qb.qb_value = qp->qu_value;
+		}
 	}
 
 	/* Write the quota into the quota file on disk */
@@ -1509,7 +1513,7 @@
 }
 
 /* GFS2 only supports a subset of the XFS fields */
-#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD)
+#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT)
 
 static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
 			  struct fs_disk_quota *fdq)
@@ -1569,9 +1573,15 @@
 	if ((fdq->d_fieldmask & FS_DQ_BSOFT) &&
 	    ((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
 		fdq->d_fieldmask ^= FS_DQ_BSOFT;
+
 	if ((fdq->d_fieldmask & FS_DQ_BHARD) &&
 	    ((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
 		fdq->d_fieldmask ^= FS_DQ_BHARD;
+
+	if ((fdq->d_fieldmask & FS_DQ_BCOUNT) &&
+	    ((fdq->d_bcount >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_value)))
+		fdq->d_fieldmask ^= FS_DQ_BCOUNT;
+
 	if (fdq->d_fieldmask == 0)
 		goto out_i;
 
@@ -1620,4 +1630,3 @@
 	.get_dqblk	= gfs2_get_dqblk,
 	.set_dqblk	= gfs2_set_dqblk,
 };
-
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 33c8407..7293ea2 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -500,7 +500,7 @@
 	for (rgrps = 0;; rgrps++) {
 		loff_t pos = rgrps * sizeof(struct gfs2_rindex);
 
-		if (pos + sizeof(struct gfs2_rindex) >= i_size_read(inode))
+		if (pos + sizeof(struct gfs2_rindex) > i_size_read(inode))
 			break;
 		error = gfs2_internal_read(ip, &ra_state, buf, &pos,
 					   sizeof(struct gfs2_rindex));
@@ -583,7 +583,7 @@
  * Returns: 0 on successful update, error code otherwise
  */
 
-static int gfs2_ri_update(struct gfs2_inode *ip)
+int gfs2_ri_update(struct gfs2_inode *ip)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct inode *inode = &ip->i_inode;
@@ -614,46 +614,6 @@
 }
 
 /**
- * gfs2_ri_update_special - Pull in a new resource index from the disk
- *
- * This is a special version that's safe to call from gfs2_inplace_reserve_i.
- * In this case we know that we don't have any resource groups in memory yet.
- *
- * @ip: pointer to the rindex inode
- *
- * Returns: 0 on successful update, error code otherwise
- */
-static int gfs2_ri_update_special(struct gfs2_inode *ip)
-{
-	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-	struct inode *inode = &ip->i_inode;
-	struct file_ra_state ra_state;
-	struct gfs2_rgrpd *rgd;
-	unsigned int max_data = 0;
-	int error;
-
-	file_ra_state_init(&ra_state, inode->i_mapping);
-	for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
-		/* Ignore partials */
-		if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
-		    i_size_read(inode))
-			break;
-		error = read_rindex_entry(ip, &ra_state);
-		if (error) {
-			clear_rgrpdi(sdp);
-			return error;
-		}
-	}
-	list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
-		if (rgd->rd_data > max_data)
-			max_data = rgd->rd_data;
-	sdp->sd_max_rg_data = max_data;
-
-	sdp->sd_rindex_uptodate = 1;
-	return 0;
-}
-
-/**
  * gfs2_rindex_hold - Grab a lock on the rindex
  * @sdp: The GFS2 superblock
  * @ri_gh: the glock holder
@@ -1226,16 +1186,25 @@
 			error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
 		else if (!sdp->sd_rgrps) /* We may not have the rindex read
 					    in, so: */
-			error = gfs2_ri_update_special(ip);
+			error = gfs2_ri_update(ip);
 		if (error)
 			return error;
 	}
 
+try_again:
 	do {
 		error = get_local_rgrp(ip, &last_unlinked);
 		/* If there is no space, flushing the log may release some */
-		if (error)
+		if (error) {
+			if (ip == GFS2_I(sdp->sd_rindex) &&
+			    !sdp->sd_rindex_uptodate) {
+				error = gfs2_ri_update(ip);
+				if (error)
+					return error;
+				goto try_again;
+			}
 			gfs2_log_flush(sdp, NULL);
+		}
 	} while (error && tries++ < 3);
 
 	if (error) {
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 0e35c04..50c2bb0 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -48,6 +48,7 @@
 
 extern void gfs2_inplace_release(struct gfs2_inode *ip);
 
+extern int gfs2_ri_update(struct gfs2_inode *ip);
 extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
 extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);
 
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 2b2c499..16c2eca 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1405,9 +1405,16 @@
 	return &ip->i_inode;
 }
 
+static void gfs2_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(gfs2_inode_cachep, inode);
+}
+
 static void gfs2_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(gfs2_inode_cachep, inode);
+	call_rcu(&inode->i_rcu, gfs2_i_callback);
 }
 
 const struct super_operations gfs2_super_ops = {
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 30b58f07..439b61c0 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -1296,10 +1296,8 @@
 
 int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
 {
-	struct inode *inode = &ip->i_inode;
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_ea_location el;
-	struct buffer_head *dibh;
 	int error;
 
 	error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el);
@@ -1321,26 +1319,7 @@
 	if (error)
 		return error;
 
-	error = gfs2_meta_inode_buffer(ip, &dibh);
-	if (error)
-		goto out_trans_end;
-
-	if ((attr->ia_valid & ATTR_SIZE) &&
-	    attr->ia_size != i_size_read(inode)) {
-		int error;
-
-		error = vmtruncate(inode, attr->ia_size);
-		gfs2_assert_warn(GFS2_SB(inode), !error);
-	}
-
-	setattr_copy(inode, attr);
-	mark_inode_dirty(inode);
-
-	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
-	gfs2_dinode_out(ip, dibh->b_data);
-	brelse(dibh);
-
-out_trans_end:
+	error = gfs2_setattr_simple(ip, attr);
 	gfs2_trans_end(sdp);
 	return error;
 }
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 2b3b861..ea4aefe 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -25,7 +25,7 @@
 	struct inode *inode = NULL;
 	int res;
 
-	dentry->d_op = &hfs_dentry_operations;
+	d_set_d_op(dentry, &hfs_dentry_operations);
 
 	hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd);
 	hfs_cat_build_key(dir->i_sb, fd.search_key, dir->i_ino, &dentry->d_name);
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index c8cffb8..ad97c2d 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -213,10 +213,14 @@
 /* string.c */
 extern const struct dentry_operations hfs_dentry_operations;
 
-extern int hfs_hash_dentry(struct dentry *, struct qstr *);
+extern int hfs_hash_dentry(const struct dentry *, const struct inode *,
+		struct qstr *);
 extern int hfs_strcmp(const unsigned char *, unsigned int,
 		      const unsigned char *, unsigned int);
-extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
+extern int hfs_compare_dentry(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
 
 /* trans.c */
 extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
diff --git a/fs/hfs/string.c b/fs/hfs/string.c
index 927a5af..495a976 100644
--- a/fs/hfs/string.c
+++ b/fs/hfs/string.c
@@ -51,7 +51,8 @@
 /*
  * Hash a string to an integer in a case-independent way
  */
-int hfs_hash_dentry(struct dentry *dentry, struct qstr *this)
+int hfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *this)
 {
 	const unsigned char *name = this->name;
 	unsigned int hash, len = this->len;
@@ -92,21 +93,21 @@
  * Test for equality of two strings in the HFS filename character ordering.
  * return 1 on failure and 0 on success
  */
-int hfs_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2)
+int hfs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
 	const unsigned char *n1, *n2;
-	int len;
 
-	len = s1->len;
 	if (len >= HFS_NAMELEN) {
-		if (s2->len < HFS_NAMELEN)
+		if (name->len < HFS_NAMELEN)
 			return 1;
 		len = HFS_NAMELEN;
-	} else if (len != s2->len)
+	} else if (len != name->len)
 		return 1;
 
-	n1 = s1->name;
-	n2 = s2->name;
+	n1 = str;
+	n2 = name->name;
 	while (len--) {
 		if (caseorder[*n1++] != caseorder[*n2++])
 			return 1;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 4824c27..0bef62a 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -167,9 +167,16 @@
 	return i ? &i->vfs_inode : NULL;
 }
 
+static void hfs_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(hfs_inode_cachep, HFS_I(inode));
+}
+
 static void hfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
+	call_rcu(&inode->i_rcu, hfs_i_callback);
 }
 
 static const struct super_operations hfs_super_operations = {
@@ -427,7 +434,7 @@
 	if (!sb->s_root)
 		goto bail_iput;
 
-	sb->s_root->d_op = &hfs_dentry_operations;
+	d_set_d_op(sb->s_root, &hfs_dentry_operations);
 
 	/* everything's okay */
 	return 0;
diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
index 7478f5c..19cf291 100644
--- a/fs/hfs/sysdep.c
+++ b/fs/hfs/sysdep.c
@@ -8,15 +8,20 @@
  * This file contains the code to do various system dependent things.
  */
 
+#include <linux/namei.h>
 #include "hfs_fs.h"
 
 /* dentry case-handling: just lowercase everything */
 
 static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode;
 	int diff;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = dentry->d_inode;
 	if(!inode)
 		return 1;
 
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index d182438..5d799c1 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -22,7 +22,8 @@
 		return -ENOMEM;
 	fd->search_key = ptr;
 	fd->key = ptr + tree->max_key_len + 2;
-	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
+	dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n",
+		tree->cnid, __builtin_return_address(0));
 	mutex_lock(&tree->tree_lock);
 	return 0;
 }
@@ -31,7 +32,8 @@
 {
 	hfs_bnode_put(fd->bnode);
 	kfree(fd->search_key);
-	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
+	dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n",
+		fd->tree->cnid, __builtin_return_address(0));
 	mutex_unlock(&fd->tree->tree_lock);
 	fd->tree = NULL;
 }
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index ad57f59..1cad80c 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -15,7 +15,8 @@
 
 #define PAGE_CACHE_BITS	(PAGE_CACHE_SIZE * 8)
 
-int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
+int hfsplus_block_allocate(struct super_block *sb, u32 size,
+		u32 offset, u32 *max)
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct page *page;
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 29da657..1c42cc5 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -42,7 +42,7 @@
 u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
 {
 	__be16 data;
-	// optimize later...
+	/* TODO: optimize later... */
 	hfs_bnode_read(node, &data, off, 2);
 	return be16_to_cpu(data);
 }
@@ -50,7 +50,7 @@
 u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off)
 {
 	u8 data;
-	// optimize later...
+	/* TODO: optimize later... */
 	hfs_bnode_read(node, &data, off, 1);
 	return data;
 }
@@ -96,7 +96,7 @@
 void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
 {
 	__be16 v = cpu_to_be16(data);
-	// optimize later...
+	/* TODO: optimize later... */
 	hfs_bnode_write(node, &v, off, 2);
 }
 
@@ -212,7 +212,8 @@
 				dst_page--;
 			}
 			src -= len;
-			memmove(kmap(*dst_page) + src, kmap(*src_page) + src, len);
+			memmove(kmap(*dst_page) + src,
+				kmap(*src_page) + src, len);
 			kunmap(*src_page);
 			set_page_dirty(*dst_page);
 			kunmap(*dst_page);
@@ -250,14 +251,16 @@
 
 		if (src == dst) {
 			l = min(len, (int)PAGE_CACHE_SIZE - src);
-			memmove(kmap(*dst_page) + src, kmap(*src_page) + src, l);
+			memmove(kmap(*dst_page) + src,
+				kmap(*src_page) + src, l);
 			kunmap(*src_page);
 			set_page_dirty(*dst_page);
 			kunmap(*dst_page);
 
 			while ((len -= l) != 0) {
 				l = min(len, (int)PAGE_CACHE_SIZE);
-				memmove(kmap(*++dst_page), kmap(*++src_page), l);
+				memmove(kmap(*++dst_page),
+					kmap(*++src_page), l);
 				kunmap(*src_page);
 				set_page_dirty(*dst_page);
 				kunmap(*dst_page);
@@ -268,7 +271,8 @@
 			do {
 				src_ptr = kmap(*src_page) + src;
 				dst_ptr = kmap(*dst_page) + dst;
-				if (PAGE_CACHE_SIZE - src < PAGE_CACHE_SIZE - dst) {
+				if (PAGE_CACHE_SIZE - src <
+						PAGE_CACHE_SIZE - dst) {
 					l = PAGE_CACHE_SIZE - src;
 					src = 0;
 					dst += l;
@@ -340,7 +344,8 @@
 			return;
 		tmp->next = node->next;
 		cnid = cpu_to_be32(tmp->next);
-		hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
+		hfs_bnode_write(tmp, &cnid,
+			offsetof(struct hfs_bnode_desc, next), 4);
 		hfs_bnode_put(tmp);
 	} else if (node->type == HFS_NODE_LEAF)
 		tree->leaf_head = node->next;
@@ -351,15 +356,15 @@
 			return;
 		tmp->prev = node->prev;
 		cnid = cpu_to_be32(tmp->prev);
-		hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, prev), 4);
+		hfs_bnode_write(tmp, &cnid,
+			offsetof(struct hfs_bnode_desc, prev), 4);
 		hfs_bnode_put(tmp);
 	} else if (node->type == HFS_NODE_LEAF)
 		tree->leaf_tail = node->prev;
 
-	// move down?
-	if (!node->prev && !node->next) {
-		printk(KERN_DEBUG "hfs_btree_del_level\n");
-	}
+	/* move down? */
+	if (!node->prev && !node->next)
+		dprint(DBG_BNODE_MOD, "hfs_btree_del_level\n");
 	if (!node->parent) {
 		tree->root = 0;
 		tree->depth = 0;
@@ -379,16 +384,16 @@
 	struct hfs_bnode *node;
 
 	if (cnid >= tree->node_count) {
-		printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
+		printk(KERN_ERR "hfs: request for non-existent node "
+				"%d in B*Tree\n",
+			cnid);
 		return NULL;
 	}
 
 	for (node = tree->node_hash[hfs_bnode_hash(cnid)];
-	     node; node = node->next_hash) {
-		if (node->this == cnid) {
+			node; node = node->next_hash)
+		if (node->this == cnid)
 			return node;
-		}
-	}
 	return NULL;
 }
 
@@ -402,7 +407,9 @@
 	loff_t off;
 
 	if (cnid >= tree->node_count) {
-		printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
+		printk(KERN_ERR "hfs: request for non-existent node "
+				"%d in B*Tree\n",
+			cnid);
 		return NULL;
 	}
 
@@ -429,7 +436,8 @@
 	} else {
 		spin_unlock(&tree->hash_lock);
 		kfree(node);
-		wait_event(node2->lock_wq, !test_bit(HFS_BNODE_NEW, &node2->flags));
+		wait_event(node2->lock_wq,
+			!test_bit(HFS_BNODE_NEW, &node2->flags));
 		return node2;
 	}
 	spin_unlock(&tree->hash_lock);
@@ -483,7 +491,8 @@
 	if (node) {
 		hfs_bnode_get(node);
 		spin_unlock(&tree->hash_lock);
-		wait_event(node->lock_wq, !test_bit(HFS_BNODE_NEW, &node->flags));
+		wait_event(node->lock_wq,
+			!test_bit(HFS_BNODE_NEW, &node->flags));
 		if (test_bit(HFS_BNODE_ERROR, &node->flags))
 			goto node_error;
 		return node;
@@ -497,7 +506,8 @@
 	if (!test_bit(HFS_BNODE_NEW, &node->flags))
 		return node;
 
-	desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) + node->page_offset);
+	desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) +
+			node->page_offset);
 	node->prev = be32_to_cpu(desc->prev);
 	node->next = be32_to_cpu(desc->next);
 	node->num_recs = be16_to_cpu(desc->num_recs);
@@ -556,11 +566,13 @@
 
 void hfs_bnode_free(struct hfs_bnode *node)
 {
-	//int i;
+#if 0
+	int i;
 
-	//for (i = 0; i < node->tree->pages_per_bnode; i++)
-	//	if (node->page[i])
-	//		page_cache_release(node->page[i]);
+	for (i = 0; i < node->tree->pages_per_bnode; i++)
+		if (node->page[i])
+			page_cache_release(node->page[i]);
+#endif
 	kfree(node);
 }
 
@@ -607,7 +619,8 @@
 	if (node) {
 		atomic_inc(&node->refcnt);
 		dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
-		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
+			node->tree->cnid, node->this,
+			atomic_read(&node->refcnt));
 	}
 }
 
@@ -619,7 +632,8 @@
 		int i;
 
 		dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
-		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
+			node->tree->cnid, node->this,
+			atomic_read(&node->refcnt));
 		BUG_ON(!atomic_read(&node->refcnt));
 		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 2f39d05..2312de3 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -39,7 +39,8 @@
 	   !(node->tree->attributes & HFS_TREE_VARIDXKEYS)) {
 		retval = node->tree->max_key_len + 2;
 	} else {
-		recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
+		recoff = hfs_bnode_read_u16(node,
+			node->tree->node_size - (rec + 1) * 2);
 		if (!recoff)
 			return 0;
 
@@ -84,7 +85,8 @@
 	end_rec_off = tree->node_size - (node->num_recs + 1) * 2;
 	end_off = hfs_bnode_read_u16(node, end_rec_off);
 	end_rec_off -= 2;
-	dprint(DBG_BNODE_MOD, "insert_rec: %d, %d, %d, %d\n", rec, size, end_off, end_rec_off);
+	dprint(DBG_BNODE_MOD, "insert_rec: %d, %d, %d, %d\n",
+		rec, size, end_off, end_rec_off);
 	if (size > end_rec_off - end_off) {
 		if (new_node)
 			panic("not enough room!\n");
@@ -99,7 +101,9 @@
 	}
 	node->num_recs++;
 	/* write new last offset */
-	hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
+	hfs_bnode_write_u16(node,
+		offsetof(struct hfs_bnode_desc, num_recs),
+		node->num_recs);
 	hfs_bnode_write_u16(node, end_rec_off, end_off + size);
 	data_off = end_off;
 	data_rec_off = end_rec_off + 2;
@@ -151,7 +155,8 @@
 		if (tree->attributes & HFS_TREE_VARIDXKEYS)
 			key_len = be16_to_cpu(fd->search_key->key_len) + 2;
 		else {
-			fd->search_key->key_len = cpu_to_be16(tree->max_key_len);
+			fd->search_key->key_len =
+				cpu_to_be16(tree->max_key_len);
 			key_len = tree->max_key_len + 2;
 		}
 		goto again;
@@ -180,7 +185,8 @@
 		mark_inode_dirty(tree->inode);
 	}
 	hfs_bnode_dump(node);
-	dprint(DBG_BNODE_MOD, "remove_rec: %d, %d\n", fd->record, fd->keylength + fd->entrylength);
+	dprint(DBG_BNODE_MOD, "remove_rec: %d, %d\n",
+		fd->record, fd->keylength + fd->entrylength);
 	if (!--node->num_recs) {
 		hfs_bnode_unlink(node);
 		if (!node->parent)
@@ -194,7 +200,9 @@
 		__hfs_brec_find(node, fd);
 		goto again;
 	}
-	hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs);
+	hfs_bnode_write_u16(node,
+		offsetof(struct hfs_bnode_desc, num_recs),
+		node->num_recs);
 
 	if (rec_off == end_off)
 		goto skip;
@@ -364,7 +372,8 @@
 		newkeylen = hfs_bnode_read_u16(node, 14) + 2;
 	else
 		fd->keylength = newkeylen = tree->max_key_len + 2;
-	dprint(DBG_BNODE_MOD, "update_rec: %d, %d, %d\n", rec, fd->keylength, newkeylen);
+	dprint(DBG_BNODE_MOD, "update_rec: %d, %d, %d\n",
+		rec, fd->keylength, newkeylen);
 
 	rec_off = tree->node_size - (rec + 2) * 2;
 	end_rec_off = tree->node_size - (parent->num_recs + 1) * 2;
@@ -375,7 +384,7 @@
 		end_off = hfs_bnode_read_u16(parent, end_rec_off);
 		if (end_rec_off - end_off < diff) {
 
-			printk(KERN_DEBUG "hfs: splitting index node...\n");
+			dprint(DBG_BNODE_MOD, "hfs: splitting index node.\n");
 			fd->bnode = parent;
 			new_node = hfs_bnode_split(fd);
 			if (IS_ERR(new_node))
@@ -383,7 +392,8 @@
 			parent = fd->bnode;
 			rec = fd->record;
 			rec_off = tree->node_size - (rec + 2) * 2;
-			end_rec_off = tree->node_size - (parent->num_recs + 1) * 2;
+			end_rec_off = tree->node_size -
+				(parent->num_recs + 1) * 2;
 		}
 	}
 
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 22e4d4e..21023d9 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -51,7 +51,8 @@
 		goto free_inode;
 
 	/* Load the header */
-	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
+	head = (struct hfs_btree_header_rec *)(kmap(page) +
+		sizeof(struct hfs_bnode_desc));
 	tree->root = be32_to_cpu(head->root);
 	tree->leaf_count = be32_to_cpu(head->leaf_count);
 	tree->leaf_head = be32_to_cpu(head->leaf_head);
@@ -115,7 +116,9 @@
 
 	tree->node_size_shift = ffs(size) - 1;
 
-	tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	tree->pages_per_bnode =
+		(tree->node_size + PAGE_CACHE_SIZE - 1) >>
+		PAGE_CACHE_SHIFT;
 
 	kunmap(page);
 	page_cache_release(page);
@@ -144,8 +147,10 @@
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
 			if (atomic_read(&node->refcnt))
-				printk(KERN_CRIT "hfs: node %d:%d still has %d user(s)!\n",
-					node->tree->cnid, node->this, atomic_read(&node->refcnt));
+				printk(KERN_CRIT "hfs: node %d:%d "
+						"still has %d user(s)!\n",
+					node->tree->cnid, node->this,
+					atomic_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
 		}
@@ -166,7 +171,8 @@
 		return;
 	/* Load the header */
 	page = node->page[0];
-	head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
+	head = (struct hfs_btree_header_rec *)(kmap(page) +
+		sizeof(struct hfs_bnode_desc));
 
 	head->root = cpu_to_be32(tree->root);
 	head->leaf_count = cpu_to_be32(tree->leaf_count);
@@ -272,7 +278,8 @@
 						tree->free_nodes--;
 						mark_inode_dirty(tree->inode);
 						hfs_bnode_put(node);
-						return hfs_bnode_create(tree, idx);
+						return hfs_bnode_create(tree,
+							idx);
 					}
 				}
 			}
@@ -287,7 +294,7 @@
 		kunmap(*pagep);
 		nidx = node->next;
 		if (!nidx) {
-			printk(KERN_DEBUG "hfs: create new bmap node...\n");
+			dprint(DBG_BNODE_MOD, "hfs: create new bmap node.\n");
 			next_node = hfs_bmap_new_bmap(node, idx);
 		} else
 			next_node = hfs_bnode_find(tree, nidx);
@@ -329,7 +336,9 @@
 		hfs_bnode_put(node);
 		if (!i) {
 			/* panic */;
-			printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
+			printk(KERN_CRIT "hfs: unable to free bnode %u. "
+					"bmap not found!\n",
+				node->this);
 			return;
 		}
 		node = hfs_bnode_find(tree, i);
@@ -337,7 +346,9 @@
 			return;
 		if (node->type != HFS_NODE_MAP) {
 			/* panic */;
-			printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
+			printk(KERN_CRIT "hfs: invalid bmap found! "
+					"(%u,%d)\n",
+				node->this, node->type);
 			hfs_bnode_put(node);
 			return;
 		}
@@ -350,7 +361,9 @@
 	m = 1 << (~nidx & 7);
 	byte = data[off];
 	if (!(byte & m)) {
-		printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
+		printk(KERN_CRIT "hfs: trying to free free bnode "
+				"%u(%d)\n",
+			node->this, node->type);
 		kunmap(page);
 		hfs_bnode_put(node);
 		return;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 8af45fc..b4ba1b3 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -91,7 +91,8 @@
 		perms->dev = 0;
 }
 
-static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode)
+static int hfsplus_cat_build_record(hfsplus_cat_entry *entry,
+		u32 cnid, struct inode *inode)
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
 
@@ -128,20 +129,32 @@
 		if (cnid == inode->i_ino) {
 			hfsplus_cat_set_perms(inode, &file->permissions);
 			if (S_ISLNK(inode->i_mode)) {
-				file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
-				file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
+				file->user_info.fdType =
+					cpu_to_be32(HFSP_SYMLINK_TYPE);
+				file->user_info.fdCreator =
+					cpu_to_be32(HFSP_SYMLINK_CREATOR);
 			} else {
-				file->user_info.fdType = cpu_to_be32(sbi->type);
-				file->user_info.fdCreator = cpu_to_be32(sbi->creator);
+				file->user_info.fdType =
+					cpu_to_be32(sbi->type);
+				file->user_info.fdCreator =
+					cpu_to_be32(sbi->creator);
 			}
-			if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
-				file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
+			if (HFSPLUS_FLG_IMMUTABLE &
+					(file->permissions.rootflags |
+					file->permissions.userflags))
+				file->flags |=
+					cpu_to_be16(HFSPLUS_FILE_LOCKED);
 		} else {
-			file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
-			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
-			file->user_info.fdFlags = cpu_to_be16(0x100);
-			file->create_date = HFSPLUS_I(sbi->hidden_dir)->create_date;
-			file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode)->linkid);
+			file->user_info.fdType =
+				cpu_to_be32(HFSP_HARDLINK_TYPE);
+			file->user_info.fdCreator =
+				cpu_to_be32(HFSP_HFSPLUS_CREATOR);
+			file->user_info.fdFlags =
+				cpu_to_be16(0x100);
+			file->create_date =
+				HFSPLUS_I(sbi->hidden_dir)->create_date;
+			file->permissions.dev =
+				cpu_to_be32(HFSPLUS_I(inode)->linkid);
 		}
 		return sizeof(*file);
 	}
@@ -182,12 +195,14 @@
 		return -EIO;
 	}
 
-	hfsplus_cat_build_key_uni(fd->search_key, be32_to_cpu(tmp.thread.parentID),
-				 &tmp.thread.nodeName);
+	hfsplus_cat_build_key_uni(fd->search_key,
+		be32_to_cpu(tmp.thread.parentID),
+		&tmp.thread.nodeName);
 	return hfs_brec_find(fd);
 }
 
-int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode)
+int hfsplus_create_cat(u32 cnid, struct inode *dir,
+		struct qstr *str, struct inode *inode)
 {
 	struct super_block *sb = dir->i_sb;
 	struct hfs_find_data fd;
@@ -195,13 +210,15 @@
 	int entry_size;
 	int err;
 
-	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink);
+	dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n",
+		str->name, cnid, inode->i_nlink);
 	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 
 	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
-	entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
+	entry_size = hfsplus_fill_cat_thread(sb, &entry,
+		S_ISDIR(inode->i_mode) ?
 			HFSPLUS_FOLDER_THREAD : HFSPLUS_FILE_THREAD,
-			dir->i_ino, str);
+		dir->i_ino, str);
 	err = hfs_brec_find(&fd);
 	if (err != -ENOENT) {
 		if (!err)
@@ -227,7 +244,8 @@
 
 	dir->i_size++;
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dir);
+	hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
+
 	hfs_find_exit(&fd);
 	return 0;
 
@@ -249,7 +267,8 @@
 	int err, off;
 	u16 type;
 
-	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
+	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n",
+		str ? str->name : NULL, cnid);
 	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 
 	if (!str) {
@@ -260,11 +279,15 @@
 		if (err)
 			goto out;
 
-		off = fd.entryoffset + offsetof(struct hfsplus_cat_thread, nodeName);
+		off = fd.entryoffset +
+			offsetof(struct hfsplus_cat_thread, nodeName);
 		fd.search_key->cat.parent = cpu_to_be32(dir->i_ino);
-		hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.length, off, 2);
+		hfs_bnode_read(fd.bnode,
+			&fd.search_key->cat.name.length, off, 2);
 		len = be16_to_cpu(fd.search_key->cat.name.length) * 2;
-		hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.unicode, off + 2, len);
+		hfs_bnode_read(fd.bnode,
+			&fd.search_key->cat.name.unicode,
+			off + 2, len);
 		fd.search_key->key_len = cpu_to_be16(6 + len);
 	} else
 		hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
@@ -281,7 +304,8 @@
 		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_DATA);
 #endif
 
-		off = fd.entryoffset + offsetof(struct hfsplus_cat_file, rsrc_fork);
+		off = fd.entryoffset +
+			offsetof(struct hfsplus_cat_file, rsrc_fork);
 		hfs_bnode_read(fd.bnode, &fork, off, sizeof(fork));
 		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
 	}
@@ -308,7 +332,7 @@
 
 	dir->i_size--;
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dir);
+	hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
 out:
 	hfs_find_exit(&fd);
 
@@ -325,7 +349,8 @@
 	int entry_size, type;
 	int err = 0;
 
-	dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name,
+	dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n",
+		cnid, src_dir->i_ino, src_name->name,
 		dst_dir->i_ino, dst_name->name);
 	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd);
 	dst_fd = src_fd;
@@ -353,7 +378,6 @@
 		goto out;
 	dst_dir->i_size++;
 	dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dst_dir);
 
 	/* finally remove the old entry */
 	hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
@@ -365,7 +389,6 @@
 		goto out;
 	src_dir->i_size--;
 	src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(src_dir);
 
 	/* remove old thread entry */
 	hfsplus_cat_build_key(sb, src_fd.search_key, cnid, NULL);
@@ -379,7 +402,8 @@
 
 	/* create new thread entry */
 	hfsplus_cat_build_key(sb, dst_fd.search_key, cnid, NULL);
-	entry_size = hfsplus_fill_cat_thread(sb, &entry, type, dst_dir->i_ino, dst_name);
+	entry_size = hfsplus_fill_cat_thread(sb, &entry, type,
+		dst_dir->i_ino, dst_name);
 	err = hfs_brec_find(&dst_fd);
 	if (err != -ENOENT) {
 		if (!err)
@@ -387,6 +411,9 @@
 		goto out;
 	}
 	err = hfs_brec_insert(&dst_fd, &entry, entry_size);
+
+	hfsplus_mark_inode_dirty(dst_dir, HFSPLUS_I_CAT_DIRTY);
+	hfsplus_mark_inode_dirty(src_dir, HFSPLUS_I_CAT_DIRTY);
 out:
 	hfs_bnode_put(dst_fd.bnode);
 	hfs_find_exit(&src_fd);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 9d59c05..f896dc84 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -37,7 +37,7 @@
 
 	sb = dir->i_sb;
 
-	dentry->d_op = &hfsplus_dentry_operations;
+	d_set_d_op(dentry, &hfsplus_dentry_operations);
 	dentry->d_fsdata = NULL;
 	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 	hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
@@ -66,11 +66,17 @@
 			goto fail;
 		}
 		cnid = be32_to_cpu(entry.file.id);
-		if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
-		    entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
-		    (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->create_date ||
-		     entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode)->create_date) &&
-		    HFSPLUS_SB(sb)->hidden_dir) {
+		if (entry.file.user_info.fdType ==
+				cpu_to_be32(HFSP_HARDLINK_TYPE) &&
+				entry.file.user_info.fdCreator ==
+				cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
+				(entry.file.create_date ==
+					HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->
+						create_date ||
+				entry.file.create_date ==
+					HFSPLUS_I(sb->s_root->d_inode)->
+						create_date) &&
+				HFSPLUS_SB(sb)->hidden_dir) {
 			struct qstr str;
 			char name[32];
 
@@ -83,11 +89,13 @@
 				linkid = 0;
 			} else {
 				dentry->d_fsdata = (void *)(unsigned long)cnid;
-				linkid = be32_to_cpu(entry.file.permissions.dev);
+				linkid =
+					be32_to_cpu(entry.file.permissions.dev);
 				str.len = sprintf(name, "iNode%d", linkid);
 				str.name = name;
 				hfsplus_cat_build_key(sb, fd.search_key,
-					HFSPLUS_SB(sb)->hidden_dir->i_ino, &str);
+					HFSPLUS_SB(sb)->hidden_dir->i_ino,
+					&str);
 				goto again;
 			}
 		} else if (!dentry->d_fsdata)
@@ -139,7 +147,8 @@
 		filp->f_pos++;
 		/* fall through */
 	case 1:
-		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+			fd.entrylength);
 		if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
 			printk(KERN_ERR "hfs: bad catalog folder thread\n");
 			err = -EIO;
@@ -169,14 +178,16 @@
 			err = -EIO;
 			goto out;
 		}
-		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+			fd.entrylength);
 		type = be16_to_cpu(entry.type);
 		len = HFSPLUS_MAX_STRLEN;
 		err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len);
 		if (err)
 			goto out;
 		if (type == HFSPLUS_FOLDER) {
-			if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
+			if (fd.entrylength <
+					sizeof(struct hfsplus_cat_folder)) {
 				printk(KERN_ERR "hfs: small dir entry\n");
 				err = -EIO;
 				goto out;
@@ -202,7 +213,7 @@
 			err = -EIO;
 			goto out;
 		}
-	next:
+next:
 		filp->f_pos++;
 		if (filp->f_pos >= inode->i_size)
 			goto out;
@@ -273,7 +284,8 @@
 		HFSPLUS_I(inode)->linkid = id;
 		cnid = sbi->next_cnid++;
 		src_dentry->d_fsdata = (void *)(unsigned long)cnid;
-		res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode);
+		res = hfsplus_create_cat(cnid, src_dir,
+			&src_dentry->d_name, inode);
 		if (res)
 			/* panic? */
 			goto out;
@@ -485,6 +497,7 @@
 };
 
 const struct file_operations hfsplus_dir_operations = {
+	.fsync		= hfsplus_file_fsync,
 	.read		= generic_read_dir,
 	.readdir	= hfsplus_readdir,
 	.unlocked_ioctl = hfsplus_ioctl,
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 0c9cb18..52a0bca 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -83,7 +83,8 @@
 	return be32_to_cpu(ext->start_block) + be32_to_cpu(ext->block_count);
 }
 
-static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
+static void __hfsplus_ext_write_extent(struct inode *inode,
+		struct hfs_find_data *fd)
 {
 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	int res;
@@ -95,24 +96,32 @@
 				HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
 
 	res = hfs_brec_find(fd);
-	if (hip->flags & HFSPLUS_FLG_EXT_NEW) {
+	if (hip->extent_state & HFSPLUS_EXT_NEW) {
 		if (res != -ENOENT)
 			return;
 		hfs_brec_insert(fd, hip->cached_extents,
 				sizeof(hfsplus_extent_rec));
-		hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+		hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
 	} else {
 		if (res)
 			return;
 		hfs_bnode_write(fd->bnode, hip->cached_extents,
 				fd->entryoffset, fd->entrylength);
-		hip->flags &= ~HFSPLUS_FLG_EXT_DIRTY;
+		hip->extent_state &= ~HFSPLUS_EXT_DIRTY;
 	}
+
+	/*
+	 * We can't just use hfsplus_mark_inode_dirty here, because we
+	 * also get called from hfsplus_write_inode, which should not
+	 * redirty the inode.  Instead the callers have to be careful
+	 * to explicily mark the inode dirty, too.
+	 */
+	set_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags);
 }
 
 static void hfsplus_ext_write_extent_locked(struct inode *inode)
 {
-	if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) {
+	if (HFSPLUS_I(inode)->extent_state & HFSPLUS_EXT_DIRTY) {
 		struct hfs_find_data fd;
 
 		hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd);
@@ -144,18 +153,20 @@
 		return -ENOENT;
 	if (fd->entrylength != sizeof(hfsplus_extent_rec))
 		return -EIO;
-	hfs_bnode_read(fd->bnode, extent, fd->entryoffset, sizeof(hfsplus_extent_rec));
+	hfs_bnode_read(fd->bnode, extent, fd->entryoffset,
+		sizeof(hfsplus_extent_rec));
 	return 0;
 }
 
-static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block)
+static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd,
+		struct inode *inode, u32 block)
 {
 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	int res;
 
 	WARN_ON(!mutex_is_locked(&hip->extents_lock));
 
-	if (hip->flags & HFSPLUS_FLG_EXT_DIRTY)
+	if (hip->extent_state & HFSPLUS_EXT_DIRTY)
 		__hfsplus_ext_write_extent(inode, fd);
 
 	res = __hfsplus_ext_read_extent(fd, hip->cached_extents, inode->i_ino,
@@ -164,10 +175,11 @@
 						HFSPLUS_TYPE_DATA);
 	if (!res) {
 		hip->cached_start = be32_to_cpu(fd->key->ext.start_block);
-		hip->cached_blocks = hfsplus_ext_block_count(hip->cached_extents);
+		hip->cached_blocks =
+			hfsplus_ext_block_count(hip->cached_extents);
 	} else {
 		hip->cached_start = hip->cached_blocks = 0;
-		hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+		hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
 	}
 	return res;
 }
@@ -197,6 +209,7 @@
 	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
 	int res = -EIO;
 	u32 ablock, dblock, mask;
+	int was_dirty = 0;
 	int shift;
 
 	/* Convert inode block to disk allocation block */
@@ -223,27 +236,37 @@
 		return -EIO;
 
 	mutex_lock(&hip->extents_lock);
+
+	/*
+	 * hfsplus_ext_read_extent will write out a cached extent into
+	 * the extents btree.  In that case we may have to mark the inode
+	 * dirty even for a pure read of an extent here.
+	 */
+	was_dirty = (hip->extent_state & HFSPLUS_EXT_DIRTY);
 	res = hfsplus_ext_read_extent(inode, ablock);
-	if (!res) {
-		dblock = hfsplus_ext_find_block(hip->cached_extents,
-						ablock - hip->cached_start);
-	} else {
+	if (res) {
 		mutex_unlock(&hip->extents_lock);
 		return -EIO;
 	}
+	dblock = hfsplus_ext_find_block(hip->cached_extents,
+					ablock - hip->cached_start);
 	mutex_unlock(&hip->extents_lock);
 
 done:
-	dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock);
+	dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n",
+		inode->i_ino, (long long)iblock, dblock);
 	mask = (1 << sbi->fs_shift) - 1;
-	map_bh(bh_result, sb, (dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask));
+	map_bh(bh_result, sb,
+		(dblock << sbi->fs_shift) + sbi->blockoffset +
+			(iblock & mask));
 	if (create) {
 		set_buffer_new(bh_result);
 		hip->phys_size += sb->s_blocksize;
 		hip->fs_blocks++;
 		inode_add_bytes(inode, sb->s_blocksize);
-		mark_inode_dirty(inode);
 	}
+	if (create || was_dirty)
+		mark_inode_dirty(inode);
 	return 0;
 }
 
@@ -326,7 +349,8 @@
 	}
 }
 
-int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw *fork, int type)
+int hfsplus_free_fork(struct super_block *sb, u32 cnid,
+		struct hfsplus_fork_raw *fork, int type)
 {
 	struct hfs_find_data fd;
 	hfsplus_extent_rec ext_entry;
@@ -373,12 +397,13 @@
 	u32 start, len, goal;
 	int res;
 
-	if (sbi->alloc_file->i_size * 8 <
-	    sbi->total_blocks - sbi->free_blocks + 8) {
-		// extend alloc file
-		printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n",
-				sbi->alloc_file->i_size * 8,
-				sbi->total_blocks, sbi->free_blocks);
+	if (sbi->total_blocks - sbi->free_blocks + 8 >
+			sbi->alloc_file->i_size * 8) {
+		/* extend alloc file */
+		printk(KERN_ERR "hfs: extend alloc file! "
+				"(%llu,%u,%u)\n",
+			sbi->alloc_file->i_size * 8,
+			sbi->total_blocks, sbi->free_blocks);
 		return -ENOSPC;
 	}
 
@@ -429,7 +454,7 @@
 					 start, len);
 		if (!res) {
 			hfsplus_dump_extent(hip->cached_extents);
-			hip->flags |= HFSPLUS_FLG_EXT_DIRTY;
+			hip->extent_state |= HFSPLUS_EXT_DIRTY;
 			hip->cached_blocks += len;
 		} else if (res == -ENOSPC)
 			goto insert_extent;
@@ -438,7 +463,7 @@
 	mutex_unlock(&hip->extents_lock);
 	if (!res) {
 		hip->alloc_blocks += len;
-		mark_inode_dirty(inode);
+		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ALLOC_DIRTY);
 	}
 	return res;
 
@@ -450,7 +475,7 @@
 	hip->cached_extents[0].start_block = cpu_to_be32(start);
 	hip->cached_extents[0].block_count = cpu_to_be32(len);
 	hfsplus_dump_extent(hip->cached_extents);
-	hip->flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW;
+	hip->extent_state |= HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW;
 	hip->cached_start = hip->alloc_blocks;
 	hip->cached_blocks = len;
 
@@ -466,8 +491,9 @@
 	u32 alloc_cnt, blk_cnt, start;
 	int res;
 
-	dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n",
-		inode->i_ino, (long long)hip->phys_size, inode->i_size);
+	dprint(DBG_INODE, "truncate: %lu, %llu -> %llu\n",
+		inode->i_ino, (long long)hip->phys_size,
+		inode->i_size);
 
 	if (inode->i_size > hip->phys_size) {
 		struct address_space *mapping = inode->i_mapping;
@@ -481,7 +507,8 @@
 						&page, &fsdata);
 		if (res)
 			return;
-		res = pagecache_write_end(NULL, mapping, size, 0, 0, page, fsdata);
+		res = pagecache_write_end(NULL, mapping, size,
+			0, 0, page, fsdata);
 		if (res < 0)
 			return;
 		mark_inode_dirty(inode);
@@ -513,12 +540,12 @@
 				     alloc_cnt - start, alloc_cnt - blk_cnt);
 		hfsplus_dump_extent(hip->cached_extents);
 		if (blk_cnt > start) {
-			hip->flags |= HFSPLUS_FLG_EXT_DIRTY;
+			hip->extent_state |= HFSPLUS_EXT_DIRTY;
 			break;
 		}
 		alloc_cnt = start;
 		hip->cached_start = hip->cached_blocks = 0;
-		hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
+		hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
 		hfs_brec_remove(&fd);
 	}
 	hfs_find_exit(&fd);
@@ -527,7 +554,8 @@
 	hip->alloc_blocks = blk_cnt;
 out:
 	hip->phys_size = inode->i_size;
-	hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >>
+		sb->s_blocksize_bits;
 	inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
-	mark_inode_dirty(inode);
+	hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ALLOC_DIRTY);
 }
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index cb3653e..d685752 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -23,13 +23,16 @@
 #define DBG_EXTENT	0x00000020
 #define DBG_BITMAP	0x00000040
 
-//#define DBG_MASK	(DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
-//#define DBG_MASK	(DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE)
-//#define DBG_MASK	(DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT)
+#if 0
+#define DBG_MASK	(DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
+#define DBG_MASK	(DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE)
+#define DBG_MASK	(DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT)
+#endif
 #define DBG_MASK	(0)
 
 #define dprint(flg, fmt, args...) \
-	if (flg & DBG_MASK) printk(fmt , ## args)
+	if (flg & DBG_MASK) \
+		printk(fmt , ## args)
 
 /* Runtime config options */
 #define HFSPLUS_DEF_CR_TYPE    0x3F3F3F3F  /* '????' */
@@ -37,7 +40,8 @@
 #define HFSPLUS_TYPE_DATA 0x00
 #define HFSPLUS_TYPE_RSRC 0xFF
 
-typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *);
+typedef int (*btree_keycmp)(const hfsplus_btree_key *,
+		const hfsplus_btree_key *);
 
 #define NODE_HASH_SIZE	256
 
@@ -61,7 +65,6 @@
 	unsigned int max_key_len;
 	unsigned int depth;
 
-	//unsigned int map1_size, map_size;
 	struct mutex tree_lock;
 
 	unsigned int pages_per_bnode;
@@ -107,8 +110,8 @@
 struct hfs_btree;
 
 struct hfsplus_sb_info {
-	struct buffer_head *s_vhbh;
 	struct hfsplus_vh *s_vhdr;
+	struct hfsplus_vh *s_backup_vhdr;
 	struct hfs_btree *ext_tree;
 	struct hfs_btree *cat_tree;
 	struct hfs_btree *attr_tree;
@@ -118,7 +121,8 @@
 
 	/* Runtime variables */
 	u32 blockoffset;
-	u32 sect_count;
+	sector_t part_start;
+	sector_t sect_count;
 	int fs_shift;
 
 	/* immutable data from the volume header */
@@ -155,6 +159,12 @@
 #define HFSPLUS_SB_FORCE	2
 #define HFSPLUS_SB_HFSX		3
 #define HFSPLUS_SB_CASEFOLD	4
+#define HFSPLUS_SB_NOBARRIER	5
+
+static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
 
 
 struct hfsplus_inode_info {
@@ -170,7 +180,7 @@
 	u32 cached_blocks;
 	hfsplus_extent_rec first_extents;
 	hfsplus_extent_rec cached_extents;
-	unsigned long flags;
+	unsigned int extent_state;
 	struct mutex extents_lock;
 
 	/*
@@ -185,6 +195,11 @@
 	u32 linkid;
 
 	/*
+	 * Accessed using atomic bitops.
+	 */
+	unsigned long flags;
+
+	/*
 	 * Protected by i_mutex.
 	 */
 	sector_t fs_blocks;
@@ -195,12 +210,34 @@
 	struct inode vfs_inode;
 };
 
-#define HFSPLUS_FLG_RSRC	0x0001
-#define HFSPLUS_FLG_EXT_DIRTY	0x0002
-#define HFSPLUS_FLG_EXT_NEW	0x0004
+#define HFSPLUS_EXT_DIRTY	0x0001
+#define HFSPLUS_EXT_NEW		0x0002
 
-#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC))
-#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC)
+#define HFSPLUS_I_RSRC		0	/* represents a resource fork */
+#define HFSPLUS_I_CAT_DIRTY	1	/* has changes in the catalog tree */
+#define HFSPLUS_I_EXT_DIRTY	2	/* has changes in the extent tree */
+#define HFSPLUS_I_ALLOC_DIRTY	3	/* has changes in the allocation file */
+
+#define HFSPLUS_IS_RSRC(inode) \
+	test_bit(HFSPLUS_I_RSRC, &HFSPLUS_I(inode)->flags)
+
+static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
+{
+	return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
+}
+
+/*
+ * Mark an inode dirty, and also mark the btree in which the
+ * specific type of metadata is stored.
+ * For data or metadata that gets written back by into the catalog btree
+ * by hfsplus_write_inode a plain mark_inode_dirty call is enough.
+ */
+static inline void hfsplus_mark_inode_dirty(struct inode *inode,
+		unsigned int flag)
+{
+	set_bit(flag, &HFSPLUS_I(inode)->flags);
+	mark_inode_dirty(inode);
+}
 
 struct hfs_find_data {
 	/* filled by caller */
@@ -318,9 +355,12 @@
 int hfs_brec_goto(struct hfs_find_data *, int);
 
 /* catalog.c */
-int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
-int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
-void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *);
+int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *,
+		const hfsplus_btree_key *);
+int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *,
+		const hfsplus_btree_key *);
+void hfsplus_cat_build_key(struct super_block *sb,
+		hfsplus_btree_key *, u32, struct qstr *);
 int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
 int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
 int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
@@ -336,7 +376,8 @@
 int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
 void hfsplus_ext_write_extent(struct inode *);
 int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
-int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
+int hfsplus_free_fork(struct super_block *, u32,
+		struct hfsplus_fork_raw *, int);
 int hfsplus_file_extend(struct inode *);
 void hfsplus_file_truncate(struct inode *);
 
@@ -351,6 +392,7 @@
 int hfsplus_cat_write_inode(struct inode *);
 struct inode *hfsplus_new_inode(struct super_block *, int);
 void hfsplus_delete_inode(struct inode *);
+int hfsplus_file_fsync(struct file *file, int datasync);
 
 /* ioctl.c */
 long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
@@ -362,6 +404,7 @@
 
 /* options.c */
 int hfsplus_parse_options(char *, struct hfsplus_sb_info *);
+int hfsplus_parse_options_remount(char *input, int *force);
 void hfsplus_fill_defaults(struct hfsplus_sb_info *);
 int hfsplus_show_options(struct seq_file *, struct vfsmount *);
 
@@ -375,45 +418,26 @@
 extern u16 hfsplus_compose_table[];
 
 /* unicode.c */
-int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
-int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
-int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
-int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
-int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str);
-int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2);
+int hfsplus_strcasecmp(const struct hfsplus_unistr *,
+		const struct hfsplus_unistr *);
+int hfsplus_strcmp(const struct hfsplus_unistr *,
+		const struct hfsplus_unistr *);
+int hfsplus_uni2asc(struct super_block *,
+		const struct hfsplus_unistr *, char *, int *);
+int hfsplus_asc2uni(struct super_block *,
+		struct hfsplus_unistr *, const char *, int);
+int hfsplus_hash_dentry(const struct dentry *dentry,
+		const struct inode *inode, struct qstr *str);
+int hfsplus_compare_dentry(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
 
 /* wrapper.c */
 int hfsplus_read_wrapper(struct super_block *);
-
 int hfs_part_find(struct super_block *, sector_t *, sector_t *);
-
-/* access macros */
-static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
-{
-	return sb->s_fs_info;
-}
-
-static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
-{
-	return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
-}
-
-#define sb_bread512(sb, sec, data) ({			\
-	struct buffer_head *__bh;			\
-	sector_t __block;				\
-	loff_t __start;					\
-	int __offset;					\
-							\
-	__start = (loff_t)(sec) << HFSPLUS_SECTOR_SHIFT;\
-	__block = __start >> (sb)->s_blocksize_bits;	\
-	__offset = __start & ((sb)->s_blocksize - 1);	\
-	__bh = sb_bread((sb), __block);			\
-	if (likely(__bh != NULL))			\
-		data = (void *)(__bh->b_data + __offset);\
-	else						\
-		data = NULL;				\
-	__bh;						\
-})
+int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
+		void *data, int rw);
 
 /* time macros */
 #define __hfsp_mt2ut(t)		(be32_to_cpu(t) - 2082844800U)
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 6892899..927cdd6 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -36,7 +36,8 @@
 #define HFSP_WRAPOFF_EMBEDSIG     0x7C
 #define HFSP_WRAPOFF_EMBEDEXT     0x7E
 
-#define HFSP_HIDDENDIR_NAME	"\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80HFS+ Private Data"
+#define HFSP_HIDDENDIR_NAME \
+	"\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80HFS+ Private Data"
 
 #define HFSP_HARDLINK_TYPE	0x686c6e6b	/* 'hlnk' */
 #define HFSP_HFSPLUS_CREATOR	0x6866732b	/* 'hfs+' */
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 8afd7e8..a8df651 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -8,6 +8,7 @@
  * Inode handling routines
  */
 
+#include <linux/blkdev.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -77,7 +78,8 @@
 	if (!tree)
 		return 0;
 	if (tree->node_size >= PAGE_CACHE_SIZE) {
-		nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT);
+		nidx = page->index >>
+			(tree->node_size_shift - PAGE_CACHE_SHIFT);
 		spin_lock(&tree->hash_lock);
 		node = hfs_bnode_findhash(tree, nidx);
 		if (!node)
@@ -90,7 +92,8 @@
 		}
 		spin_unlock(&tree->hash_lock);
 	} else {
-		nidx = page->index << (PAGE_CACHE_SHIFT - tree->node_size_shift);
+		nidx = page->index <<
+			(PAGE_CACHE_SHIFT - tree->node_size_shift);
 		i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift);
 		spin_lock(&tree->hash_lock);
 		do {
@@ -166,8 +169,8 @@
 	.d_compare    = hfsplus_compare_dentry,
 };
 
-static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry,
-					  struct nameidata *nd)
+static struct dentry *hfsplus_file_lookup(struct inode *dir,
+		struct dentry *dentry, struct nameidata *nd)
 {
 	struct hfs_find_data fd;
 	struct super_block *sb = dir->i_sb;
@@ -190,7 +193,9 @@
 	inode->i_ino = dir->i_ino;
 	INIT_LIST_HEAD(&hip->open_dir_list);
 	mutex_init(&hip->extents_lock);
-	hip->flags = HFSPLUS_FLG_RSRC;
+	hip->extent_state = 0;
+	hip->flags = 0;
+	set_bit(HFSPLUS_I_RSRC, &hip->flags);
 
 	hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 	err = hfsplus_find_cat(sb, dir->i_ino, &fd);
@@ -219,7 +224,8 @@
 	return NULL;
 }
 
-static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir)
+static void hfsplus_get_perms(struct inode *inode,
+		struct hfsplus_perm *perms, int dir)
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
 	u16 mode;
@@ -302,29 +308,41 @@
 	return 0;
 }
 
-static int hfsplus_file_fsync(struct file *filp, int datasync)
+int hfsplus_file_fsync(struct file *file, int datasync)
 {
-	struct inode *inode = filp->f_mapping->host;
-	struct super_block * sb;
-	int ret, err;
+	struct inode *inode = file->f_mapping->host;
+	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
+	int error = 0, error2;
 
-	/* sync the inode to buffers */
-	ret = write_inode_now(inode, 0);
+	/*
+	 * Sync inode metadata into the catalog and extent trees.
+	 */
+	sync_inode_metadata(inode, 1);
 
-	/* sync the superblock to buffers */
-	sb = inode->i_sb;
-	if (sb->s_dirt) {
-		if (!(sb->s_flags & MS_RDONLY))
-			hfsplus_sync_fs(sb, 1);
-		else
-			sb->s_dirt = 0;
+	/*
+	 * And explicitly write out the btrees.
+	 */
+	if (test_and_clear_bit(HFSPLUS_I_CAT_DIRTY, &hip->flags))
+		error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
+
+	if (test_and_clear_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags)) {
+		error2 =
+			filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
+		if (!error)
+			error = error2;
 	}
 
-	/* .. finally sync the buffers to disk */
-	err = sync_blockdev(sb->s_bdev);
-	if (!ret)
-		ret = err;
-	return ret;
+	if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags)) {
+		error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
+		if (!error)
+			error = error2;
+	}
+
+	if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+
+	return error;
 }
 
 static const struct inode_operations hfsplus_file_inode_operations = {
@@ -337,7 +355,7 @@
 };
 
 static const struct file_operations hfsplus_file_operations = {
-	.llseek 	= generic_file_llseek,
+	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
 	.write		= do_sync_write,
@@ -370,6 +388,7 @@
 	INIT_LIST_HEAD(&hip->open_dir_list);
 	mutex_init(&hip->extents_lock);
 	atomic_set(&hip->opencnt, 0);
+	hip->extent_state = 0;
 	hip->flags = 0;
 	memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
 	memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
@@ -457,7 +476,8 @@
 	}
 }
 
-void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
+void hfsplus_inode_write_fork(struct inode *inode,
+		struct hfsplus_fork_raw *fork)
 {
 	memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents,
 	       sizeof(hfsplus_extent_rec));
@@ -499,13 +519,14 @@
 		hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
 					sizeof(struct hfsplus_cat_file));
 
-		hfsplus_inode_read_fork(inode, HFSPLUS_IS_DATA(inode) ?
-					&file->data_fork : &file->rsrc_fork);
+		hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
+					&file->rsrc_fork : &file->data_fork);
 		hfsplus_get_perms(inode, &file->permissions, 0);
 		inode->i_nlink = 1;
 		if (S_ISREG(inode->i_mode)) {
 			if (file->permissions.dev)
-				inode->i_nlink = be32_to_cpu(file->permissions.dev);
+				inode->i_nlink =
+					be32_to_cpu(file->permissions.dev);
 			inode->i_op = &hfsplus_file_inode_operations;
 			inode->i_fop = &hfsplus_file_operations;
 			inode->i_mapping->a_ops = &hfsplus_aops;
@@ -578,7 +599,9 @@
 					sizeof(struct hfsplus_cat_file));
 		hfsplus_inode_write_fork(inode, &file->data_fork);
 		hfsplus_cat_set_perms(inode, &file->permissions);
-		if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
+		if (HFSPLUS_FLG_IMMUTABLE &
+				(file->permissions.rootflags |
+					file->permissions.userflags))
 			file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
 		else
 			file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED);
@@ -588,6 +611,8 @@
 		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
 					 sizeof(struct hfsplus_cat_file));
 	}
+
+	set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
 out:
 	hfs_find_exit(&fd);
 	return 0;
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index 40a85a3d..508ce66 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -28,7 +28,7 @@
 
 	if (inode->i_flags & S_IMMUTABLE)
 		flags |= FS_IMMUTABLE_FL;
-	if (inode->i_flags |= S_APPEND)
+	if (inode->i_flags & S_APPEND)
 		flags |= FS_APPEND_FL;
 	if (hip->userflags & HFSPLUS_FLG_NODUMP)
 		flags |= FS_NODUMP_FL;
@@ -147,9 +147,11 @@
 			res = -ERANGE;
 	} else
 		res = -EOPNOTSUPP;
-	if (!res)
+	if (!res) {
 		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
 				sizeof(struct hfsplus_cat_file));
+		hfsplus_mark_inode_dirty(inode, HFSPLUS_I_CAT_DIRTY);
+	}
 out:
 	hfs_find_exit(&fd);
 	return res;
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index f9ab276..bb62a5882 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -23,6 +23,7 @@
 	opt_umask, opt_uid, opt_gid,
 	opt_part, opt_session, opt_nls,
 	opt_nodecompose, opt_decompose,
+	opt_barrier, opt_nobarrier,
 	opt_force, opt_err
 };
 
@@ -37,6 +38,8 @@
 	{ opt_nls, "nls=%s" },
 	{ opt_decompose, "decompose" },
 	{ opt_nodecompose, "nodecompose" },
+	{ opt_barrier, "barrier" },
+	{ opt_nobarrier, "nobarrier" },
 	{ opt_force, "force" },
 	{ opt_err, NULL }
 };
@@ -65,6 +68,32 @@
 	return 0;
 }
 
+int hfsplus_parse_options_remount(char *input, int *force)
+{
+	char *p;
+	substring_t args[MAX_OPT_ARGS];
+	int token;
+
+	if (!input)
+		return 0;
+
+	while ((p = strsep(&input, ",")) != NULL) {
+		if (!*p)
+			continue;
+
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case opt_force:
+			*force = 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 1;
+}
+
 /* Parse options from mount. Returns 0 on failure */
 /* input is the options passed to mount() as a string */
 int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
@@ -136,7 +165,9 @@
 			if (p)
 				sbi->nls = load_nls(p);
 			if (!sbi->nls) {
-				printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p);
+				printk(KERN_ERR "hfs: unable to load "
+						"nls mapping \"%s\"\n",
+					p);
 				kfree(p);
 				return 0;
 			}
@@ -148,6 +179,12 @@
 		case opt_nodecompose:
 			set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
 			break;
+		case opt_barrier:
+			clear_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags);
+			break;
+		case opt_nobarrier:
+			set_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags);
+			break;
 		case opt_force:
 			set_bit(HFSPLUS_SB_FORCE, &sbi->flags);
 			break;
@@ -177,7 +214,8 @@
 		seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator);
 	if (sbi->type != HFSPLUS_DEF_CR_TYPE)
 		seq_printf(seq, ",type=%.4s", (char *)&sbi->type);
-	seq_printf(seq, ",umask=%o,uid=%u,gid=%u", sbi->umask, sbi->uid, sbi->gid);
+	seq_printf(seq, ",umask=%o,uid=%u,gid=%u", sbi->umask,
+		sbi->uid, sbi->gid);
 	if (sbi->part >= 0)
 		seq_printf(seq, ",part=%u", sbi->part);
 	if (sbi->session >= 0)
@@ -186,5 +224,7 @@
 		seq_printf(seq, ",nls=%s", sbi->nls->charset);
 	if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags))
 		seq_printf(seq, ",nodecompose");
+	if (test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+		seq_printf(seq, ",nobarrier");
 	return 0;
 }
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c
index 208b16c..d66ad11 100644
--- a/fs/hfsplus/part_tbl.c
+++ b/fs/hfsplus/part_tbl.c
@@ -2,7 +2,8 @@
  * linux/fs/hfsplus/part_tbl.c
  *
  * Copyright (C) 1996-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU General Public License.
+ * This file may be distributed under the terms of
+ * the GNU General Public License.
  *
  * Original code to handle the new style Mac partition table based on
  * a patch contributed by Holger Schemel (aeglos@valinor.owl.de).
@@ -13,6 +14,7 @@
  *
  */
 
+#include <linux/slab.h>
 #include "hfsplus_fs.h"
 
 /* offsets to various blocks */
@@ -58,77 +60,94 @@
  */
 struct old_pmap {
 	__be16		pdSig;	/* Signature bytes */
-	struct 	old_pmap_entry {
+	struct old_pmap_entry {
 		__be32	pdStart;
 		__be32	pdSize;
 		__be32	pdFSID;
 	}	pdEntry[42];
 } __packed;
 
-/*
- * hfs_part_find()
- *
- * Parse the partition map looking for the
- * start and length of the 'part'th HFS partition.
- */
-int hfs_part_find(struct super_block *sb,
-		  sector_t *part_start, sector_t *part_size)
+static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm,
+		sector_t *part_start, sector_t *part_size)
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
-	struct buffer_head *bh;
-	__be16 *data;
-	int i, size, res;
+	int i;
 
-	res = -ENOENT;
-	bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data);
-	if (!bh)
-		return -EIO;
+	for (i = 0; i < 42; i++) {
+		struct old_pmap_entry *p = &pm->pdEntry[i];
 
-	switch (be16_to_cpu(*data)) {
-	case HFS_OLD_PMAP_MAGIC:
-	  {
-		struct old_pmap *pm;
-		struct old_pmap_entry *p;
-
-		pm = (struct old_pmap *)bh->b_data;
-		p = pm->pdEntry;
-		size = 42;
-		for (i = 0; i < size; p++, i++) {
-			if (p->pdStart && p->pdSize &&
-			    p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
-			    (sbi->part < 0 || sbi->part == i)) {
-				*part_start += be32_to_cpu(p->pdStart);
-				*part_size = be32_to_cpu(p->pdSize);
-				res = 0;
-			}
+		if (p->pdStart && p->pdSize &&
+		    p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
+		    (sbi->part < 0 || sbi->part == i)) {
+			*part_start += be32_to_cpu(p->pdStart);
+			*part_size = be32_to_cpu(p->pdSize);
+			return 0;
 		}
-		break;
-	  }
-	case HFS_NEW_PMAP_MAGIC:
-	  {
-		struct new_pmap *pm;
-
-		pm = (struct new_pmap *)bh->b_data;
-		size = be32_to_cpu(pm->pmMapBlkCnt);
-		for (i = 0; i < size;) {
-			if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
-			    (sbi->part < 0 || sbi->part == i)) {
-				*part_start += be32_to_cpu(pm->pmPyPartStart);
-				*part_size = be32_to_cpu(pm->pmPartBlkCnt);
-				res = 0;
-				break;
-			}
-			brelse(bh);
-			bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm);
-			if (!bh)
-				return -EIO;
-			if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC))
-				break;
-		}
-		break;
-	  }
 	}
-	brelse(bh);
 
+	return -ENOENT;
+}
+
+static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
+		sector_t *part_start, sector_t *part_size)
+{
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+	int size = be32_to_cpu(pm->pmMapBlkCnt);
+	int res;
+	int i = 0;
+
+	do {
+		if (!memcmp(pm->pmPartType, "Apple_HFS", 9) &&
+		    (sbi->part < 0 || sbi->part == i)) {
+			*part_start += be32_to_cpu(pm->pmPyPartStart);
+			*part_size = be32_to_cpu(pm->pmPartBlkCnt);
+			return 0;
+		}
+
+		if (++i >= size)
+			return -ENOENT;
+
+		res = hfsplus_submit_bio(sb->s_bdev,
+					 *part_start + HFS_PMAP_BLK + i,
+					 pm, READ);
+		if (res)
+			return res;
+	} while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
+
+	return -ENOENT;
+}
+
+/*
+ * Parse the partition map looking for the start and length of a
+ * HFS/HFS+ partition.
+ */
+int hfs_part_find(struct super_block *sb,
+		sector_t *part_start, sector_t *part_size)
+{
+	void *data;
+	int res;
+
+	data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK,
+				 data, READ);
+	if (res)
+		return res;
+
+	switch (be16_to_cpu(*((__be16 *)data))) {
+	case HFS_OLD_PMAP_MAGIC:
+		res = hfs_parse_old_pmap(sb, data, part_start, part_size);
+		break;
+	case HFS_NEW_PMAP_MAGIC:
+		res = hfs_parse_new_pmap(sb, data, part_start, part_size);
+		break;
+	default:
+		res = -ENOENT;
+		break;
+	}
+
+	kfree(data);
 	return res;
 }
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 52cc746..6ee6ad2 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
+#include <linux/blkdev.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/vfs.h>
@@ -66,6 +67,7 @@
 	INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list);
 	mutex_init(&HFSPLUS_I(inode)->extents_lock);
 	HFSPLUS_I(inode)->flags = 0;
+	HFSPLUS_I(inode)->extent_state = 0;
 	HFSPLUS_I(inode)->rsrc_inode = NULL;
 	atomic_set(&HFSPLUS_I(inode)->opencnt, 0);
 
@@ -157,45 +159,65 @@
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct hfsplus_vh *vhdr = sbi->s_vhdr;
+	int write_backup = 0;
+	int error, error2;
+
+	if (!wait)
+		return 0;
 
 	dprint(DBG_SUPER, "hfsplus_write_super\n");
 
-	mutex_lock(&sbi->vh_mutex);
-	mutex_lock(&sbi->alloc_mutex);
 	sb->s_dirt = 0;
 
+	/*
+	 * Explicitly write out the special metadata inodes.
+	 *
+	 * While these special inodes are marked as hashed and written
+	 * out peridocically by the flusher threads we redirty them
+	 * during writeout of normal inodes, and thus the life lock
+	 * prevents us from getting the latest state to disk.
+	 */
+	error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
+	error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
+	if (!error)
+		error = error2;
+	error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
+	if (!error)
+		error = error2;
+
+	mutex_lock(&sbi->vh_mutex);
+	mutex_lock(&sbi->alloc_mutex);
 	vhdr->free_blocks = cpu_to_be32(sbi->free_blocks);
 	vhdr->next_cnid = cpu_to_be32(sbi->next_cnid);
 	vhdr->folder_count = cpu_to_be32(sbi->folder_count);
 	vhdr->file_count = cpu_to_be32(sbi->file_count);
 
-	mark_buffer_dirty(sbi->s_vhbh);
 	if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) {
-		if (sbi->sect_count) {
-			struct buffer_head *bh;
-			u32 block, offset;
-
-			block = sbi->blockoffset;
-			block += (sbi->sect_count - 2) >> (sb->s_blocksize_bits - 9);
-			offset = ((sbi->sect_count - 2) << 9) & (sb->s_blocksize - 1);
-			printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n",
-					  sbi->blockoffset, sbi->sect_count,
-					  block, offset);
-			bh = sb_bread(sb, block);
-			if (bh) {
-				vhdr = (struct hfsplus_vh *)(bh->b_data + offset);
-				if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) {
-					memcpy(vhdr, sbi->s_vhdr, sizeof(*vhdr));
-					mark_buffer_dirty(bh);
-					brelse(bh);
-				} else
-					printk(KERN_WARNING "hfs: backup not found!\n");
-			}
-		}
+		memcpy(sbi->s_backup_vhdr, sbi->s_vhdr, sizeof(*sbi->s_vhdr));
+		write_backup = 1;
 	}
+
+	error2 = hfsplus_submit_bio(sb->s_bdev,
+				   sbi->part_start + HFSPLUS_VOLHEAD_SECTOR,
+				   sbi->s_vhdr, WRITE_SYNC);
+	if (!error)
+		error = error2;
+	if (!write_backup)
+		goto out;
+
+	error2 = hfsplus_submit_bio(sb->s_bdev,
+				  sbi->part_start + sbi->sect_count - 2,
+				  sbi->s_backup_vhdr, WRITE_SYNC);
+	if (!error)
+		error2 = error;
+out:
 	mutex_unlock(&sbi->alloc_mutex);
 	mutex_unlock(&sbi->vh_mutex);
-	return 0;
+
+	if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+		blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
+
+	return error;
 }
 
 static void hfsplus_write_super(struct super_block *sb)
@@ -215,23 +237,22 @@
 	if (!sb->s_fs_info)
 		return;
 
-	if (sb->s_dirt)
-		hfsplus_write_super(sb);
 	if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) {
 		struct hfsplus_vh *vhdr = sbi->s_vhdr;
 
 		vhdr->modify_date = hfsp_now2mt();
 		vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT);
 		vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT);
-		mark_buffer_dirty(sbi->s_vhbh);
-		sync_dirty_buffer(sbi->s_vhbh);
+
+		hfsplus_sync_fs(sb, 1);
 	}
 
 	hfs_btree_close(sbi->cat_tree);
 	hfs_btree_close(sbi->ext_tree);
 	iput(sbi->alloc_file);
 	iput(sbi->hidden_dir);
-	brelse(sbi->s_vhbh);
+	kfree(sbi->s_vhdr);
+	kfree(sbi->s_backup_vhdr);
 	unload_nls(sbi->nls);
 	kfree(sb->s_fs_info);
 	sb->s_fs_info = NULL;
@@ -263,26 +284,31 @@
 		return 0;
 	if (!(*flags & MS_RDONLY)) {
 		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr;
-		struct hfsplus_sb_info sbi;
+		int force = 0;
 
-		memset(&sbi, 0, sizeof(struct hfsplus_sb_info));
-		sbi.nls = HFSPLUS_SB(sb)->nls;
-		if (!hfsplus_parse_options(data, &sbi))
+		if (!hfsplus_parse_options_remount(data, &force))
 			return -EINVAL;
 
 		if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
-			printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
-			       "running fsck.hfsplus is recommended.  leaving read-only.\n");
+			printk(KERN_WARNING "hfs: filesystem was "
+					"not cleanly unmounted, "
+					"running fsck.hfsplus is recommended.  "
+					"leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
-		} else if (test_bit(HFSPLUS_SB_FORCE, &sbi.flags)) {
+		} else if (force) {
 			/* nothing */
-		} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
-			printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
+		} else if (vhdr->attributes &
+				cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
+			printk(KERN_WARNING "hfs: filesystem is marked locked, "
+					"leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
-		} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
-			printk(KERN_WARNING "hfs: filesystem is marked journaled, leaving read-only.\n");
+		} else if (vhdr->attributes &
+				cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
+			printk(KERN_WARNING "hfs: filesystem is "
+					"marked journaled, "
+					"leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
 			*flags |= MS_RDONLY;
 		}
@@ -372,17 +398,22 @@
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 
 	if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
-		printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, "
-		       "running fsck.hfsplus is recommended.  mounting read-only.\n");
+		printk(KERN_WARNING "hfs: Filesystem was "
+				"not cleanly unmounted, "
+				"running fsck.hfsplus is recommended.  "
+				"mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	} else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) {
 		/* nothing */
 	} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
 		printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
-	} else if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) && !(sb->s_flags & MS_RDONLY)) {
-		printk(KERN_WARNING "hfs: write access to a journaled filesystem is not supported, "
-		       "use the force option at your own risk, mounting read-only.\n");
+	} else if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) &&
+			!(sb->s_flags & MS_RDONLY)) {
+		printk(KERN_WARNING "hfs: write access to "
+				"a journaled filesystem is not supported, "
+				"use the force option at your own risk, "
+				"mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
 	}
 
@@ -419,7 +450,7 @@
 		err = -ENOMEM;
 		goto cleanup;
 	}
-	sb->s_root->d_op = &hfsplus_dentry_operations;
+	d_set_d_op(sb->s_root, &hfsplus_dentry_operations);
 
 	str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
 	str.name = HFSP_HIDDENDIR_NAME;
@@ -449,19 +480,16 @@
 	be32_add_cpu(&vhdr->write_count, 1);
 	vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
 	vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
-	mark_buffer_dirty(sbi->s_vhbh);
-	sync_dirty_buffer(sbi->s_vhbh);
+	hfsplus_sync_fs(sb, 1);
 
 	if (!sbi->hidden_dir) {
-		printk(KERN_DEBUG "hfs: create hidden dir...\n");
-
 		mutex_lock(&sbi->vh_mutex);
 		sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
 		hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode,
 				   &str, sbi->hidden_dir);
 		mutex_unlock(&sbi->vh_mutex);
 
-		mark_inode_dirty(sbi->hidden_dir);
+		hfsplus_mark_inode_dirty(sbi->hidden_dir, HFSPLUS_I_CAT_DIRTY);
 	}
 out:
 	unload_nls(sbi->nls);
@@ -488,9 +516,17 @@
 	return i ? &i->vfs_inode : NULL;
 }
 
+static void hfsplus_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(hfsplus_inode_cachep, HFSPLUS_I(inode));
+}
+
 static void hfsplus_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode));
+	call_rcu(&inode->i_rcu, hfsplus_i_callback);
 }
 
 #define HFSPLUS_INODE_SIZE	sizeof(struct hfsplus_inode_info)
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index b66d67d..a3f0bfc 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -17,14 +17,14 @@
 /* Returns folded char, or 0 if ignorable */
 static inline u16 case_fold(u16 c)
 {
-        u16 tmp;
+	u16 tmp;
 
-        tmp = hfsplus_case_fold_table[c >> 8];
-        if (tmp)
-                tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
-        else
-                tmp = c;
-        return tmp;
+	tmp = hfsplus_case_fold_table[c >> 8];
+	if (tmp)
+		tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
+	else
+		tmp = c;
+	return tmp;
 }
 
 /* Compare unicode strings, return values like normal strcmp */
@@ -118,7 +118,9 @@
 	return NULL;
 }
 
-int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p)
+int hfsplus_uni2asc(struct super_block *sb,
+		const struct hfsplus_unistr *ustr,
+		char *astr, int *len_p)
 {
 	const hfsplus_unichr *ip;
 	struct nls_table *nls = HFSPLUS_SB(sb)->nls;
@@ -171,7 +173,8 @@
 				goto same;
 			c1 = be16_to_cpu(*ip);
 			if (likely(compose))
-				ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c1);
+				ce1 = hfsplus_compose_lookup(
+					hfsplus_compose_table, c1);
 			if (ce1)
 				break;
 			switch (c0) {
@@ -199,7 +202,8 @@
 		if (ce2) {
 			i = 1;
 			while (i < ustrlen) {
-				ce1 = hfsplus_compose_lookup(ce2, be16_to_cpu(ip[i]));
+				ce1 = hfsplus_compose_lookup(ce2,
+					be16_to_cpu(ip[i]));
 				if (!ce1)
 					break;
 				i++;
@@ -211,7 +215,7 @@
 				goto done;
 			}
 		}
-	same:
+same:
 		switch (c0) {
 		case 0:
 			cc = 0x2400;
@@ -222,7 +226,7 @@
 		default:
 			cc = c0;
 		}
-	done:
+done:
 		res = nls->uni2char(cc, op, len);
 		if (res < 0) {
 			if (res == -ENAMETOOLONG)
@@ -320,7 +324,8 @@
  * Composed unicode characters are decomposed and case-folding is performed
  * if the appropriate bits are (un)set on the superblock.
  */
-int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str)
+int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *str)
 {
 	struct super_block *sb = dentry->d_sb;
 	const char *astr;
@@ -363,9 +368,12 @@
  * Composed unicode characters are decomposed and case-folding is performed
  * if the appropriate bits are (un)set on the superblock.
  */
-int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2)
+int hfsplus_compare_dentry(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	struct super_block *sb = dentry->d_sb;
+	struct super_block *sb = parent->d_sb;
 	int casefold, decompose, size;
 	int dsize1, dsize2, len1, len2;
 	const u16 *dstr1, *dstr2;
@@ -375,10 +383,10 @@
 
 	casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
 	decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
-	astr1 = s1->name;
-	len1 = s1->len;
-	astr2 = s2->name;
-	len2 = s2->len;
+	astr1 = str;
+	len1 = len;
+	astr2 = name->name;
+	len2 = name->len;
 	dsize1 = dsize2 = 0;
 	dstr1 = dstr2 = NULL;
 
@@ -388,7 +396,9 @@
 			astr1 += size;
 			len1 -= size;
 
-			if (!decompose || !(dstr1 = decompose_unichar(c, &dsize1))) {
+			if (decompose)
+				dstr1 = decompose_unichar(c, &dsize1);
+			if (!decompose || !dstr1) {
 				c1 = c;
 				dstr1 = &c1;
 				dsize1 = 1;
@@ -400,7 +410,9 @@
 			astr2 += size;
 			len2 -= size;
 
-			if (!decompose || !(dstr2 = decompose_unichar(c, &dsize2))) {
+			if (decompose)
+				dstr2 = decompose_unichar(c, &dsize2);
+			if (!decompose || !dstr2) {
 				c2 = c;
 				dstr2 = &c2;
 				dsize2 = 1;
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 8972c20..1962317 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -24,6 +24,40 @@
 	u16 embed_count;
 };
 
+static void hfsplus_end_io_sync(struct bio *bio, int err)
+{
+	if (err)
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+	complete(bio->bi_private);
+}
+
+int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
+		void *data, int rw)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+	struct bio *bio;
+
+	bio = bio_alloc(GFP_NOIO, 1);
+	bio->bi_sector = sector;
+	bio->bi_bdev = bdev;
+	bio->bi_end_io = hfsplus_end_io_sync;
+	bio->bi_private = &wait;
+
+	/*
+	 * We always submit one sector at a time, so bio_add_page must not fail.
+	 */
+	if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE,
+			 offset_in_page(data)) != HFSPLUS_SECTOR_SIZE)
+		BUG();
+
+	submit_bio(rw, bio);
+	wait_for_completion(&wait);
+
+	if (!bio_flagged(bio, BIO_UPTODATE))
+		return -EIO;
+	return 0;
+}
+
 static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
 {
 	u32 extent;
@@ -40,12 +74,14 @@
 	   !(attrib & HFSP_WRAP_ATTRIB_SPARED))
 		return 0;
 
-	wd->ablk_size = be32_to_cpu(*(__be32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
+	wd->ablk_size =
+		be32_to_cpu(*(__be32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
 	if (wd->ablk_size < HFSPLUS_SECTOR_SIZE)
 		return 0;
 	if (wd->ablk_size % HFSPLUS_SECTOR_SIZE)
 		return 0;
-	wd->ablk_start = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
+	wd->ablk_start =
+		be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
 
 	extent = get_unaligned_be32(bufptr + HFSP_WRAPOFF_EMBEDEXT);
 	wd->embed_start = (extent >> 16) & 0xFFFF;
@@ -68,7 +104,8 @@
 	if (HFSPLUS_SB(sb)->session >= 0) {
 		te.cdte_track = HFSPLUS_SB(sb)->session;
 		te.cdte_format = CDROM_LBA;
-		res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te);
+		res = ioctl_by_bdev(sb->s_bdev,
+			CDROMREADTOCENTRY, (unsigned long)&te);
 		if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) {
 			*start = (sector_t)te.cdte_addr.lba << 2;
 			return 0;
@@ -77,7 +114,8 @@
 		return -EINVAL;
 	}
 	ms_info.addr_format = CDROM_LBA;
-	res = ioctl_by_bdev(sb->s_bdev, CDROMMULTISESSION, (unsigned long)&ms_info);
+	res = ioctl_by_bdev(sb->s_bdev, CDROMMULTISESSION,
+		(unsigned long)&ms_info);
 	if (!res && ms_info.xa_flag)
 		*start = (sector_t)ms_info.addr.lba << 2;
 	return 0;
@@ -88,100 +126,112 @@
 int hfsplus_read_wrapper(struct super_block *sb)
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
-	struct buffer_head *bh;
-	struct hfsplus_vh *vhdr;
 	struct hfsplus_wd wd;
 	sector_t part_start, part_size;
 	u32 blocksize;
+	int error = 0;
 
+	error = -EINVAL;
 	blocksize = sb_min_blocksize(sb, HFSPLUS_SECTOR_SIZE);
 	if (!blocksize)
-		return -EINVAL;
+		goto out;
 
 	if (hfsplus_get_last_session(sb, &part_start, &part_size))
-		return -EINVAL;
+		goto out;
 	if ((u64)part_start + part_size > 0x100000000ULL) {
 		pr_err("hfs: volumes larger than 2TB are not supported yet\n");
-		return -EINVAL;
+		goto out;
 	}
-	while (1) {
-		bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
-		if (!bh)
-			return -EIO;
 
-		if (vhdr->signature == cpu_to_be16(HFSP_WRAP_MAGIC)) {
-			if (!hfsplus_read_mdb(vhdr, &wd))
-				goto error;
-			wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT;
-			part_start += wd.ablk_start + wd.embed_start * wd.ablk_size;
-			part_size = wd.embed_count * wd.ablk_size;
-			brelse(bh);
-			bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
-			if (!bh)
-				return -EIO;
-		}
-		if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
-			break;
-		if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
-			set_bit(HFSPLUS_SB_HFSX, &sbi->flags);
-			break;
-		}
-		brelse(bh);
+	error = -ENOMEM;
+	sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
+	if (!sbi->s_vhdr)
+		goto out;
+	sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
+	if (!sbi->s_backup_vhdr)
+		goto out_free_vhdr;
 
-		/* check for a partition block
+reread:
+	error = hfsplus_submit_bio(sb->s_bdev,
+				   part_start + HFSPLUS_VOLHEAD_SECTOR,
+				   sbi->s_vhdr, READ);
+	if (error)
+		goto out_free_backup_vhdr;
+
+	error = -EINVAL;
+	switch (sbi->s_vhdr->signature) {
+	case cpu_to_be16(HFSPLUS_VOLHEAD_SIGX):
+		set_bit(HFSPLUS_SB_HFSX, &sbi->flags);
+		/*FALLTHRU*/
+	case cpu_to_be16(HFSPLUS_VOLHEAD_SIG):
+		break;
+	case cpu_to_be16(HFSP_WRAP_MAGIC):
+		if (!hfsplus_read_mdb(sbi->s_vhdr, &wd))
+			goto out;
+		wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT;
+		part_start += wd.ablk_start + wd.embed_start * wd.ablk_size;
+		part_size = wd.embed_count * wd.ablk_size;
+		goto reread;
+	default:
+		/*
+		 * Check for a partition block.
+		 *
 		 * (should do this only for cdrom/loop though)
 		 */
 		if (hfs_part_find(sb, &part_start, &part_size))
-			return -EINVAL;
+			goto out;
+		goto reread;
 	}
 
-	blocksize = be32_to_cpu(vhdr->blocksize);
-	brelse(bh);
+	error = hfsplus_submit_bio(sb->s_bdev,
+				   part_start + part_size - 2,
+				   sbi->s_backup_vhdr, READ);
+	if (error)
+		goto out_free_backup_vhdr;
 
-	/* block size must be at least as large as a sector
-	 * and a multiple of 2
+	error = -EINVAL;
+	if (sbi->s_backup_vhdr->signature != sbi->s_vhdr->signature) {
+		printk(KERN_WARNING
+			"hfs: invalid secondary volume header\n");
+		goto out_free_backup_vhdr;
+	}
+
+	blocksize = be32_to_cpu(sbi->s_vhdr->blocksize);
+
+	/*
+	 * Block size must be at least as large as a sector and a multiple of 2.
 	 */
-	if (blocksize < HFSPLUS_SECTOR_SIZE ||
-	    ((blocksize - 1) & blocksize))
-		return -EINVAL;
+	if (blocksize < HFSPLUS_SECTOR_SIZE || ((blocksize - 1) & blocksize))
+		goto out_free_backup_vhdr;
 	sbi->alloc_blksz = blocksize;
 	sbi->alloc_blksz_shift = 0;
 	while ((blocksize >>= 1) != 0)
 		sbi->alloc_blksz_shift++;
 	blocksize = min(sbi->alloc_blksz, (u32)PAGE_SIZE);
 
-	/* align block size to block offset */
+	/*
+	 * Align block size to block offset.
+	 */
 	while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1))
 		blocksize >>= 1;
 
 	if (sb_set_blocksize(sb, blocksize) != blocksize) {
-		printk(KERN_ERR "hfs: unable to set blocksize to %u!\n", blocksize);
-		return -EINVAL;
+		printk(KERN_ERR "hfs: unable to set blocksize to %u!\n",
+			blocksize);
+		goto out_free_backup_vhdr;
 	}
 
 	sbi->blockoffset =
 		part_start >> (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT);
+	sbi->part_start = part_start;
 	sbi->sect_count = part_size;
 	sbi->fs_shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits;
-
-	bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr);
-	if (!bh)
-		return -EIO;
-
-	/* should still be the same... */
-	if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) {
-		if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
-			goto error;
-	} else {
-		if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
-			goto error;
-	}
-
-	sbi->s_vhbh = bh;
-	sbi->s_vhdr = vhdr;
-
 	return 0;
- error:
-	brelse(bh);
-	return -EINVAL;
+
+out_free_backup_vhdr:
+	kfree(sbi->s_backup_vhdr);
+out_free_vhdr:
+	kfree(sbi->s_vhdr);
+out:
+	return error;
 }
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 2c0f148..d3244d9 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -32,7 +32,7 @@
 
 #define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
 
-static int hostfs_d_delete(struct dentry *dentry)
+static int hostfs_d_delete(const struct dentry *dentry)
 {
 	return 1;
 }
@@ -92,12 +92,10 @@
 
 static char *__dentry_name(struct dentry *dentry, char *name)
 {
-	char *p = __dentry_path(dentry, name, PATH_MAX);
+	char *p = dentry_path_raw(dentry, name, PATH_MAX);
 	char *root;
 	size_t len;
 
-	spin_unlock(&dcache_lock);
-
 	root = dentry->d_sb->s_fs_info;
 	len = strlen(root);
 	if (IS_ERR(p)) {
@@ -123,25 +121,23 @@
 	if (!name)
 		return NULL;
 
-	spin_lock(&dcache_lock);
 	return __dentry_name(dentry, name); /* will unlock */
 }
 
 static char *inode_name(struct inode *ino)
 {
 	struct dentry *dentry;
-	char *name = __getname();
-	if (!name)
+	char *name;
+
+	dentry = d_find_alias(ino);
+	if (!dentry)
 		return NULL;
 
-	spin_lock(&dcache_lock);
-	if (list_empty(&ino->i_dentry)) {
-		spin_unlock(&dcache_lock);
-		__putname(name);
-		return NULL;
-	}
-	dentry = list_first_entry(&ino->i_dentry, struct dentry, d_alias);
-	return __dentry_name(dentry, name); /* will unlock */
+	name = dentry_name(dentry);
+
+	dput(dentry);
+
+	return name;
 }
 
 static char *follow_link(char *link)
@@ -251,9 +247,16 @@
 	}
 }
 
+static void hostfs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kfree(HOSTFS_I(inode));
+}
+
 static void hostfs_destroy_inode(struct inode *inode)
 {
-	kfree(HOSTFS_I(inode));
+	call_rcu(&inode->i_rcu, hostfs_i_callback);
 }
 
 static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
@@ -609,7 +612,7 @@
 		goto out_put;
 
 	d_add(dentry, inode);
-	dentry->d_op = &hostfs_dentry_ops;
+	d_set_d_op(dentry, &hostfs_dentry_ops);
 	return NULL;
 
  out_put:
@@ -746,11 +749,14 @@
 	return err;
 }
 
-int hostfs_permission(struct inode *ino, int desired)
+int hostfs_permission(struct inode *ino, int desired, unsigned int flags)
 {
 	char *name;
 	int r = 0, w = 0, x = 0, err;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	if (desired & MAY_READ) r = 1;
 	if (desired & MAY_WRITE) w = 1;
 	if (desired & MAY_EXEC) x = 1;
@@ -765,7 +771,7 @@
 		err = access_file(name, r, w, x);
 	__putname(name);
 	if (!err)
-		err = generic_permission(ino, desired, NULL);
+		err = generic_permission(ino, desired, flags, NULL);
 	return err;
 }
 
diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c
index 67d9d36..32c13a9 100644
--- a/fs/hpfs/dentry.c
+++ b/fs/hpfs/dentry.c
@@ -12,7 +12,8 @@
  * Note: the dentry argument is the parent dentry.
  */
 
-static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
+static int hpfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
 	unsigned long	 hash;
 	int		 i;
@@ -34,19 +35,25 @@
 	return 0;
 }
 
-static int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int hpfs_compare_dentry(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	unsigned al=a->len;
-	unsigned bl=b->len;
-	hpfs_adjust_length(a->name, &al);
+	unsigned al = len;
+	unsigned bl = name->len;
+
+	hpfs_adjust_length(str, &al);
 	/*hpfs_adjust_length(b->name, &bl);*/
-	/* 'a' is the qstr of an already existing dentry, so the name
-	 * must be valid. 'b' must be validated first.
+
+	/*
+	 * 'str' is the nane of an already existing dentry, so the name
+	 * must be valid. 'name' must be validated first.
 	 */
 
-	if (hpfs_chk_name(b->name, &bl))
+	if (hpfs_chk_name(name->name, &bl))
 		return 1;
-	if (hpfs_compare_names(dentry->d_sb, a->name, al, b->name, bl, 0))
+	if (hpfs_compare_names(parent->d_sb, str, al, name->name, bl, 0))
 		return 1;
 	return 0;
 }
@@ -58,5 +65,5 @@
 
 void hpfs_set_dentry_operations(struct dentry *dentry)
 {
-	dentry->d_op = &hpfs_dentry_operations;
+	d_set_d_op(dentry, &hpfs_dentry_operations);
 }
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 11c2b40..f4ad9e3 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -419,7 +419,7 @@
 			unlock_kernel();
 			return -ENOSPC;
 		}
-		if (generic_permission(inode, MAY_WRITE, NULL) ||
+		if (generic_permission(inode, MAY_WRITE, 0, NULL) ||
 		    !S_ISREG(inode->i_mode) ||
 		    get_write_access(inode)) {
 			d_rehash(dentry);
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 6c5f015..49935ba 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -177,9 +177,16 @@
 	return &ei->vfs_inode;
 }
 
+static void hpfs_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(hpfs_inode_cachep, hpfs_i(inode));
+}
+
 static void hpfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode));
+	call_rcu(&inode->i_rcu, hpfs_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index f702b5f..87ed48e 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -632,9 +632,16 @@
 	mntput(ino->i_sb->s_fs_info);
 }
 
+static void hppfs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kfree(HPPFS_I(inode));
+}
+
 static void hppfs_destroy_inode(struct inode *inode)
 {
-	kfree(HPPFS_I(inode));
+	call_rcu(&inode->i_rcu, hppfs_i_callback);
 }
 
 static const struct super_operations hppfs_sbops = {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index a5fe681..9885082 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -663,11 +663,18 @@
 	return &p->vfs_inode;
 }
 
+static void hugetlbfs_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(hugetlbfs_inode_cachep, HUGETLBFS_I(inode));
+}
+
 static void hugetlbfs_destroy_inode(struct inode *inode)
 {
 	hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb));
 	mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy);
-	kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode));
+	call_rcu(&inode->i_rcu, hugetlbfs_i_callback);
 }
 
 static const struct address_space_operations hugetlbfs_aops = {
diff --git a/fs/inode.c b/fs/inode.c
index ae2727a..da85e56 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -102,26 +102,29 @@
  */
 struct inodes_stat_t inodes_stat;
 
-static struct percpu_counter nr_inodes __cacheline_aligned_in_smp;
-static struct percpu_counter nr_inodes_unused __cacheline_aligned_in_smp;
+static DEFINE_PER_CPU(unsigned int, nr_inodes);
 
 static struct kmem_cache *inode_cachep __read_mostly;
 
-static inline int get_nr_inodes(void)
+static int get_nr_inodes(void)
 {
-	return percpu_counter_sum_positive(&nr_inodes);
+	int i;
+	int sum = 0;
+	for_each_possible_cpu(i)
+		sum += per_cpu(nr_inodes, i);
+	return sum < 0 ? 0 : sum;
 }
 
 static inline int get_nr_inodes_unused(void)
 {
-	return percpu_counter_sum_positive(&nr_inodes_unused);
+	return inodes_stat.nr_unused;
 }
 
 int get_nr_dirty_inodes(void)
 {
+	/* not actually dirty inodes, but a wild approximation */
 	int nr_dirty = get_nr_inodes() - get_nr_inodes_unused();
 	return nr_dirty > 0 ? nr_dirty : 0;
-
 }
 
 /*
@@ -132,7 +135,6 @@
 		   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	inodes_stat.nr_inodes = get_nr_inodes();
-	inodes_stat.nr_unused = get_nr_inodes_unused();
 	return proc_dointvec(table, write, buffer, lenp, ppos);
 }
 #endif
@@ -224,7 +226,7 @@
 	inode->i_fsnotify_mask = 0;
 #endif
 
-	percpu_counter_inc(&nr_inodes);
+	this_cpu_inc(nr_inodes);
 
 	return 0;
 out:
@@ -255,6 +257,12 @@
 	return inode;
 }
 
+void free_inode_nonrcu(struct inode *inode)
+{
+	kmem_cache_free(inode_cachep, inode);
+}
+EXPORT_SYMBOL(free_inode_nonrcu);
+
 void __destroy_inode(struct inode *inode)
 {
 	BUG_ON(inode_has_buffers(inode));
@@ -266,10 +274,17 @@
 	if (inode->i_default_acl && inode->i_default_acl != ACL_NOT_CACHED)
 		posix_acl_release(inode->i_default_acl);
 #endif
-	percpu_counter_dec(&nr_inodes);
+	this_cpu_dec(nr_inodes);
 }
 EXPORT_SYMBOL(__destroy_inode);
 
+static void 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(inode_cachep, inode);
+}
+
 static void destroy_inode(struct inode *inode)
 {
 	BUG_ON(!list_empty(&inode->i_lru));
@@ -277,7 +292,7 @@
 	if (inode->i_sb->s_op->destroy_inode)
 		inode->i_sb->s_op->destroy_inode(inode);
 	else
-		kmem_cache_free(inode_cachep, (inode));
+		call_rcu(&inode->i_rcu, i_callback);
 }
 
 /*
@@ -335,7 +350,7 @@
 {
 	if (list_empty(&inode->i_lru)) {
 		list_add(&inode->i_lru, &inode_lru);
-		percpu_counter_inc(&nr_inodes_unused);
+		inodes_stat.nr_unused++;
 	}
 }
 
@@ -343,7 +358,7 @@
 {
 	if (!list_empty(&inode->i_lru)) {
 		list_del_init(&inode->i_lru);
-		percpu_counter_dec(&nr_inodes_unused);
+		inodes_stat.nr_unused--;
 	}
 }
 
@@ -430,6 +445,7 @@
 	BUG_ON(!(inode->i_state & I_FREEING));
 	BUG_ON(inode->i_state & I_CLEAR);
 	inode_sync_wait(inode);
+	/* don't need i_lock here, no concurrent mods to i_state */
 	inode->i_state = I_FREEING | I_CLEAR;
 }
 EXPORT_SYMBOL(end_writeback);
@@ -513,7 +529,7 @@
 		list_move(&inode->i_lru, &dispose);
 		list_del_init(&inode->i_wb_list);
 		if (!(inode->i_state & (I_DIRTY | I_SYNC)))
-			percpu_counter_dec(&nr_inodes_unused);
+			inodes_stat.nr_unused--;
 	}
 	spin_unlock(&inode_lock);
 
@@ -554,7 +570,7 @@
 		list_move(&inode->i_lru, &dispose);
 		list_del_init(&inode->i_wb_list);
 		if (!(inode->i_state & (I_DIRTY | I_SYNC)))
-			percpu_counter_dec(&nr_inodes_unused);
+			inodes_stat.nr_unused--;
 	}
 	spin_unlock(&inode_lock);
 
@@ -616,7 +632,7 @@
 		if (atomic_read(&inode->i_count) ||
 		    (inode->i_state & ~I_REFERENCED)) {
 			list_del_init(&inode->i_lru);
-			percpu_counter_dec(&nr_inodes_unused);
+			inodes_stat.nr_unused--;
 			continue;
 		}
 
@@ -650,7 +666,7 @@
 		 */
 		list_move(&inode->i_lru, &freeable);
 		list_del_init(&inode->i_wb_list);
-		percpu_counter_dec(&nr_inodes_unused);
+		inodes_stat.nr_unused--;
 	}
 	if (current_is_kswapd())
 		__count_vm_events(KSWAPD_INODESTEAL, reap);
@@ -1648,8 +1664,6 @@
 					 SLAB_MEM_SPREAD),
 					 init_once);
 	register_shrinker(&icache_shrinker);
-	percpu_counter_init(&nr_inodes, 0);
-	percpu_counter_init(&nr_inodes_unused, 0);
 
 	/* Hash may have been set up in inode_init_early */
 	if (!hashdist)
diff --git a/fs/internal.h b/fs/internal.h
index e43b9a4..9687c2e 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -63,6 +63,7 @@
 
 extern void free_vfsmnt(struct vfsmount *);
 extern struct vfsmount *alloc_vfsmnt(const char *);
+extern unsigned int mnt_get_count(struct vfsmount *mnt);
 extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
 extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
 				struct vfsmount *);
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index bfdeb82..844a790 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -26,16 +26,32 @@
 
 #define BEQUIET
 
-static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
-static int isofs_hash(struct dentry *parent, struct qstr *qstr);
-static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
+static int isofs_hashi(const struct dentry *parent, const struct inode *inode,
+		struct qstr *qstr);
+static int isofs_hash(const struct dentry *parent, const struct inode *inode,
+		struct qstr *qstr);
+static int isofs_dentry_cmpi(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
+static int isofs_dentry_cmp(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
 
 #ifdef CONFIG_JOLIET
-static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
-static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
-static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
+static int isofs_hashi_ms(const struct dentry *parent, const struct inode *inode,
+		struct qstr *qstr);
+static int isofs_hash_ms(const struct dentry *parent, const struct inode *inode,
+		struct qstr *qstr);
+static int isofs_dentry_cmpi_ms(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
+static int isofs_dentry_cmp_ms(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name);
 #endif
 
 static void isofs_put_super(struct super_block *sb)
@@ -65,9 +81,16 @@
 	return &ei->vfs_inode;
 }
 
+static void isofs_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(isofs_inode_cachep, ISOFS_I(inode));
+}
+
 static void isofs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
+	call_rcu(&inode->i_rcu, isofs_i_callback);
 }
 
 static void init_once(void *foo)
@@ -160,7 +183,7 @@
  * Compute the hash for the isofs name corresponding to the dentry.
  */
 static int
-isofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms)
+isofs_hash_common(const struct dentry *dentry, struct qstr *qstr, int ms)
 {
 	const char *name;
 	int len;
@@ -181,7 +204,7 @@
  * Compute the hash for the isofs name corresponding to the dentry.
  */
 static int
-isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
+isofs_hashi_common(const struct dentry *dentry, struct qstr *qstr, int ms)
 {
 	const char *name;
 	int len;
@@ -206,100 +229,94 @@
 }
 
 /*
- * Case insensitive compare of two isofs names.
+ * Compare of two isofs names.
  */
-static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a,
-				struct qstr *b, int ms)
+static int isofs_dentry_cmp_common(
+		unsigned int len, const char *str,
+		const struct qstr *name, int ms, int ci)
 {
 	int alen, blen;
 
 	/* A filename cannot end in '.' or we treat it like it has none */
-	alen = a->len;
-	blen = b->len;
+	alen = name->len;
+	blen = len;
 	if (ms) {
-		while (alen && a->name[alen-1] == '.')
+		while (alen && name->name[alen-1] == '.')
 			alen--;
-		while (blen && b->name[blen-1] == '.')
+		while (blen && str[blen-1] == '.')
 			blen--;
 	}
 	if (alen == blen) {
-		if (strnicmp(a->name, b->name, alen) == 0)
-			return 0;
-	}
-	return 1;
-}
-
-/*
- * Case sensitive compare of two isofs names.
- */
-static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a,
-					struct qstr *b, int ms)
-{
-	int alen, blen;
-
-	/* A filename cannot end in '.' or we treat it like it has none */
-	alen = a->len;
-	blen = b->len;
-	if (ms) {
-		while (alen && a->name[alen-1] == '.')
-			alen--;
-		while (blen && b->name[blen-1] == '.')
-			blen--;
-	}
-	if (alen == blen) {
-		if (strncmp(a->name, b->name, alen) == 0)
-			return 0;
+		if (ci) {
+			if (strnicmp(name->name, str, alen) == 0)
+				return 0;
+		} else {
+			if (strncmp(name->name, str, alen) == 0)
+				return 0;
+		}
 	}
 	return 1;
 }
 
 static int
-isofs_hash(struct dentry *dentry, struct qstr *qstr)
+isofs_hash(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
 	return isofs_hash_common(dentry, qstr, 0);
 }
 
 static int
-isofs_hashi(struct dentry *dentry, struct qstr *qstr)
+isofs_hashi(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
 	return isofs_hashi_common(dentry, qstr, 0);
 }
 
 static int
-isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmp(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	return isofs_dentry_cmp_common(dentry, a, b, 0);
+	return isofs_dentry_cmp_common(len, str, name, 0, 0);
 }
 
 static int
-isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	return isofs_dentry_cmpi_common(dentry, a, b, 0);
+	return isofs_dentry_cmp_common(len, str, name, 0, 1);
 }
 
 #ifdef CONFIG_JOLIET
 static int
-isofs_hash_ms(struct dentry *dentry, struct qstr *qstr)
+isofs_hash_ms(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
 	return isofs_hash_common(dentry, qstr, 1);
 }
 
 static int
-isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
+isofs_hashi_ms(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
 	return isofs_hashi_common(dentry, qstr, 1);
 }
 
 static int
-isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmp_ms(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	return isofs_dentry_cmp_common(dentry, a, b, 1);
+	return isofs_dentry_cmp_common(len, str, name, 1, 0);
 }
 
 static int
-isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
+isofs_dentry_cmpi_ms(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	return isofs_dentry_cmpi_common(dentry, a, b, 1);
+	return isofs_dentry_cmp_common(len, str, name, 1, 1);
 }
 #endif
 
@@ -932,7 +949,7 @@
 		table += 2;
 	if (opt.check == 'r')
 		table++;
-	s->s_root->d_op = &isofs_dentry_ops[table];
+	d_set_d_op(s->s_root, &isofs_dentry_ops[table]);
 
 	kfree(opt.iocharset);
 
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 0d23abf..679a849 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -37,7 +37,8 @@
 
 	qstr.name = compare;
 	qstr.len = dlen;
-	return dentry->d_op->d_compare(dentry, &dentry->d_name, &qstr);
+	return dentry->d_op->d_compare(NULL, NULL, NULL, NULL,
+			dentry->d_name.len, dentry->d_name.name, &qstr);
 }
 
 /*
@@ -171,7 +172,7 @@
 	struct inode *inode;
 	struct page *page;
 
-	dentry->d_op = dir->i_sb->s_root->d_op;
+	d_set_d_op(dentry, dir->i_sb->s_root->d_op);
 
 	page = alloc_page(GFP_USER);
 	if (!page)
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 54a92fd..95b7967 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -259,11 +259,14 @@
 	return rc;
 }
 
-int jffs2_check_acl(struct inode *inode, int mask)
+int jffs2_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
 	struct posix_acl *acl;
 	int rc;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 5e42de8..3119f59 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -26,7 +26,7 @@
 
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 
-extern int jffs2_check_acl(struct inode *, int);
+extern int jffs2_check_acl(struct inode *, int, unsigned int);
 extern int jffs2_acl_chmod(struct inode *);
 extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
 extern int jffs2_init_acl_post(struct inode *);
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index c86041b..853b8e3 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -40,9 +40,16 @@
 	return &f->vfs_inode;
 }
 
+static void jffs2_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(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
+}
+
 static void jffs2_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
+	call_rcu(&inode->i_rcu, jffs2_i_callback);
 }
 
 static void jffs2_i_init_once(void *foo)
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 1057a49..e5de942 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -114,10 +114,14 @@
 	return rc;
 }
 
-int jfs_check_acl(struct inode *inode, int mask)
+int jfs_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct posix_acl *acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
+	struct posix_acl *acl;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
+	acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl) {
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index 54e0755..f9285c4 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -20,7 +20,7 @@
 
 #ifdef CONFIG_JFS_POSIX_ACL
 
-int jfs_check_acl(struct inode *, int);
+int jfs_check_acl(struct inode *, int, unsigned int flags);
 int jfs_init_acl(tid_t, struct inode *, struct inode *);
 int jfs_acl_chmod(struct inode *inode);
 
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 231ca4a..4414e3a 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/namei.h>
 #include <linux/ctype.h>
 #include <linux/quotaops.h>
 #include <linux/exportfs.h>
@@ -1465,7 +1466,7 @@
 	jfs_info("jfs_lookup: name = %s", name);
 
 	if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
-		dentry->d_op = &jfs_ci_dentry_operations;
+		d_set_d_op(dentry, &jfs_ci_dentry_operations);
 
 	if ((name[0] == '.') && (len == 1))
 		inum = dip->i_ino;
@@ -1494,7 +1495,7 @@
 	dentry = d_splice_alias(ip, dentry);
 
 	if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))
-		dentry->d_op = &jfs_ci_dentry_operations;
+		d_set_d_op(dentry, &jfs_ci_dentry_operations);
 
 	return dentry;
 }
@@ -1573,7 +1574,8 @@
 	.llseek		= generic_file_llseek,
 };
 
-static int jfs_ci_hash(struct dentry *dir, struct qstr *this)
+static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode,
+		struct qstr *this)
 {
 	unsigned long hash;
 	int i;
@@ -1586,32 +1588,63 @@
 	return 0;
 }
 
-static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b)
+static int jfs_ci_compare(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
 	int i, result = 1;
 
-	if (a->len != b->len)
+	if (len != name->len)
 		goto out;
-	for (i=0; i < a->len; i++) {
-		if (tolower(a->name[i]) != tolower(b->name[i]))
+	for (i=0; i < len; i++) {
+		if (tolower(str[i]) != tolower(name->name[i]))
 			goto out;
 	}
 	result = 0;
-
-	/*
-	 * We want creates to preserve case.  A negative dentry, a, that
-	 * has a different case than b may cause a new entry to be created
-	 * with the wrong case.  Since we can't tell if a comes from a negative
-	 * dentry, we blindly replace it with b.  This should be harmless if
-	 * a is not a negative dentry.
-	 */
-	memcpy((unsigned char *)a->name, b->name, a->len);
 out:
 	return result;
 }
 
+static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+	/*
+	 * This is not negative dentry. Always valid.
+	 *
+	 * Note, rename() to existing directory entry will have ->d_inode,
+	 * and will use existing name which isn't specified name by user.
+	 *
+	 * We may be able to drop this positive dentry here. But dropping
+	 * positive dentry isn't good idea. So it's unsupported like
+	 * rename("filename", "FILENAME") for now.
+	 */
+	if (dentry->d_inode)
+		return 1;
+
+	/*
+	 * This may be nfsd (or something), anyway, we can't see the
+	 * intent of this. So, since this can be for creation, drop it.
+	 */
+	if (!nd)
+		return 0;
+
+	/*
+	 * Drop the negative dentry, in order to make sure to use the
+	 * case sensitive name which is specified by user if this is
+	 * for creation.
+	 */
+	if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
+		if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+			return 0;
+	}
+	return 1;
+}
+
 const struct dentry_operations jfs_ci_dentry_operations =
 {
 	.d_hash = jfs_ci_hash,
 	.d_compare = jfs_ci_compare,
+	.d_revalidate = jfs_ci_revalidate,
 };
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 0669fc1..3150d76 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -115,6 +115,14 @@
 	return &jfs_inode->vfs_inode;
 }
 
+static void jfs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	struct jfs_inode_info *ji = JFS_IP(inode);
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kmem_cache_free(jfs_inode_cachep, ji);
+}
+
 static void jfs_destroy_inode(struct inode *inode)
 {
 	struct jfs_inode_info *ji = JFS_IP(inode);
@@ -128,7 +136,7 @@
 		ji->active_ag = -1;
 	}
 	spin_unlock_irq(&ji->ag_lock);
-	kmem_cache_free(jfs_inode_cachep, ji);
+	call_rcu(&inode->i_rcu, jfs_i_callback);
 }
 
 static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -517,7 +525,7 @@
 		goto out_no_root;
 
 	if (sbi->mntflag & JFS_OS2)
-		sb->s_root->d_op = &jfs_ci_dentry_operations;
+		d_set_d_op(sb->s_root, &jfs_ci_dentry_operations);
 
 	/* logical blocks are represented by 40 bits in pxd_t, etc. */
 	sb->s_maxbytes = ((u64) sb->s_blocksize) << 40;
diff --git a/fs/libfs.c b/fs/libfs.c
index a3accdf..889311e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -16,6 +16,11 @@
 
 #include <asm/uaccess.h>
 
+static inline int simple_positive(struct dentry *dentry)
+{
+	return dentry->d_inode && !d_unhashed(dentry);
+}
+
 int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		   struct kstat *stat)
 {
@@ -37,7 +42,7 @@
  * Retaining negative dentries for an in-memory filesystem just wastes
  * memory and lookup time: arrange for them to be deleted immediately.
  */
-static int simple_delete_dentry(struct dentry *dentry)
+static int simple_delete_dentry(const struct dentry *dentry)
 {
 	return 1;
 }
@@ -54,7 +59,7 @@
 
 	if (dentry->d_name.len > NAME_MAX)
 		return ERR_PTR(-ENAMETOOLONG);
-	dentry->d_op = &simple_dentry_operations;
+	d_set_d_op(dentry, &simple_dentry_operations);
 	d_add(dentry, NULL);
 	return NULL;
 }
@@ -76,7 +81,8 @@
 
 loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
 {
-	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
+	struct dentry *dentry = file->f_path.dentry;
+	mutex_lock(&dentry->d_inode->i_mutex);
 	switch (origin) {
 		case 1:
 			offset += file->f_pos;
@@ -84,7 +90,7 @@
 			if (offset >= 0)
 				break;
 		default:
-			mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+			mutex_unlock(&dentry->d_inode->i_mutex);
 			return -EINVAL;
 	}
 	if (offset != file->f_pos) {
@@ -94,21 +100,24 @@
 			struct dentry *cursor = file->private_data;
 			loff_t n = file->f_pos - 2;
 
-			spin_lock(&dcache_lock);
+			spin_lock(&dentry->d_lock);
+			/* d_lock not required for cursor */
 			list_del(&cursor->d_u.d_child);
-			p = file->f_path.dentry->d_subdirs.next;
-			while (n && p != &file->f_path.dentry->d_subdirs) {
+			p = dentry->d_subdirs.next;
+			while (n && p != &dentry->d_subdirs) {
 				struct dentry *next;
 				next = list_entry(p, struct dentry, d_u.d_child);
-				if (!d_unhashed(next) && next->d_inode)
+				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
+				if (simple_positive(next))
 					n--;
+				spin_unlock(&next->d_lock);
 				p = p->next;
 			}
 			list_add_tail(&cursor->d_u.d_child, p);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&dentry->d_lock);
 		}
 	}
-	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+	mutex_unlock(&dentry->d_inode->i_mutex);
 	return offset;
 }
 
@@ -148,29 +157,35 @@
 			i++;
 			/* fallthrough */
 		default:
-			spin_lock(&dcache_lock);
+			spin_lock(&dentry->d_lock);
 			if (filp->f_pos == 2)
 				list_move(q, &dentry->d_subdirs);
 
 			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
 				struct dentry *next;
 				next = list_entry(p, struct dentry, d_u.d_child);
-				if (d_unhashed(next) || !next->d_inode)
+				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
+				if (!simple_positive(next)) {
+					spin_unlock(&next->d_lock);
 					continue;
+				}
 
-				spin_unlock(&dcache_lock);
+				spin_unlock(&next->d_lock);
+				spin_unlock(&dentry->d_lock);
 				if (filldir(dirent, next->d_name.name, 
 					    next->d_name.len, filp->f_pos, 
 					    next->d_inode->i_ino, 
 					    dt_type(next->d_inode)) < 0)
 					return 0;
-				spin_lock(&dcache_lock);
+				spin_lock(&dentry->d_lock);
+				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
 				/* next is still alive */
 				list_move(q, p);
+				spin_unlock(&next->d_lock);
 				p = q;
 				filp->f_pos++;
 			}
-			spin_unlock(&dcache_lock);
+			spin_unlock(&dentry->d_lock);
 	}
 	return 0;
 }
@@ -259,23 +274,23 @@
 	return 0;
 }
 
-static inline int simple_positive(struct dentry *dentry)
-{
-	return dentry->d_inode && !d_unhashed(dentry);
-}
-
 int simple_empty(struct dentry *dentry)
 {
 	struct dentry *child;
 	int ret = 0;
 
-	spin_lock(&dcache_lock);
-	list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
-		if (simple_positive(child))
+	spin_lock(&dentry->d_lock);
+	list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+		spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
+		if (simple_positive(child)) {
+			spin_unlock(&child->d_lock);
 			goto out;
+		}
+		spin_unlock(&child->d_lock);
+	}
 	ret = 1;
 out:
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
 	return ret;
 }
 
diff --git a/fs/locks.c b/fs/locks.c
index 8729347..08415b2 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1389,7 +1389,7 @@
 		if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
 			goto out;
 		if ((arg == F_WRLCK)
-		    && ((atomic_read(&dentry->d_count) > 1)
+		    && ((dentry->d_count > 1)
 			|| (atomic_read(&inode->i_count) > 1)))
 			goto out;
 	}
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 409dfd6..f9ddf0c 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -555,9 +555,11 @@
 	return __logfs_create(dir, dentry, inode, target, destlen);
 }
 
-static int logfs_permission(struct inode *inode, int mask)
+static int logfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
-	return generic_permission(inode, mask, NULL);
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+	return generic_permission(inode, mask, flags, NULL);
 }
 
 static int logfs_link(struct dentry *old_dentry, struct inode *dir,
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index d8c71ec..03b8c24 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -141,13 +141,20 @@
 	return __logfs_iget(sb, ino);
 }
 
+static void logfs_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(logfs_inode_cache, logfs_inode(inode));
+}
+
 static void __logfs_destroy_inode(struct inode *inode)
 {
 	struct logfs_inode *li = logfs_inode(inode);
 
 	BUG_ON(li->li_block);
 	list_del(&li->li_freeing_list);
-	kmem_cache_free(logfs_inode_cache, li);
+	call_rcu(&inode->i_rcu, logfs_i_callback);
 }
 
 static void logfs_destroy_inode(struct inode *inode)
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index fb20208..ae0b83f 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -68,9 +68,16 @@
 	return &ei->vfs_inode;
 }
 
+static void minix_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(minix_inode_cachep, minix_i(inode));
+}
+
 static void minix_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(minix_inode_cachep, minix_i(inode));
+	call_rcu(&inode->i_rcu, minix_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index c0d35a3..1b9e077 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -23,7 +23,7 @@
 	struct inode * inode = NULL;
 	ino_t ino;
 
-	dentry->d_op = dir->i_sb->s_root->d_op;
+	d_set_d_op(dentry, dir->i_sb->s_root->d_op);
 
 	if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen)
 		return ERR_PTR(-ENAMETOOLONG);
diff --git a/fs/namei.c b/fs/namei.c
index 4ff7ca5..19433cd 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -169,8 +169,8 @@
 /*
  * This does basic POSIX ACL permission checking
  */
-static int acl_permission_check(struct inode *inode, int mask,
-		int (*check_acl)(struct inode *inode, int mask))
+static int acl_permission_check(struct inode *inode, int mask, unsigned int flags,
+		int (*check_acl)(struct inode *inode, int mask, unsigned int flags))
 {
 	umode_t			mode = inode->i_mode;
 
@@ -180,7 +180,7 @@
 		mode >>= 6;
 	else {
 		if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
-			int error = check_acl(inode, mask);
+			int error = check_acl(inode, mask, flags);
 			if (error != -EAGAIN)
 				return error;
 		}
@@ -198,25 +198,30 @@
 }
 
 /**
- * generic_permission  -  check for access rights on a Posix-like filesystem
+ * generic_permission -  check for access rights on a Posix-like filesystem
  * @inode:	inode to check access rights for
  * @mask:	right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
  * @check_acl:	optional callback to check for Posix ACLs
+ * @flags	IPERM_FLAG_ flags.
  *
  * Used to check for read/write/execute permissions on a file.
  * We use "fsuid" for this, letting us set arbitrary permissions
  * for filesystem access without changing the "normal" uids which
- * are used for other things..
+ * are used for other things.
+ *
+ * generic_permission is rcu-walk aware. It returns -ECHILD in case an rcu-walk
+ * request cannot be satisfied (eg. requires blocking or too much complexity).
+ * It would then be called again in ref-walk mode.
  */
-int generic_permission(struct inode *inode, int mask,
-		int (*check_acl)(struct inode *inode, int mask))
+int generic_permission(struct inode *inode, int mask, unsigned int flags,
+	int (*check_acl)(struct inode *inode, int mask, unsigned int flags))
 {
 	int ret;
 
 	/*
 	 * Do the basic POSIX ACL permission checks.
 	 */
-	ret = acl_permission_check(inode, mask, check_acl);
+	ret = acl_permission_check(inode, mask, flags, check_acl);
 	if (ret != -EACCES)
 		return ret;
 
@@ -271,9 +276,10 @@
 	}
 
 	if (inode->i_op->permission)
-		retval = inode->i_op->permission(inode, mask);
+		retval = inode->i_op->permission(inode, mask, 0);
 	else
-		retval = generic_permission(inode, mask, inode->i_op->check_acl);
+		retval = generic_permission(inode, mask, 0,
+				inode->i_op->check_acl);
 
 	if (retval)
 		return retval;
@@ -362,6 +368,18 @@
 EXPORT_SYMBOL(path_get);
 
 /**
+ * path_get_long - get a long reference to a path
+ * @path: path to get the reference to
+ *
+ * Given a path increment the reference count to the dentry and the vfsmount.
+ */
+void path_get_long(struct path *path)
+{
+	mntget_long(path->mnt);
+	dget(path->dentry);
+}
+
+/**
  * path_put - put a reference to a path
  * @path: path to put the reference to
  *
@@ -375,6 +393,185 @@
 EXPORT_SYMBOL(path_put);
 
 /**
+ * path_put_long - put a long reference to a path
+ * @path: path to put the reference to
+ *
+ * Given a path decrement the reference count to the dentry and the vfsmount.
+ */
+void path_put_long(struct path *path)
+{
+	dput(path->dentry);
+	mntput_long(path->mnt);
+}
+
+/**
+ * nameidata_drop_rcu - drop this nameidata out of rcu-walk
+ * @nd: nameidata pathwalk data to drop
+ * @Returns: 0 on success, -ECHLID on failure
+ *
+ * Path walking has 2 modes, rcu-walk and ref-walk (see
+ * Documentation/filesystems/path-lookup.txt). __drop_rcu* functions attempt
+ * to drop out of rcu-walk mode and take normal reference counts on dentries
+ * and vfsmounts to transition to rcu-walk mode. __drop_rcu* functions take
+ * refcounts at the last known good point before rcu-walk got stuck, so
+ * ref-walk may continue from there. If this is not successful (eg. a seqcount
+ * has changed), then failure is returned and path walk restarts from the
+ * beginning in ref-walk mode.
+ *
+ * nameidata_drop_rcu attempts to drop the current nd->path and nd->root into
+ * ref-walk. Must be called from rcu-walk context.
+ */
+static int nameidata_drop_rcu(struct nameidata *nd)
+{
+	struct fs_struct *fs = current->fs;
+	struct dentry *dentry = nd->path.dentry;
+
+	BUG_ON(!(nd->flags & LOOKUP_RCU));
+	if (nd->root.mnt) {
+		spin_lock(&fs->lock);
+		if (nd->root.mnt != fs->root.mnt ||
+				nd->root.dentry != fs->root.dentry)
+			goto err_root;
+	}
+	spin_lock(&dentry->d_lock);
+	if (!__d_rcu_to_refcount(dentry, nd->seq))
+		goto err;
+	BUG_ON(nd->inode != dentry->d_inode);
+	spin_unlock(&dentry->d_lock);
+	if (nd->root.mnt) {
+		path_get(&nd->root);
+		spin_unlock(&fs->lock);
+	}
+	mntget(nd->path.mnt);
+
+	rcu_read_unlock();
+	br_read_unlock(vfsmount_lock);
+	nd->flags &= ~LOOKUP_RCU;
+	return 0;
+err:
+	spin_unlock(&dentry->d_lock);
+err_root:
+	if (nd->root.mnt)
+		spin_unlock(&fs->lock);
+	return -ECHILD;
+}
+
+/* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing.  */
+static inline int nameidata_drop_rcu_maybe(struct nameidata *nd)
+{
+	if (nd->flags & LOOKUP_RCU)
+		return nameidata_drop_rcu(nd);
+	return 0;
+}
+
+/**
+ * nameidata_dentry_drop_rcu - drop nameidata and dentry out of rcu-walk
+ * @nd: nameidata pathwalk data to drop
+ * @dentry: dentry to drop
+ * @Returns: 0 on success, -ECHLID on failure
+ *
+ * nameidata_dentry_drop_rcu attempts to drop the current nd->path and nd->root,
+ * and dentry into ref-walk. @dentry must be a path found by a do_lookup call on
+ * @nd. Must be called from rcu-walk context.
+ */
+static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry)
+{
+	struct fs_struct *fs = current->fs;
+	struct dentry *parent = nd->path.dentry;
+
+	BUG_ON(!(nd->flags & LOOKUP_RCU));
+	if (nd->root.mnt) {
+		spin_lock(&fs->lock);
+		if (nd->root.mnt != fs->root.mnt ||
+				nd->root.dentry != fs->root.dentry)
+			goto err_root;
+	}
+	spin_lock(&parent->d_lock);
+	spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
+	if (!__d_rcu_to_refcount(dentry, nd->seq))
+		goto err;
+	/*
+	 * If the sequence check on the child dentry passed, then the child has
+	 * not been removed from its parent. This means the parent dentry must
+	 * be valid and able to take a reference at this point.
+	 */
+	BUG_ON(!IS_ROOT(dentry) && dentry->d_parent != parent);
+	BUG_ON(!parent->d_count);
+	parent->d_count++;
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&parent->d_lock);
+	if (nd->root.mnt) {
+		path_get(&nd->root);
+		spin_unlock(&fs->lock);
+	}
+	mntget(nd->path.mnt);
+
+	rcu_read_unlock();
+	br_read_unlock(vfsmount_lock);
+	nd->flags &= ~LOOKUP_RCU;
+	return 0;
+err:
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&parent->d_lock);
+err_root:
+	if (nd->root.mnt)
+		spin_unlock(&fs->lock);
+	return -ECHILD;
+}
+
+/* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing.  */
+static inline int nameidata_dentry_drop_rcu_maybe(struct nameidata *nd, struct dentry *dentry)
+{
+	if (nd->flags & LOOKUP_RCU)
+		return nameidata_dentry_drop_rcu(nd, dentry);
+	return 0;
+}
+
+/**
+ * nameidata_drop_rcu_last - drop nameidata ending path walk out of rcu-walk
+ * @nd: nameidata pathwalk data to drop
+ * @Returns: 0 on success, -ECHLID on failure
+ *
+ * nameidata_drop_rcu_last attempts to drop the current nd->path into ref-walk.
+ * nd->path should be the final element of the lookup, so nd->root is discarded.
+ * Must be called from rcu-walk context.
+ */
+static int nameidata_drop_rcu_last(struct nameidata *nd)
+{
+	struct dentry *dentry = nd->path.dentry;
+
+	BUG_ON(!(nd->flags & LOOKUP_RCU));
+	nd->flags &= ~LOOKUP_RCU;
+	nd->root.mnt = NULL;
+	spin_lock(&dentry->d_lock);
+	if (!__d_rcu_to_refcount(dentry, nd->seq))
+		goto err_unlock;
+	BUG_ON(nd->inode != dentry->d_inode);
+	spin_unlock(&dentry->d_lock);
+
+	mntget(nd->path.mnt);
+
+	rcu_read_unlock();
+	br_read_unlock(vfsmount_lock);
+
+	return 0;
+
+err_unlock:
+	spin_unlock(&dentry->d_lock);
+	rcu_read_unlock();
+	br_read_unlock(vfsmount_lock);
+	return -ECHILD;
+}
+
+/* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing.  */
+static inline int nameidata_drop_rcu_last_maybe(struct nameidata *nd)
+{
+	if (likely(nd->flags & LOOKUP_RCU))
+		return nameidata_drop_rcu_last(nd);
+	return 0;
+}
+
+/**
  * release_open_intent - free up open intent resources
  * @nd: pointer to nameidata
  */
@@ -386,10 +583,26 @@
 		fput(nd->intent.open.file);
 }
 
+static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+	int status;
+
+	status = dentry->d_op->d_revalidate(dentry, nd);
+	if (status == -ECHILD) {
+		if (nameidata_dentry_drop_rcu(nd, dentry))
+			return status;
+		status = dentry->d_op->d_revalidate(dentry, nd);
+	}
+
+	return status;
+}
+
 static inline struct dentry *
 do_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	int status = dentry->d_op->d_revalidate(dentry, nd);
+	int status;
+
+	status = d_revalidate(dentry, nd);
 	if (unlikely(status <= 0)) {
 		/*
 		 * The dentry failed validation.
@@ -397,19 +610,36 @@
 		 * the dentry otherwise d_revalidate is asking us
 		 * to return a fail status.
 		 */
-		if (!status) {
+		if (status < 0) {
+			/* If we're in rcu-walk, we don't have a ref */
+			if (!(nd->flags & LOOKUP_RCU))
+				dput(dentry);
+			dentry = ERR_PTR(status);
+
+		} else {
+			/* Don't d_invalidate in rcu-walk mode */
+			if (nameidata_dentry_drop_rcu_maybe(nd, dentry))
+				return ERR_PTR(-ECHILD);
 			if (!d_invalidate(dentry)) {
 				dput(dentry);
 				dentry = NULL;
 			}
-		} else {
-			dput(dentry);
-			dentry = ERR_PTR(status);
 		}
 	}
 	return dentry;
 }
 
+static inline int need_reval_dot(struct dentry *dentry)
+{
+	if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
+		return 0;
+
+	if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)))
+		return 0;
+
+	return 1;
+}
+
 /*
  * force_reval_path - force revalidation of a dentry
  *
@@ -433,13 +663,12 @@
 
 	/*
 	 * only check on filesystems where it's possible for the dentry to
-	 * become stale. It's assumed that if this flag is set then the
-	 * d_revalidate op will also be defined.
+	 * become stale.
 	 */
-	if (!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))
+	if (!need_reval_dot(dentry))
 		return 0;
 
-	status = dentry->d_op->d_revalidate(dentry, nd);
+	status = d_revalidate(dentry, nd);
 	if (status > 0)
 		return 0;
 
@@ -459,26 +688,27 @@
  * short-cut DAC fails, then call ->permission() to do more
  * complete permission check.
  */
-static int exec_permission(struct inode *inode)
+static inline int exec_permission(struct inode *inode, unsigned int flags)
 {
 	int ret;
 
 	if (inode->i_op->permission) {
-		ret = inode->i_op->permission(inode, MAY_EXEC);
-		if (!ret)
-			goto ok;
-		return ret;
+		ret = inode->i_op->permission(inode, MAY_EXEC, flags);
+	} else {
+		ret = acl_permission_check(inode, MAY_EXEC, flags,
+				inode->i_op->check_acl);
 	}
-	ret = acl_permission_check(inode, MAY_EXEC, inode->i_op->check_acl);
-	if (!ret)
+	if (likely(!ret))
 		goto ok;
+	if (ret == -ECHILD)
+		return ret;
 
 	if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH))
 		goto ok;
 
 	return ret;
 ok:
-	return security_inode_permission(inode, MAY_EXEC);
+	return security_inode_exec_permission(inode, flags);
 }
 
 static __always_inline void set_root(struct nameidata *nd)
@@ -489,8 +719,23 @@
 
 static int link_path_walk(const char *, struct nameidata *);
 
+static __always_inline void set_root_rcu(struct nameidata *nd)
+{
+	if (!nd->root.mnt) {
+		struct fs_struct *fs = current->fs;
+		unsigned seq;
+
+		do {
+			seq = read_seqcount_begin(&fs->seq);
+			nd->root = fs->root;
+		} while (read_seqcount_retry(&fs->seq, seq));
+	}
+}
+
 static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
 {
+	int ret;
+
 	if (IS_ERR(link))
 		goto fail;
 
@@ -500,8 +745,10 @@
 		nd->path = nd->root;
 		path_get(&nd->root);
 	}
+	nd->inode = nd->path.dentry->d_inode;
 
-	return link_path_walk(link, nd);
+	ret = link_path_walk(link, nd);
+	return ret;
 fail:
 	path_put(&nd->path);
 	return PTR_ERR(link);
@@ -516,11 +763,12 @@
 
 static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
 {
-	dput(nd->path.dentry);
-	if (nd->path.mnt != path->mnt) {
-		mntput(nd->path.mnt);
-		nd->path.mnt = path->mnt;
+	if (!(nd->flags & LOOKUP_RCU)) {
+		dput(nd->path.dentry);
+		if (nd->path.mnt != path->mnt)
+			mntput(nd->path.mnt);
 	}
+	nd->path.mnt = path->mnt;
 	nd->path.dentry = path->dentry;
 }
 
@@ -535,9 +783,11 @@
 
 	if (path->mnt != nd->path.mnt) {
 		path_to_nameidata(path, nd);
+		nd->inode = nd->path.dentry->d_inode;
 		dget(dentry);
 	}
 	mntget(path->mnt);
+
 	nd->last_type = LAST_BIND;
 	*p = dentry->d_inode->i_op->follow_link(dentry, nd);
 	error = PTR_ERR(*p);
@@ -591,6 +841,20 @@
 	return err;
 }
 
+static int follow_up_rcu(struct path *path)
+{
+	struct vfsmount *parent;
+	struct dentry *mountpoint;
+
+	parent = path->mnt->mnt_parent;
+	if (parent == path->mnt)
+		return 0;
+	mountpoint = path->mnt->mnt_mountpoint;
+	path->dentry = mountpoint;
+	path->mnt = parent;
+	return 1;
+}
+
 int follow_up(struct path *path)
 {
 	struct vfsmount *parent;
@@ -612,9 +876,24 @@
 	return 1;
 }
 
-/* no need for dcache_lock, as serialization is taken care in
- * namespace.c
+/*
+ * serialization is taken care of in namespace.c
  */
+static void __follow_mount_rcu(struct nameidata *nd, struct path *path,
+				struct inode **inode)
+{
+	while (d_mountpoint(path->dentry)) {
+		struct vfsmount *mounted;
+		mounted = __lookup_mnt(path->mnt, path->dentry, 1);
+		if (!mounted)
+			return;
+		path->mnt = mounted;
+		path->dentry = mounted->mnt_root;
+		nd->seq = read_seqcount_begin(&path->dentry->d_seq);
+		*inode = path->dentry->d_inode;
+	}
+}
+
 static int __follow_mount(struct path *path)
 {
 	int res = 0;
@@ -645,9 +924,6 @@
 	}
 }
 
-/* no need for dcache_lock, as serialization is taken care in
- * namespace.c
- */
 int follow_down(struct path *path)
 {
 	struct vfsmount *mounted;
@@ -663,7 +939,42 @@
 	return 0;
 }
 
-static __always_inline void follow_dotdot(struct nameidata *nd)
+static int follow_dotdot_rcu(struct nameidata *nd)
+{
+	struct inode *inode = nd->inode;
+
+	set_root_rcu(nd);
+
+	while(1) {
+		if (nd->path.dentry == nd->root.dentry &&
+		    nd->path.mnt == nd->root.mnt) {
+			break;
+		}
+		if (nd->path.dentry != nd->path.mnt->mnt_root) {
+			struct dentry *old = nd->path.dentry;
+			struct dentry *parent = old->d_parent;
+			unsigned seq;
+
+			seq = read_seqcount_begin(&parent->d_seq);
+			if (read_seqcount_retry(&old->d_seq, nd->seq))
+				return -ECHILD;
+			inode = parent->d_inode;
+			nd->path.dentry = parent;
+			nd->seq = seq;
+			break;
+		}
+		if (!follow_up_rcu(&nd->path))
+			break;
+		nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
+		inode = nd->path.dentry->d_inode;
+	}
+	__follow_mount_rcu(nd, &nd->path, &inode);
+	nd->inode = inode;
+
+	return 0;
+}
+
+static void follow_dotdot(struct nameidata *nd)
 {
 	set_root(nd);
 
@@ -684,6 +995,7 @@
 			break;
 	}
 	follow_mount(&nd->path);
+	nd->inode = nd->path.dentry->d_inode;
 }
 
 /*
@@ -721,17 +1033,17 @@
  *  It _is_ time-critical.
  */
 static int do_lookup(struct nameidata *nd, struct qstr *name,
-		     struct path *path)
+			struct path *path, struct inode **inode)
 {
 	struct vfsmount *mnt = nd->path.mnt;
-	struct dentry *dentry, *parent;
+	struct dentry *dentry, *parent = nd->path.dentry;
 	struct inode *dir;
 	/*
 	 * See if the low-level filesystem might want
 	 * to use its own hash..
 	 */
-	if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
-		int err = nd->path.dentry->d_op->d_hash(nd->path.dentry, name);
+	if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
+		int err = parent->d_op->d_hash(parent, nd->inode, name);
 		if (err < 0)
 			return err;
 	}
@@ -741,21 +1053,44 @@
 	 * of a false negative due to a concurrent rename, we're going to
 	 * do the non-racy lookup, below.
 	 */
-	dentry = __d_lookup(nd->path.dentry, name);
-	if (!dentry)
-		goto need_lookup;
+	if (nd->flags & LOOKUP_RCU) {
+		unsigned seq;
+
+		*inode = nd->inode;
+		dentry = __d_lookup_rcu(parent, name, &seq, inode);
+		if (!dentry) {
+			if (nameidata_drop_rcu(nd))
+				return -ECHILD;
+			goto need_lookup;
+		}
+		/* Memory barrier in read_seqcount_begin of child is enough */
+		if (__read_seqcount_retry(&parent->d_seq, nd->seq))
+			return -ECHILD;
+
+		nd->seq = seq;
+		if (dentry->d_flags & DCACHE_OP_REVALIDATE)
+			goto need_revalidate;
+		path->mnt = mnt;
+		path->dentry = dentry;
+		__follow_mount_rcu(nd, path, inode);
+	} else {
+		dentry = __d_lookup(parent, name);
+		if (!dentry)
+			goto need_lookup;
 found:
-	if (dentry->d_op && dentry->d_op->d_revalidate)
-		goto need_revalidate;
+		if (dentry->d_flags & DCACHE_OP_REVALIDATE)
+			goto need_revalidate;
 done:
-	path->mnt = mnt;
-	path->dentry = dentry;
-	__follow_mount(path);
+		path->mnt = mnt;
+		path->dentry = dentry;
+		__follow_mount(path);
+		*inode = path->dentry->d_inode;
+	}
 	return 0;
 
 need_lookup:
-	parent = nd->path.dentry;
 	dir = parent->d_inode;
+	BUG_ON(nd->inode != dir);
 
 	mutex_lock(&dir->i_mutex);
 	/*
@@ -817,7 +1152,6 @@
 static int link_path_walk(const char *name, struct nameidata *nd)
 {
 	struct path next;
-	struct inode *inode;
 	int err;
 	unsigned int lookup_flags = nd->flags;
 	
@@ -826,18 +1160,28 @@
 	if (!*name)
 		goto return_reval;
 
-	inode = nd->path.dentry->d_inode;
 	if (nd->depth)
 		lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE);
 
 	/* At this point we know we have a real path component. */
 	for(;;) {
+		struct inode *inode;
 		unsigned long hash;
 		struct qstr this;
 		unsigned int c;
 
 		nd->flags |= LOOKUP_CONTINUE;
-		err = exec_permission(inode);
+		if (nd->flags & LOOKUP_RCU) {
+			err = exec_permission(nd->inode, IPERM_FLAG_RCU);
+			if (err == -ECHILD) {
+				if (nameidata_drop_rcu(nd))
+					return -ECHILD;
+				goto exec_again;
+			}
+		} else {
+exec_again:
+			err = exec_permission(nd->inode, 0);
+		}
  		if (err)
 			break;
 
@@ -868,37 +1212,44 @@
 		if (this.name[0] == '.') switch (this.len) {
 			default:
 				break;
-			case 2:	
+			case 2:
 				if (this.name[1] != '.')
 					break;
-				follow_dotdot(nd);
-				inode = nd->path.dentry->d_inode;
+				if (nd->flags & LOOKUP_RCU) {
+					if (follow_dotdot_rcu(nd))
+						return -ECHILD;
+				} else
+					follow_dotdot(nd);
 				/* fallthrough */
 			case 1:
 				continue;
 		}
 		/* This does the actual lookups.. */
-		err = do_lookup(nd, &this, &next);
+		err = do_lookup(nd, &this, &next, &inode);
 		if (err)
 			break;
-
 		err = -ENOENT;
-		inode = next.dentry->d_inode;
 		if (!inode)
 			goto out_dput;
 
 		if (inode->i_op->follow_link) {
+			/* We commonly drop rcu-walk here */
+			if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry))
+				return -ECHILD;
+			BUG_ON(inode != next.dentry->d_inode);
 			err = do_follow_link(&next, nd);
 			if (err)
 				goto return_err;
+			nd->inode = nd->path.dentry->d_inode;
 			err = -ENOENT;
-			inode = nd->path.dentry->d_inode;
-			if (!inode)
+			if (!nd->inode)
 				break;
-		} else
+		} else {
 			path_to_nameidata(&next, nd);
+			nd->inode = inode;
+		}
 		err = -ENOTDIR; 
-		if (!inode->i_op->lookup)
+		if (!nd->inode->i_op->lookup)
 			break;
 		continue;
 		/* here ends the main loop */
@@ -913,32 +1264,39 @@
 		if (this.name[0] == '.') switch (this.len) {
 			default:
 				break;
-			case 2:	
+			case 2:
 				if (this.name[1] != '.')
 					break;
-				follow_dotdot(nd);
-				inode = nd->path.dentry->d_inode;
+				if (nd->flags & LOOKUP_RCU) {
+					if (follow_dotdot_rcu(nd))
+						return -ECHILD;
+				} else
+					follow_dotdot(nd);
 				/* fallthrough */
 			case 1:
 				goto return_reval;
 		}
-		err = do_lookup(nd, &this, &next);
+		err = do_lookup(nd, &this, &next, &inode);
 		if (err)
 			break;
-		inode = next.dentry->d_inode;
 		if (follow_on_final(inode, lookup_flags)) {
+			if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry))
+				return -ECHILD;
+			BUG_ON(inode != next.dentry->d_inode);
 			err = do_follow_link(&next, nd);
 			if (err)
 				goto return_err;
-			inode = nd->path.dentry->d_inode;
-		} else
+			nd->inode = nd->path.dentry->d_inode;
+		} else {
 			path_to_nameidata(&next, nd);
+			nd->inode = inode;
+		}
 		err = -ENOENT;
-		if (!inode)
+		if (!nd->inode)
 			break;
 		if (lookup_flags & LOOKUP_DIRECTORY) {
 			err = -ENOTDIR; 
-			if (!inode->i_op->lookup)
+			if (!nd->inode->i_op->lookup)
 				break;
 		}
 		goto return_base;
@@ -958,25 +1316,43 @@
 		 * We bypassed the ordinary revalidation routines.
 		 * We may need to check the cached dentry for staleness.
 		 */
-		if (nd->path.dentry && nd->path.dentry->d_sb &&
-		    (nd->path.dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) {
-			err = -ESTALE;
+		if (need_reval_dot(nd->path.dentry)) {
 			/* Note: we do not d_invalidate() */
-			if (!nd->path.dentry->d_op->d_revalidate(
-					nd->path.dentry, nd))
+			err = d_revalidate(nd->path.dentry, nd);
+			if (!err)
+				err = -ESTALE;
+			if (err < 0)
 				break;
 		}
 return_base:
+		if (nameidata_drop_rcu_last_maybe(nd))
+			return -ECHILD;
 		return 0;
 out_dput:
-		path_put_conditional(&next, nd);
+		if (!(nd->flags & LOOKUP_RCU))
+			path_put_conditional(&next, nd);
 		break;
 	}
-	path_put(&nd->path);
+	if (!(nd->flags & LOOKUP_RCU))
+		path_put(&nd->path);
 return_err:
 	return err;
 }
 
+static inline int path_walk_rcu(const char *name, struct nameidata *nd)
+{
+	current->total_link_count = 0;
+
+	return link_path_walk(name, nd);
+}
+
+static inline int path_walk_simple(const char *name, struct nameidata *nd)
+{
+	current->total_link_count = 0;
+
+	return link_path_walk(name, nd);
+}
+
 static int path_walk(const char *name, struct nameidata *nd)
 {
 	struct path save = nd->path;
@@ -1002,6 +1378,93 @@
 	return result;
 }
 
+static void path_finish_rcu(struct nameidata *nd)
+{
+	if (nd->flags & LOOKUP_RCU) {
+		/* RCU dangling. Cancel it. */
+		nd->flags &= ~LOOKUP_RCU;
+		nd->root.mnt = NULL;
+		rcu_read_unlock();
+		br_read_unlock(vfsmount_lock);
+	}
+	if (nd->file)
+		fput(nd->file);
+}
+
+static int path_init_rcu(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
+{
+	int retval = 0;
+	int fput_needed;
+	struct file *file;
+
+	nd->last_type = LAST_ROOT; /* if there are only slashes... */
+	nd->flags = flags | LOOKUP_RCU;
+	nd->depth = 0;
+	nd->root.mnt = NULL;
+	nd->file = NULL;
+
+	if (*name=='/') {
+		struct fs_struct *fs = current->fs;
+		unsigned seq;
+
+		br_read_lock(vfsmount_lock);
+		rcu_read_lock();
+
+		do {
+			seq = read_seqcount_begin(&fs->seq);
+			nd->root = fs->root;
+			nd->path = nd->root;
+			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
+		} while (read_seqcount_retry(&fs->seq, seq));
+
+	} else if (dfd == AT_FDCWD) {
+		struct fs_struct *fs = current->fs;
+		unsigned seq;
+
+		br_read_lock(vfsmount_lock);
+		rcu_read_lock();
+
+		do {
+			seq = read_seqcount_begin(&fs->seq);
+			nd->path = fs->pwd;
+			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
+		} while (read_seqcount_retry(&fs->seq, seq));
+
+	} else {
+		struct dentry *dentry;
+
+		file = fget_light(dfd, &fput_needed);
+		retval = -EBADF;
+		if (!file)
+			goto out_fail;
+
+		dentry = file->f_path.dentry;
+
+		retval = -ENOTDIR;
+		if (!S_ISDIR(dentry->d_inode->i_mode))
+			goto fput_fail;
+
+		retval = file_permission(file, MAY_EXEC);
+		if (retval)
+			goto fput_fail;
+
+		nd->path = file->f_path;
+		if (fput_needed)
+			nd->file = file;
+
+		nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
+		br_read_lock(vfsmount_lock);
+		rcu_read_lock();
+	}
+	nd->inode = nd->path.dentry->d_inode;
+	return 0;
+
+fput_fail:
+	fput_light(file, fput_needed);
+out_fail:
+	return retval;
+}
+
 static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
 {
 	int retval = 0;
@@ -1042,6 +1505,7 @@
 
 		fput_light(file, fput_needed);
 	}
+	nd->inode = nd->path.dentry->d_inode;
 	return 0;
 
 fput_fail:
@@ -1054,16 +1518,53 @@
 static int do_path_lookup(int dfd, const char *name,
 				unsigned int flags, struct nameidata *nd)
 {
-	int retval = path_init(dfd, name, flags, nd);
-	if (!retval)
-		retval = path_walk(name, nd);
-	if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
-				nd->path.dentry->d_inode))
-		audit_inode(name, nd->path.dentry);
+	int retval;
+
+	/*
+	 * Path walking is largely split up into 2 different synchronisation
+	 * schemes, rcu-walk and ref-walk (explained in
+	 * Documentation/filesystems/path-lookup.txt). These share much of the
+	 * path walk code, but some things particularly setup, cleanup, and
+	 * following mounts are sufficiently divergent that functions are
+	 * duplicated. Typically there is a function foo(), and its RCU
+	 * analogue, foo_rcu().
+	 *
+	 * -ECHILD is the error number of choice (just to avoid clashes) that
+	 * is returned if some aspect of an rcu-walk fails. Such an error must
+	 * be handled by restarting a traditional ref-walk (which will always
+	 * be able to complete).
+	 */
+	retval = path_init_rcu(dfd, name, flags, nd);
+	if (unlikely(retval))
+		return retval;
+	retval = path_walk_rcu(name, nd);
+	path_finish_rcu(nd);
 	if (nd->root.mnt) {
 		path_put(&nd->root);
 		nd->root.mnt = NULL;
 	}
+
+	if (unlikely(retval == -ECHILD || retval == -ESTALE)) {
+		/* slower, locked walk */
+		if (retval == -ESTALE)
+			flags |= LOOKUP_REVAL;
+		retval = path_init(dfd, name, flags, nd);
+		if (unlikely(retval))
+			return retval;
+		retval = path_walk(name, nd);
+		if (nd->root.mnt) {
+			path_put(&nd->root);
+			nd->root.mnt = NULL;
+		}
+	}
+
+	if (likely(!retval)) {
+		if (unlikely(!audit_dummy_context())) {
+			if (nd->path.dentry && nd->inode)
+				audit_inode(name, nd->path.dentry);
+		}
+	}
+
 	return retval;
 }
 
@@ -1106,10 +1607,11 @@
 	path_get(&nd->path);
 	nd->root = nd->path;
 	path_get(&nd->root);
+	nd->inode = nd->path.dentry->d_inode;
 
 	retval = path_walk(name, nd);
 	if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
-				nd->path.dentry->d_inode))
+				nd->inode))
 		audit_inode(name, nd->path.dentry);
 
 	path_put(&nd->root);
@@ -1125,7 +1627,7 @@
 	struct dentry *dentry;
 	int err;
 
-	err = exec_permission(inode);
+	err = exec_permission(inode, 0);
 	if (err)
 		return ERR_PTR(err);
 
@@ -1133,8 +1635,8 @@
 	 * See if the low-level filesystem might want
 	 * to use its own hash..
 	 */
-	if (base->d_op && base->d_op->d_hash) {
-		err = base->d_op->d_hash(base, name);
+	if (base->d_flags & DCACHE_OP_HASH) {
+		err = base->d_op->d_hash(base, inode, name);
 		dentry = ERR_PTR(err);
 		if (err < 0)
 			goto out;
@@ -1147,7 +1649,7 @@
 	 */
 	dentry = d_lookup(base, name);
 
-	if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
+	if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE))
 		dentry = do_revalidate(dentry, nd);
 
 	if (!dentry)
@@ -1490,6 +1992,7 @@
 	mutex_unlock(&dir->d_inode->i_mutex);
 	dput(nd->path.dentry);
 	nd->path.dentry = path->dentry;
+
 	if (error)
 		return error;
 	/* Don't check for write permission, don't truncate */
@@ -1584,6 +2087,9 @@
 	return ERR_PTR(error);
 }
 
+/*
+ * Handle O_CREAT case for do_filp_open
+ */
 static struct file *do_last(struct nameidata *nd, struct path *path,
 			    int open_flag, int acc_mode,
 			    int mode, const char *pathname)
@@ -1597,50 +2103,25 @@
 		follow_dotdot(nd);
 		dir = nd->path.dentry;
 	case LAST_DOT:
-		if (nd->path.mnt->mnt_sb->s_type->fs_flags & FS_REVAL_DOT) {
-			if (!dir->d_op->d_revalidate(dir, nd)) {
+		if (need_reval_dot(dir)) {
+			error = d_revalidate(nd->path.dentry, nd);
+			if (!error)
 				error = -ESTALE;
+			if (error < 0)
 				goto exit;
-			}
 		}
 		/* fallthrough */
 	case LAST_ROOT:
-		if (open_flag & O_CREAT)
-			goto exit;
-		/* fallthrough */
+		goto exit;
 	case LAST_BIND:
 		audit_inode(pathname, dir);
 		goto ok;
 	}
 
 	/* trailing slashes? */
-	if (nd->last.name[nd->last.len]) {
-		if (open_flag & O_CREAT)
-			goto exit;
-		nd->flags |= LOOKUP_DIRECTORY | LOOKUP_FOLLOW;
-	}
+	if (nd->last.name[nd->last.len])
+		goto exit;
 
-	/* just plain open? */
-	if (!(open_flag & O_CREAT)) {
-		error = do_lookup(nd, &nd->last, path);
-		if (error)
-			goto exit;
-		error = -ENOENT;
-		if (!path->dentry->d_inode)
-			goto exit_dput;
-		if (path->dentry->d_inode->i_op->follow_link)
-			return NULL;
-		error = -ENOTDIR;
-		if (nd->flags & LOOKUP_DIRECTORY) {
-			if (!path->dentry->d_inode->i_op->lookup)
-				goto exit_dput;
-		}
-		path_to_nameidata(path, nd);
-		audit_inode(pathname, nd->path.dentry);
-		goto ok;
-	}
-
-	/* OK, it's O_CREAT */
 	mutex_lock(&dir->d_inode->i_mutex);
 
 	path->dentry = lookup_hash(nd);
@@ -1711,8 +2192,9 @@
 		return NULL;
 
 	path_to_nameidata(path, nd);
+	nd->inode = path->dentry->d_inode;
 	error = -EISDIR;
-	if (S_ISDIR(path->dentry->d_inode->i_mode))
+	if (S_ISDIR(nd->inode->i_mode))
 		goto exit;
 ok:
 	filp = finish_open(nd, open_flag, acc_mode);
@@ -1743,7 +2225,7 @@
 	struct path path;
 	int count = 0;
 	int flag = open_to_namei_flags(open_flag);
-	int force_reval = 0;
+	int flags;
 
 	if (!(open_flag & O_CREAT))
 		mode = 0;
@@ -1772,54 +2254,84 @@
 	if (open_flag & O_APPEND)
 		acc_mode |= MAY_APPEND;
 
-	/* find the parent */
-reval:
-	error = path_init(dfd, pathname, LOOKUP_PARENT, &nd);
-	if (error)
-		return ERR_PTR(error);
-	if (force_reval)
-		nd.flags |= LOOKUP_REVAL;
-
-	current->total_link_count = 0;
-	error = link_path_walk(pathname, &nd);
-	if (error) {
-		filp = ERR_PTR(error);
-		goto out;
+	flags = LOOKUP_OPEN;
+	if (open_flag & O_CREAT) {
+		flags |= LOOKUP_CREATE;
+		if (open_flag & O_EXCL)
+			flags |= LOOKUP_EXCL;
 	}
-	if (unlikely(!audit_dummy_context()) && (open_flag & O_CREAT))
+	if (open_flag & O_DIRECTORY)
+		flags |= LOOKUP_DIRECTORY;
+	if (!(open_flag & O_NOFOLLOW))
+		flags |= LOOKUP_FOLLOW;
+
+	filp = get_empty_filp();
+	if (!filp)
+		return ERR_PTR(-ENFILE);
+
+	filp->f_flags = open_flag;
+	nd.intent.open.file = filp;
+	nd.intent.open.flags = flag;
+	nd.intent.open.create_mode = mode;
+
+	if (open_flag & O_CREAT)
+		goto creat;
+
+	/* !O_CREAT, simple open */
+	error = do_path_lookup(dfd, pathname, flags, &nd);
+	if (unlikely(error))
+		goto out_filp;
+	error = -ELOOP;
+	if (!(nd.flags & LOOKUP_FOLLOW)) {
+		if (nd.inode->i_op->follow_link)
+			goto out_path;
+	}
+	error = -ENOTDIR;
+	if (nd.flags & LOOKUP_DIRECTORY) {
+		if (!nd.inode->i_op->lookup)
+			goto out_path;
+	}
+	audit_inode(pathname, nd.path.dentry);
+	filp = finish_open(&nd, open_flag, acc_mode);
+	return filp;
+
+creat:
+	/* OK, have to create the file. Find the parent. */
+	error = path_init_rcu(dfd, pathname,
+			LOOKUP_PARENT | (flags & LOOKUP_REVAL), &nd);
+	if (error)
+		goto out_filp;
+	error = path_walk_rcu(pathname, &nd);
+	path_finish_rcu(&nd);
+	if (unlikely(error == -ECHILD || error == -ESTALE)) {
+		/* slower, locked walk */
+		if (error == -ESTALE) {
+reval:
+			flags |= LOOKUP_REVAL;
+		}
+		error = path_init(dfd, pathname,
+				LOOKUP_PARENT | (flags & LOOKUP_REVAL), &nd);
+		if (error)
+			goto out_filp;
+
+		error = path_walk_simple(pathname, &nd);
+	}
+	if (unlikely(error))
+		goto out_filp;
+	if (unlikely(!audit_dummy_context()))
 		audit_inode(pathname, nd.path.dentry);
 
 	/*
 	 * We have the parent and last component.
 	 */
-
-	error = -ENFILE;
-	filp = get_empty_filp();
-	if (filp == NULL)
-		goto exit_parent;
-	nd.intent.open.file = filp;
-	filp->f_flags = open_flag;
-	nd.intent.open.flags = flag;
-	nd.intent.open.create_mode = mode;
-	nd.flags &= ~LOOKUP_PARENT;
-	nd.flags |= LOOKUP_OPEN;
-	if (open_flag & O_CREAT) {
-		nd.flags |= LOOKUP_CREATE;
-		if (open_flag & O_EXCL)
-			nd.flags |= LOOKUP_EXCL;
-	}
-	if (open_flag & O_DIRECTORY)
-		nd.flags |= LOOKUP_DIRECTORY;
-	if (!(open_flag & O_NOFOLLOW))
-		nd.flags |= LOOKUP_FOLLOW;
+	nd.flags = flags;
 	filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
 	while (unlikely(!filp)) { /* trailing symlink */
 		struct path holder;
-		struct inode *inode = path.dentry->d_inode;
 		void *cookie;
 		error = -ELOOP;
 		/* S_ISDIR part is a temporary automount kludge */
-		if (!(nd.flags & LOOKUP_FOLLOW) && !S_ISDIR(inode->i_mode))
+		if (!(nd.flags & LOOKUP_FOLLOW) && !S_ISDIR(nd.inode->i_mode))
 			goto exit_dput;
 		if (count++ == 32)
 			goto exit_dput;
@@ -1840,36 +2352,33 @@
 			goto exit_dput;
 		error = __do_follow_link(&path, &nd, &cookie);
 		if (unlikely(error)) {
+			if (!IS_ERR(cookie) && nd.inode->i_op->put_link)
+				nd.inode->i_op->put_link(path.dentry, &nd, cookie);
 			/* nd.path had been dropped */
-			if (!IS_ERR(cookie) && inode->i_op->put_link)
-				inode->i_op->put_link(path.dentry, &nd, cookie);
-			path_put(&path);
-			release_open_intent(&nd);
-			filp = ERR_PTR(error);
-			goto out;
+			nd.path = path;
+			goto out_path;
 		}
 		holder = path;
 		nd.flags &= ~LOOKUP_PARENT;
 		filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
-		if (inode->i_op->put_link)
-			inode->i_op->put_link(holder.dentry, &nd, cookie);
+		if (nd.inode->i_op->put_link)
+			nd.inode->i_op->put_link(holder.dentry, &nd, cookie);
 		path_put(&holder);
 	}
 out:
 	if (nd.root.mnt)
 		path_put(&nd.root);
-	if (filp == ERR_PTR(-ESTALE) && !force_reval) {
-		force_reval = 1;
+	if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL))
 		goto reval;
-	}
 	return filp;
 
 exit_dput:
 	path_put_conditional(&path, &nd);
+out_path:
+	path_put(&nd.path);
+out_filp:
 	if (!IS_ERR(nd.intent.open.file))
 		release_open_intent(&nd);
-exit_parent:
-	path_put(&nd.path);
 	filp = ERR_PTR(error);
 	goto out;
 }
@@ -2130,12 +2639,10 @@
 {
 	dget(dentry);
 	shrink_dcache_parent(dentry);
-	spin_lock(&dcache_lock);
 	spin_lock(&dentry->d_lock);
-	if (atomic_read(&dentry->d_count) == 2)
+	if (dentry->d_count == 2)
 		__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
 }
 
 int vfs_rmdir(struct inode *dir, struct dentry *dentry)
diff --git a/fs/namespace.c b/fs/namespace.c
index 3dbfc07..3ddfd90 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -138,6 +138,64 @@
 	mnt->mnt_group_id = 0;
 }
 
+/*
+ * vfsmount lock must be held for read
+ */
+static inline void mnt_add_count(struct vfsmount *mnt, int n)
+{
+#ifdef CONFIG_SMP
+	this_cpu_add(mnt->mnt_pcp->mnt_count, n);
+#else
+	preempt_disable();
+	mnt->mnt_count += n;
+	preempt_enable();
+#endif
+}
+
+static inline void mnt_set_count(struct vfsmount *mnt, int n)
+{
+#ifdef CONFIG_SMP
+	this_cpu_write(mnt->mnt_pcp->mnt_count, n);
+#else
+	mnt->mnt_count = n;
+#endif
+}
+
+/*
+ * vfsmount lock must be held for read
+ */
+static inline void mnt_inc_count(struct vfsmount *mnt)
+{
+	mnt_add_count(mnt, 1);
+}
+
+/*
+ * vfsmount lock must be held for read
+ */
+static inline void mnt_dec_count(struct vfsmount *mnt)
+{
+	mnt_add_count(mnt, -1);
+}
+
+/*
+ * vfsmount lock must be held for write
+ */
+unsigned int mnt_get_count(struct vfsmount *mnt)
+{
+#ifdef CONFIG_SMP
+	unsigned int count = atomic_read(&mnt->mnt_longrefs);
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count;
+	}
+
+	return count;
+#else
+	return mnt->mnt_count;
+#endif
+}
+
 struct vfsmount *alloc_vfsmnt(const char *name)
 {
 	struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
@@ -154,7 +212,17 @@
 				goto out_free_id;
 		}
 
-		atomic_set(&mnt->mnt_count, 1);
+#ifdef CONFIG_SMP
+		mnt->mnt_pcp = alloc_percpu(struct mnt_pcp);
+		if (!mnt->mnt_pcp)
+			goto out_free_devname;
+
+		atomic_set(&mnt->mnt_longrefs, 1);
+#else
+		mnt->mnt_count = 1;
+		mnt->mnt_writers = 0;
+#endif
+
 		INIT_LIST_HEAD(&mnt->mnt_hash);
 		INIT_LIST_HEAD(&mnt->mnt_child);
 		INIT_LIST_HEAD(&mnt->mnt_mounts);
@@ -166,13 +234,6 @@
 #ifdef CONFIG_FSNOTIFY
 		INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks);
 #endif
-#ifdef CONFIG_SMP
-		mnt->mnt_writers = alloc_percpu(int);
-		if (!mnt->mnt_writers)
-			goto out_free_devname;
-#else
-		mnt->mnt_writers = 0;
-#endif
 	}
 	return mnt;
 
@@ -216,32 +277,32 @@
 }
 EXPORT_SYMBOL_GPL(__mnt_is_readonly);
 
-static inline void inc_mnt_writers(struct vfsmount *mnt)
+static inline void mnt_inc_writers(struct vfsmount *mnt)
 {
 #ifdef CONFIG_SMP
-	(*per_cpu_ptr(mnt->mnt_writers, smp_processor_id()))++;
+	this_cpu_inc(mnt->mnt_pcp->mnt_writers);
 #else
 	mnt->mnt_writers++;
 #endif
 }
 
-static inline void dec_mnt_writers(struct vfsmount *mnt)
+static inline void mnt_dec_writers(struct vfsmount *mnt)
 {
 #ifdef CONFIG_SMP
-	(*per_cpu_ptr(mnt->mnt_writers, smp_processor_id()))--;
+	this_cpu_dec(mnt->mnt_pcp->mnt_writers);
 #else
 	mnt->mnt_writers--;
 #endif
 }
 
-static unsigned int count_mnt_writers(struct vfsmount *mnt)
+static unsigned int mnt_get_writers(struct vfsmount *mnt)
 {
 #ifdef CONFIG_SMP
 	unsigned int count = 0;
 	int cpu;
 
 	for_each_possible_cpu(cpu) {
-		count += *per_cpu_ptr(mnt->mnt_writers, cpu);
+		count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_writers;
 	}
 
 	return count;
@@ -273,9 +334,9 @@
 	int ret = 0;
 
 	preempt_disable();
-	inc_mnt_writers(mnt);
+	mnt_inc_writers(mnt);
 	/*
-	 * The store to inc_mnt_writers must be visible before we pass
+	 * The store to mnt_inc_writers must be visible before we pass
 	 * MNT_WRITE_HOLD loop below, so that the slowpath can see our
 	 * incremented count after it has set MNT_WRITE_HOLD.
 	 */
@@ -289,7 +350,7 @@
 	 */
 	smp_rmb();
 	if (__mnt_is_readonly(mnt)) {
-		dec_mnt_writers(mnt);
+		mnt_dec_writers(mnt);
 		ret = -EROFS;
 		goto out;
 	}
@@ -317,7 +378,7 @@
 	if (__mnt_is_readonly(mnt))
 		return -EROFS;
 	preempt_disable();
-	inc_mnt_writers(mnt);
+	mnt_inc_writers(mnt);
 	preempt_enable();
 	return 0;
 }
@@ -351,7 +412,7 @@
 void mnt_drop_write(struct vfsmount *mnt)
 {
 	preempt_disable();
-	dec_mnt_writers(mnt);
+	mnt_dec_writers(mnt);
 	preempt_enable();
 }
 EXPORT_SYMBOL_GPL(mnt_drop_write);
@@ -384,7 +445,7 @@
 	 * MNT_WRITE_HOLD, so it can't be decremented by another CPU while
 	 * we're counting up here.
 	 */
-	if (count_mnt_writers(mnt) > 0)
+	if (mnt_get_writers(mnt) > 0)
 		ret = -EBUSY;
 	else
 		mnt->mnt_flags |= MNT_READONLY;
@@ -418,7 +479,7 @@
 	kfree(mnt->mnt_devname);
 	mnt_free_id(mnt);
 #ifdef CONFIG_SMP
-	free_percpu(mnt->mnt_writers);
+	free_percpu(mnt->mnt_pcp);
 #endif
 	kmem_cache_free(mnt_cache, mnt);
 }
@@ -492,6 +553,27 @@
 }
 
 /*
+ * Clear dentry's mounted state if it has no remaining mounts.
+ * vfsmount_lock must be held for write.
+ */
+static void dentry_reset_mounted(struct vfsmount *mnt, struct dentry *dentry)
+{
+	unsigned u;
+
+	for (u = 0; u < HASH_SIZE; u++) {
+		struct vfsmount *p;
+
+		list_for_each_entry(p, &mount_hashtable[u], mnt_hash) {
+			if (p->mnt_mountpoint == dentry)
+				return;
+		}
+	}
+	spin_lock(&dentry->d_lock);
+	dentry->d_flags &= ~DCACHE_MOUNTED;
+	spin_unlock(&dentry->d_lock);
+}
+
+/*
  * vfsmount lock must be held for write
  */
 static void detach_mnt(struct vfsmount *mnt, struct path *old_path)
@@ -502,7 +584,7 @@
 	mnt->mnt_mountpoint = mnt->mnt_root;
 	list_del_init(&mnt->mnt_child);
 	list_del_init(&mnt->mnt_hash);
-	old_path->dentry->d_mounted--;
+	dentry_reset_mounted(old_path->mnt, old_path->dentry);
 }
 
 /*
@@ -513,7 +595,9 @@
 {
 	child_mnt->mnt_parent = mntget(mnt);
 	child_mnt->mnt_mountpoint = dget(dentry);
-	dentry->d_mounted++;
+	spin_lock(&dentry->d_lock);
+	dentry->d_flags |= DCACHE_MOUNTED;
+	spin_unlock(&dentry->d_lock);
 }
 
 /*
@@ -629,9 +713,10 @@
 	return NULL;
 }
 
-static inline void __mntput(struct vfsmount *mnt)
+static inline void mntfree(struct vfsmount *mnt)
 {
 	struct super_block *sb = mnt->mnt_sb;
+
 	/*
 	 * This probably indicates that somebody messed
 	 * up a mnt_want/drop_write() pair.  If this
@@ -639,38 +724,123 @@
 	 * to make r/w->r/o transitions.
 	 */
 	/*
-	 * atomic_dec_and_lock() used to deal with ->mnt_count decrements
-	 * provides barriers, so count_mnt_writers() below is safe.  AV
+	 * The locking used to deal with mnt_count decrement provides barriers,
+	 * so mnt_get_writers() below is safe.
 	 */
-	WARN_ON(count_mnt_writers(mnt));
+	WARN_ON(mnt_get_writers(mnt));
 	fsnotify_vfsmount_delete(mnt);
 	dput(mnt->mnt_root);
 	free_vfsmnt(mnt);
 	deactivate_super(sb);
 }
 
-void mntput_no_expire(struct vfsmount *mnt)
+#ifdef CONFIG_SMP
+static inline void __mntput(struct vfsmount *mnt, int longrefs)
 {
-repeat:
-	if (atomic_add_unless(&mnt->mnt_count, -1, 1))
+	if (!longrefs) {
+put_again:
+		br_read_lock(vfsmount_lock);
+		if (likely(atomic_read(&mnt->mnt_longrefs))) {
+			mnt_dec_count(mnt);
+			br_read_unlock(vfsmount_lock);
+			return;
+		}
+		br_read_unlock(vfsmount_lock);
+	} else {
+		BUG_ON(!atomic_read(&mnt->mnt_longrefs));
+		if (atomic_add_unless(&mnt->mnt_longrefs, -1, 1))
+			return;
+	}
+
+	br_write_lock(vfsmount_lock);
+	if (!longrefs)
+		mnt_dec_count(mnt);
+	else
+		atomic_dec(&mnt->mnt_longrefs);
+	if (mnt_get_count(mnt)) {
+		br_write_unlock(vfsmount_lock);
+		return;
+	}
+	if (unlikely(mnt->mnt_pinned)) {
+		mnt_add_count(mnt, mnt->mnt_pinned + 1);
+		mnt->mnt_pinned = 0;
+		br_write_unlock(vfsmount_lock);
+		acct_auto_close_mnt(mnt);
+		goto put_again;
+	}
+	br_write_unlock(vfsmount_lock);
+	mntfree(mnt);
+}
+#else
+static inline void __mntput(struct vfsmount *mnt, int longrefs)
+{
+put_again:
+	mnt_dec_count(mnt);
+	if (likely(mnt_get_count(mnt)))
 		return;
 	br_write_lock(vfsmount_lock);
-	if (!atomic_dec_and_test(&mnt->mnt_count)) {
+	if (unlikely(mnt->mnt_pinned)) {
+		mnt_add_count(mnt, mnt->mnt_pinned + 1);
+		mnt->mnt_pinned = 0;
 		br_write_unlock(vfsmount_lock);
-		return;
+		acct_auto_close_mnt(mnt);
+		goto put_again;
 	}
-	if (likely(!mnt->mnt_pinned)) {
-		br_write_unlock(vfsmount_lock);
-		__mntput(mnt);
-		return;
-	}
-	atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count);
-	mnt->mnt_pinned = 0;
 	br_write_unlock(vfsmount_lock);
-	acct_auto_close_mnt(mnt);
-	goto repeat;
+	mntfree(mnt);
 }
-EXPORT_SYMBOL(mntput_no_expire);
+#endif
+
+static void mntput_no_expire(struct vfsmount *mnt)
+{
+	__mntput(mnt, 0);
+}
+
+void mntput(struct vfsmount *mnt)
+{
+	if (mnt) {
+		/* avoid cacheline pingpong, hope gcc doesn't get "smart" */
+		if (unlikely(mnt->mnt_expiry_mark))
+			mnt->mnt_expiry_mark = 0;
+		__mntput(mnt, 0);
+	}
+}
+EXPORT_SYMBOL(mntput);
+
+struct vfsmount *mntget(struct vfsmount *mnt)
+{
+	if (mnt)
+		mnt_inc_count(mnt);
+	return mnt;
+}
+EXPORT_SYMBOL(mntget);
+
+void mntput_long(struct vfsmount *mnt)
+{
+#ifdef CONFIG_SMP
+	if (mnt) {
+		/* avoid cacheline pingpong, hope gcc doesn't get "smart" */
+		if (unlikely(mnt->mnt_expiry_mark))
+			mnt->mnt_expiry_mark = 0;
+		__mntput(mnt, 1);
+	}
+#else
+	mntput(mnt);
+#endif
+}
+EXPORT_SYMBOL(mntput_long);
+
+struct vfsmount *mntget_long(struct vfsmount *mnt)
+{
+#ifdef CONFIG_SMP
+	if (mnt)
+		atomic_inc(&mnt->mnt_longrefs);
+	return mnt;
+#else
+	return mntget(mnt);
+#endif
+}
+EXPORT_SYMBOL(mntget_long);
 
 void mnt_pin(struct vfsmount *mnt)
 {
@@ -678,19 +848,17 @@
 	mnt->mnt_pinned++;
 	br_write_unlock(vfsmount_lock);
 }
-
 EXPORT_SYMBOL(mnt_pin);
 
 void mnt_unpin(struct vfsmount *mnt)
 {
 	br_write_lock(vfsmount_lock);
 	if (mnt->mnt_pinned) {
-		atomic_inc(&mnt->mnt_count);
+		mnt_inc_count(mnt);
 		mnt->mnt_pinned--;
 	}
 	br_write_unlock(vfsmount_lock);
 }
-
 EXPORT_SYMBOL(mnt_unpin);
 
 static inline void mangle(struct seq_file *m, const char *s)
@@ -985,12 +1153,13 @@
 	int minimum_refs = 0;
 	struct vfsmount *p;
 
-	br_read_lock(vfsmount_lock);
+	/* write lock needed for mnt_get_count */
+	br_write_lock(vfsmount_lock);
 	for (p = mnt; p; p = next_mnt(p, mnt)) {
-		actual_refs += atomic_read(&p->mnt_count);
+		actual_refs += mnt_get_count(p);
 		minimum_refs += 2;
 	}
-	br_read_unlock(vfsmount_lock);
+	br_write_unlock(vfsmount_lock);
 
 	if (actual_refs > minimum_refs)
 		return 0;
@@ -1017,10 +1186,10 @@
 {
 	int ret = 1;
 	down_read(&namespace_sem);
-	br_read_lock(vfsmount_lock);
+	br_write_lock(vfsmount_lock);
 	if (propagate_mount_busy(mnt, 2))
 		ret = 0;
-	br_read_unlock(vfsmount_lock);
+	br_write_unlock(vfsmount_lock);
 	up_read(&namespace_sem);
 	return ret;
 }
@@ -1047,7 +1216,7 @@
 			dput(dentry);
 			mntput(m);
 		}
-		mntput(mnt);
+		mntput_long(mnt);
 	}
 }
 
@@ -1073,7 +1242,7 @@
 		list_del_init(&p->mnt_child);
 		if (p->mnt_parent != p) {
 			p->mnt_parent->mnt_ghosts++;
-			p->mnt_mountpoint->d_mounted--;
+			dentry_reset_mounted(p->mnt_parent, p->mnt_mountpoint);
 		}
 		change_mnt_propagation(p, MS_PRIVATE);
 	}
@@ -1102,8 +1271,16 @@
 		    flags & (MNT_FORCE | MNT_DETACH))
 			return -EINVAL;
 
-		if (atomic_read(&mnt->mnt_count) != 2)
+		/*
+		 * probably don't strictly need the lock here if we examined
+		 * all race cases, but it's a slowpath.
+		 */
+		br_write_lock(vfsmount_lock);
+		if (mnt_get_count(mnt) != 2) {
+			br_write_lock(vfsmount_lock);
 			return -EBUSY;
+		}
+		br_write_unlock(vfsmount_lock);
 
 		if (!xchg(&mnt->mnt_expiry_mark, 1))
 			return -EAGAIN;
@@ -1792,7 +1969,7 @@
 
 unlock:
 	up_write(&namespace_sem);
-	mntput(newmnt);
+	mntput_long(newmnt);
 	return err;
 }
 
@@ -2125,11 +2302,11 @@
 		if (fs) {
 			if (p == fs->root.mnt) {
 				rootmnt = p;
-				fs->root.mnt = mntget(q);
+				fs->root.mnt = mntget_long(q);
 			}
 			if (p == fs->pwd.mnt) {
 				pwdmnt = p;
-				fs->pwd.mnt = mntget(q);
+				fs->pwd.mnt = mntget_long(q);
 			}
 		}
 		p = next_mnt(p, mnt_ns->root);
@@ -2138,9 +2315,9 @@
 	up_write(&namespace_sem);
 
 	if (rootmnt)
-		mntput(rootmnt);
+		mntput_long(rootmnt);
 	if (pwdmnt)
-		mntput(pwdmnt);
+		mntput_long(pwdmnt);
 
 	return new_ns;
 }
@@ -2327,6 +2504,7 @@
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
 	br_write_unlock(vfsmount_lock);
 	chroot_fs_refs(&root, &new);
+
 	error = 0;
 	path_put(&root_parent);
 	path_put(&parent_path);
@@ -2353,6 +2531,7 @@
 	mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
 	if (IS_ERR(mnt))
 		panic("Can't create rootfs");
+
 	ns = create_mnt_ns(mnt);
 	if (IS_ERR(ns))
 		panic("Can't allocate initial namespace");
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index f22b12e7..28f136d 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
+#include <linux/namei.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
@@ -74,9 +75,12 @@
  * Dentry operations routines
  */
 static int ncp_lookup_validate(struct dentry *, struct nameidata *);
-static int ncp_hash_dentry(struct dentry *, struct qstr *);
-static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
-static int ncp_delete_dentry(struct dentry *);
+static int ncp_hash_dentry(const struct dentry *, const struct inode *,
+		struct qstr *);
+static int ncp_compare_dentry(const struct dentry *, const struct inode *,
+		const struct dentry *, const struct inode *,
+		unsigned int, const char *, const struct qstr *);
+static int ncp_delete_dentry(const struct dentry *);
 
 static const struct dentry_operations ncp_dentry_operations =
 {
@@ -113,10 +117,10 @@
 
 #define ncp_preserve_case(i)	(ncp_namespace(i) != NW_NS_DOS)
 
-static inline int ncp_case_sensitive(struct dentry *dentry)
+static inline int ncp_case_sensitive(const struct inode *i)
 {
 #ifdef CONFIG_NCPFS_NFS_NS
-	return ncp_namespace(dentry->d_inode) == NW_NS_NFS;
+	return ncp_namespace(i) == NW_NS_NFS;
 #else
 	return 0;
 #endif /* CONFIG_NCPFS_NFS_NS */
@@ -127,14 +131,16 @@
  * is case-sensitive.
  */
 static int 
-ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
+ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *this)
 {
-	if (!ncp_case_sensitive(dentry)) {
+	if (!ncp_case_sensitive(inode)) {
+		struct super_block *sb = dentry->d_sb;
 		struct nls_table *t;
 		unsigned long hash;
 		int i;
 
-		t = NCP_IO_TABLE(dentry);
+		t = NCP_IO_TABLE(sb);
 		hash = init_name_hash();
 		for (i=0; i<this->len ; i++)
 			hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -145,15 +151,17 @@
 }
 
 static int
-ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
+ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	if (a->len != b->len)
+	if (len != name->len)
 		return 1;
 
-	if (ncp_case_sensitive(dentry))
-		return strncmp(a->name, b->name, a->len);
+	if (ncp_case_sensitive(pinode))
+		return strncmp(str, name->name, len);
 
-	return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
+	return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
 }
 
 /*
@@ -162,7 +170,7 @@
  * Closing files can be safely postponed until iput() - it's done there anyway.
  */
 static int
-ncp_delete_dentry(struct dentry * dentry)
+ncp_delete_dentry(const struct dentry * dentry)
 {
 	struct inode *inode = dentry->d_inode;
 
@@ -301,6 +309,9 @@
 	int res, val = 0, len;
 	__u8 __name[NCP_MAXPATHLEN + 1];
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
 
@@ -384,21 +395,21 @@
 	}
 
 	/* If a pointer is invalid, we search the dentry. */
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 	next = parent->d_subdirs.next;
 	while (next != &parent->d_subdirs) {
 		dent = list_entry(next, struct dentry, d_u.d_child);
 		if ((unsigned long)dent->d_fsdata == fpos) {
 			if (dent->d_inode)
-				dget_locked(dent);
+				dget(dent);
 			else
 				dent = NULL;
-			spin_unlock(&dcache_lock);
+			spin_unlock(&parent->d_lock);
 			goto out;
 		}
 		next = next->next;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&parent->d_lock);
 	return NULL;
 
 out:
@@ -592,7 +603,7 @@
 	qname.hash = full_name_hash(qname.name, qname.len);
 
 	if (dentry->d_op && dentry->d_op->d_hash)
-		if (dentry->d_op->d_hash(dentry, &qname) != 0)
+		if (dentry->d_op->d_hash(dentry, dentry->d_inode, &qname) != 0)
 			goto end_advance;
 
 	newdent = d_lookup(dentry, &qname);
@@ -611,35 +622,12 @@
 			shrink_dcache_parent(newdent);
 
 		/*
-		 * It is not as dangerous as it looks.  NetWare's OS2 namespace is
-		 * case preserving yet case insensitive.  So we update dentry's name
-		 * as received from server.  We found dentry via d_lookup with our
-		 * hash, so we know that hash does not change, and so replacing name
-		 * should be reasonably safe.
+		 * NetWare's OS2 namespace is case preserving yet case
+		 * insensitive.  So we update dentry's name as received from
+		 * server. Parent dir's i_mutex is locked because we're in
+		 * readdir.
 		 */
-		if (qname.len == newdent->d_name.len &&
-		    memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) {
-			struct inode *inode = newdent->d_inode;
-
-			/*
-			 * Inside ncpfs all uses of d_name are either for debugging,
-			 * or on functions which acquire inode mutex (mknod, creat,
-			 * lookup).  So grab i_mutex here, to be sure.  d_path
-			 * uses dcache_lock when generating path, so we should too.
-			 * And finally d_compare is protected by dentry's d_lock, so
-			 * here we go.
-			 */
-			if (inode)
-				mutex_lock(&inode->i_mutex);
-			spin_lock(&dcache_lock);
-			spin_lock(&newdent->d_lock);
-			memcpy((char *) newdent->d_name.name, qname.name,
-								newdent->d_name.len);
-			spin_unlock(&newdent->d_lock);
-			spin_unlock(&dcache_lock);
-			if (inode)
-				mutex_unlock(&inode->i_mutex);
-		}
+		dentry_update_name_case(newdent, &qname);
 	}
 
 	if (!newdent->d_inode) {
@@ -649,7 +637,7 @@
 		entry->ino = iunique(dir->i_sb, 2);
 		inode = ncp_iget(dir->i_sb, entry);
 		if (inode) {
-			newdent->d_op = &ncp_dentry_operations;
+			d_set_d_op(newdent, &ncp_dentry_operations);
 			d_instantiate(newdent, inode);
 			if (!hashed)
 				d_rehash(newdent);
@@ -657,7 +645,7 @@
 	} else {
 		struct inode *inode = newdent->d_inode;
 
-		mutex_lock(&inode->i_mutex);
+		mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
 		ncp_update_inode2(inode, entry);
 		mutex_unlock(&inode->i_mutex);
 	}
@@ -905,7 +893,7 @@
 	if (inode) {
 		ncp_new_dentry(dentry);
 add_entry:
-		dentry->d_op = &ncp_dentry_operations;
+		d_set_d_op(dentry, &ncp_dentry_operations);
 		d_add(dentry, inode);
 		error = 0;
 	}
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 8fb93b6..9b39a5d 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -29,6 +29,7 @@
 #include <linux/vfs.h>
 #include <linux/mount.h>
 #include <linux/seq_file.h>
+#include <linux/namei.h>
 
 #include <linux/ncp_fs.h>
 
@@ -58,9 +59,16 @@
 	return &ei->vfs_inode;
 }
 
+static void ncp_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(ncp_inode_cachep, NCP_FINFO(inode));
+}
+
 static void ncp_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
+	call_rcu(&inode->i_rcu, ncp_i_callback);
 }
 
 static void init_once(void *foo)
@@ -309,7 +317,12 @@
 	sk->sk_write_space  = server->write_space;
 	release_sock(sk);
 	del_timer_sync(&server->timeout_tm);
-	flush_scheduled_work();
+
+	flush_work_sync(&server->rcv.tq);
+	if (sk->sk_socket->type == SOCK_STREAM)
+		flush_work_sync(&server->tx.tq);
+	else
+		flush_work_sync(&server->timeout_tq);
 }
 
 static int  ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
@@ -710,7 +723,7 @@
 	sb->s_root = d_alloc_root(root_inode);
         if (!sb->s_root)
 		goto out_no_root;
-	sb->s_root->d_op = &ncp_root_dentry_operations;
+	d_set_d_op(sb->s_root, &ncp_root_dentry_operations);
 	return 0;
 
 out_no_root:
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 3c57eca..1220df7 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -135,7 +135,7 @@
 				const unsigned char *, unsigned int, int);
 
 #define NCP_ESC			':'
-#define NCP_IO_TABLE(dentry)	(NCP_SERVER((dentry)->d_inode)->nls_io)
+#define NCP_IO_TABLE(sb)	(NCP_SBP(sb)->nls_io)
 #define ncp_tolower(t, c)	nls_tolower(t, c)
 #define ncp_toupper(t, c)	nls_toupper(t, c)
 #define ncp_strnicmp(t, s1, s2, len) \
@@ -150,15 +150,15 @@
 int ncp__vol2io(unsigned char *, unsigned int *,
 				const unsigned char *, unsigned int, int);
 
-#define NCP_IO_TABLE(dentry)	NULL
+#define NCP_IO_TABLE(sb)	NULL
 #define ncp_tolower(t, c)	tolower(c)
 #define ncp_toupper(t, c)	toupper(c)
 #define ncp_io2vol(S,m,i,n,k,U)	ncp__io2vol(m,i,n,k,U)
 #define ncp_vol2io(S,m,i,n,k,U)	ncp__vol2io(m,i,n,k,U)
 
 
-static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
-		const unsigned char *s2, int len)
+static inline int ncp_strnicmp(const struct nls_table *t,
+		const unsigned char *s1, const unsigned char *s2, int len)
 {
 	while (len--) {
 		if (tolower(*s1++) != tolower(*s2++))
@@ -193,7 +193,7 @@
 	struct list_head *next;
 	struct dentry *dentry;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 	next = parent->d_subdirs.next;
 	while (next != &parent->d_subdirs) {
 		dentry = list_entry(next, struct dentry, d_u.d_child);
@@ -205,7 +205,7 @@
 
 		next = next->next;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&parent->d_lock);
 }
 
 static inline void
@@ -215,7 +215,7 @@
 	struct list_head *next;
 	struct dentry *dentry;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&parent->d_lock);
 	next = parent->d_subdirs.next;
 	while (next != &parent->d_subdirs) {
 		dentry = list_entry(next, struct dentry, d_u.d_child);
@@ -223,7 +223,7 @@
 		ncp_age_dentry(server, dentry);
 		next = next->next;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&parent->d_lock);
 }
 
 struct ncp_cache_head {
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 996dd89..d33da53 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -438,7 +438,7 @@
 	if (dentry == NULL)
 		return;
 
-	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+	d_set_d_op(dentry, NFS_PROTO(dir)->dentry_ops);
 	inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
 	if (IS_ERR(inode))
 		goto out;
@@ -938,7 +938,8 @@
  * component of the path.
  * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
  */
-static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
+static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
+						unsigned int mask)
 {
 	if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
 		return 0;
@@ -1018,7 +1019,7 @@
  * If the parent directory is seen to have changed, we throw out the
  * cached dentry and do a new lookup.
  */
-static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
+static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *dir;
 	struct inode *inode;
@@ -1027,6 +1028,9 @@
 	struct nfs_fattr *fattr = NULL;
 	int error;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
 	nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
@@ -1117,7 +1121,7 @@
 /*
  * This is called from dput() when d_count is going to 0.
  */
-static int nfs_dentry_delete(struct dentry *dentry)
+static int nfs_dentry_delete(const struct dentry *dentry)
 {
 	dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -1188,7 +1192,7 @@
 	if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
 		goto out;
 
-	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+	d_set_d_op(dentry, NFS_PROTO(dir)->dentry_ops);
 
 	/*
 	 * If we're doing an exclusive create, optimize away the lookup
@@ -1333,7 +1337,7 @@
 		res = ERR_PTR(-ENAMETOOLONG);
 		goto out;
 	}
-	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+	d_set_d_op(dentry, NFS_PROTO(dir)->dentry_ops);
 
 	/* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
 	 * the dentry. */
@@ -1718,11 +1722,9 @@
 	dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id,
 		dir->i_ino, dentry->d_name.name);
 
-	spin_lock(&dcache_lock);
 	spin_lock(&dentry->d_lock);
-	if (atomic_read(&dentry->d_count) > 1) {
+	if (dentry->d_count > 1) {
 		spin_unlock(&dentry->d_lock);
-		spin_unlock(&dcache_lock);
 		/* Start asynchronous writeout of the inode */
 		write_inode_now(dentry->d_inode, 0);
 		error = nfs_sillyrename(dir, dentry);
@@ -1733,7 +1735,6 @@
 		need_rehash = 1;
 	}
 	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
 	error = nfs_safe_remove(dentry);
 	if (!error || error == -ENOENT) {
 		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -1868,7 +1869,7 @@
 	dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
 		 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 		 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-		 atomic_read(&new_dentry->d_count));
+		 new_dentry->d_count);
 
 	/*
 	 * For non-directories, check whether the target is busy and if so,
@@ -1886,7 +1887,7 @@
 			rehash = new_dentry;
 		}
 
-		if (atomic_read(&new_dentry->d_count) > 2) {
+		if (new_dentry->d_count > 2) {
 			int err;
 
 			/* copy the target dentry's name */
@@ -2188,11 +2189,14 @@
 	return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
 }
 
-int nfs_permission(struct inode *inode, int mask)
+int nfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	struct rpc_cred *cred;
 	int res = 0;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	nfs_inc_stats(inode, NFSIOS_VFSACCESS);
 
 	if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
@@ -2240,7 +2244,7 @@
 out_notsup:
 	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	if (res == 0)
-		res = generic_permission(inode, mask, NULL);
+		res = generic_permission(inode, mask, flags, NULL);
 	goto out;
 }
 
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index ac7b814..5596c6a 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -63,9 +63,11 @@
 		 * This again causes shrink_dcache_for_umount_subtree() to
 		 * Oops, since the test for IS_ROOT() will fail.
 		 */
-		spin_lock(&dcache_lock);
+		spin_lock(&sb->s_root->d_inode->i_lock);
+		spin_lock(&sb->s_root->d_lock);
 		list_del_init(&sb->s_root->d_alias);
-		spin_unlock(&dcache_lock);
+		spin_unlock(&sb->s_root->d_lock);
+		spin_unlock(&sb->s_root->d_inode->i_lock);
 	}
 	return 0;
 }
@@ -119,7 +121,7 @@
 	security_d_instantiate(ret, inode);
 
 	if (ret->d_op == NULL)
-		ret->d_op = server->nfs_client->rpc_ops->dentry_ops;
+		d_set_d_op(ret, server->nfs_client->rpc_ops->dentry_ops);
 out:
 	nfs_free_fattr(fsinfo.fattr);
 	return ret;
@@ -226,7 +228,7 @@
 	security_d_instantiate(ret, inode);
 
 	if (ret->d_op == NULL)
-		ret->d_op = server->nfs_client->rpc_ops->dentry_ops;
+		d_set_d_op(ret, server->nfs_client->rpc_ops->dentry_ops);
 
 out:
 	nfs_free_fattr(fattr);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index e67e31c..017daa3 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1438,9 +1438,16 @@
 	return &nfsi->vfs_inode;
 }
 
+static void nfs_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(nfs_inode_cachep, NFS_I(inode));
+}
+
 void nfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(nfs_inode_cachep, NFS_I(inode));
+	call_rcu(&inode->i_rcu, nfs_i_callback);
 }
 
 static inline void nfs4_init_once(struct nfs_inode *nfsi)
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index db6aa36..74aaf39 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -49,12 +49,17 @@
 	       const struct dentry *dentry,
 	       char *buffer, ssize_t buflen)
 {
-	char *end = buffer+buflen;
+	char *end;
 	int namelen;
+	unsigned seq;
 
+rename_retry:
+	end = buffer+buflen;
 	*--end = '\0';
 	buflen--;
-	spin_lock(&dcache_lock);
+
+	seq = read_seqbegin(&rename_lock);
+	rcu_read_lock();
 	while (!IS_ROOT(dentry) && dentry != droot) {
 		namelen = dentry->d_name.len;
 		buflen -= namelen + 1;
@@ -65,7 +70,9 @@
 		*--end = '/';
 		dentry = dentry->d_parent;
 	}
-	spin_unlock(&dcache_lock);
+	rcu_read_unlock();
+	if (read_seqretry(&rename_lock, seq))
+		goto rename_retry;
 	if (*end != '/') {
 		if (--buflen < 0)
 			goto Elong;
@@ -82,7 +89,9 @@
 	memcpy(end, base, namelen);
 	return end;
 Elong_unlock:
-	spin_unlock(&dcache_lock);
+	rcu_read_unlock();
+	if (read_seqretry(&rename_lock, seq))
+		goto rename_retry;
 Elong:
 	return ERR_PTR(-ENAMETOOLONG);
 }
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 7bdec85..8fe9eb4 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -496,7 +496,7 @@
 
 	dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
-		atomic_read(&dentry->d_count));
+		dentry->d_count);
 	nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
 
 	/*
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 116cab9..fbd18c3 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4336,7 +4336,7 @@
 void
 nfs4_state_shutdown(void)
 {
-	cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work);
+	cancel_delayed_work_sync(&laundromat_work);
 	destroy_workqueue(laundry_wq);
 	locks_end_grace(&nfsd4_manager);
 	nfs4_lock_state();
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 184938f..3a35902 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1756,8 +1756,7 @@
 		goto out_dput_new;
 
 	if (svc_msnfs(ffhp) &&
-		((atomic_read(&odentry->d_count) > 1)
-		 || (atomic_read(&ndentry->d_count) > 1))) {
+		((odentry->d_count > 1) || (ndentry->d_count > 1))) {
 			host_err = -EPERM;
 			goto out_dput_new;
 	}
@@ -1843,7 +1842,7 @@
 	if (type != S_IFDIR) { /* It's UNLINK */
 #ifdef MSNFS
 		if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
-			(atomic_read(&rdentry->d_count) > 1)) {
+			(rdentry->d_count > 1)) {
 			host_err = -EPERM;
 		} else
 #endif
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 71d4bc8..77b48c8 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -785,15 +785,19 @@
 	return err;
 }
 
-int nilfs_permission(struct inode *inode, int mask)
+int nilfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
-	struct nilfs_root *root = NILFS_I(inode)->i_root;
+	struct nilfs_root *root;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
+	root = NILFS_I(inode)->i_root;
 	if ((mask & MAY_WRITE) && root &&
 	    root->cno != NILFS_CPTREE_CURRENT_CNO)
 		return -EROFS; /* snapshot is not writable */
 
-	return generic_permission(inode, mask, NULL);
+	return generic_permission(inode, mask, flags, NULL);
 }
 
 int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode,
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index f7560da..0ca9882 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -256,7 +256,7 @@
 extern void nilfs_truncate(struct inode *);
 extern void nilfs_evict_inode(struct inode *);
 extern int nilfs_setattr(struct dentry *, struct iattr *);
-int nilfs_permission(struct inode *inode, int mask);
+int nilfs_permission(struct inode *inode, int mask, unsigned int flags);
 extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *,
 				  struct buffer_head **);
 extern int nilfs_inode_dirty(struct inode *);
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index f804d41..e2dcc9c 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -162,10 +162,13 @@
 	return &ii->vfs_inode;
 }
 
-void nilfs_destroy_inode(struct inode *inode)
+static void nilfs_i_callback(struct rcu_head *head)
 {
+	struct inode *inode = container_of(head, struct inode, i_rcu);
 	struct nilfs_mdt_info *mdi = NILFS_MDT(inode);
 
+	INIT_LIST_HEAD(&inode->i_dentry);
+
 	if (mdi) {
 		kfree(mdi->mi_bgl); /* kfree(NULL) is safe */
 		kfree(mdi);
@@ -173,6 +176,11 @@
 	kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode));
 }
 
+void nilfs_destroy_inode(struct inode *inode)
+{
+	call_rcu(&inode->i_rcu, nilfs_i_callback);
+}
+
 static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag)
 {
 	struct the_nilfs *nilfs = sbi->s_nilfs;
@@ -838,7 +846,7 @@
 
 static int nilfs_tree_was_touched(struct dentry *root_dentry)
 {
-	return atomic_read(&root_dentry->d_count) > 1;
+	return root_dentry->d_count > 1;
 }
 
 /**
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 20dc218..79b47cb 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -59,7 +59,7 @@
 	/* determine if the children should tell inode about their events */
 	watched = fsnotify_inode_watches_children(inode);
 
-	spin_lock(&dcache_lock);
+	spin_lock(&inode->i_lock);
 	/* run all of the dentries associated with this inode.  Since this is a
 	 * directory, there damn well better only be one item on this list */
 	list_for_each_entry(alias, &inode->i_dentry, d_alias) {
@@ -68,19 +68,21 @@
 		/* run all of the children of the original inode and fix their
 		 * d_flags to indicate parental interest (their parent is the
 		 * original inode) */
+		spin_lock(&alias->d_lock);
 		list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
 			if (!child->d_inode)
 				continue;
 
-			spin_lock(&child->d_lock);
+			spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
 			if (watched)
 				child->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
 			else
 				child->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
 			spin_unlock(&child->d_lock);
 		}
+		spin_unlock(&alias->d_lock);
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 }
 
 /* Notify this dentry's parent about a child's events. */
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 93622b1..a627ed8 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -332,6 +332,13 @@
 	return NULL;
 }
 
+static void ntfs_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(ntfs_big_inode_cache, NTFS_I(inode));
+}
+
 void ntfs_destroy_big_inode(struct inode *inode)
 {
 	ntfs_inode *ni = NTFS_I(inode);
@@ -340,7 +347,7 @@
 	BUG_ON(ni->page);
 	if (!atomic_dec_and_test(&ni->count))
 		BUG();
-	kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode));
+	call_rcu(&inode->i_rcu, ntfs_i_callback);
 }
 
 static inline ntfs_inode *ntfs_alloc_extent_inode(void)
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 3919150..704f6b1 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -291,13 +291,17 @@
 	return ret;
 }
 
-int ocfs2_check_acl(struct inode *inode, int mask)
+int ocfs2_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_super *osb;
 	struct buffer_head *di_bh = NULL;
 	struct posix_acl *acl;
 	int ret = -EAGAIN;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
+	osb = OCFS2_SB(inode->i_sb);
 	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
 		return ret;
 
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
index 5c5d31f..4fe7c9c 100644
--- a/fs/ocfs2/acl.h
+++ b/fs/ocfs2/acl.h
@@ -26,7 +26,7 @@
 	__le32 e_id;
 };
 
-extern int ocfs2_check_acl(struct inode *, int);
+extern int ocfs2_check_acl(struct inode *, int, unsigned int);
 extern int ocfs2_acl_chmod(struct inode *);
 extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
 			  struct buffer_head *, struct buffer_head *,
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 9f26ac9..9e3d45b 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -307,8 +307,7 @@
 
 static void o2hb_disarm_write_timeout(struct o2hb_region *reg)
 {
-	cancel_delayed_work(&reg->hr_write_timeout_work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&reg->hr_write_timeout_work);
 }
 
 static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc)
diff --git a/fs/ocfs2/cluster/quorum.c b/fs/ocfs2/cluster/quorum.c
index cf3e166..a873667 100644
--- a/fs/ocfs2/cluster/quorum.c
+++ b/fs/ocfs2/cluster/quorum.c
@@ -325,5 +325,7 @@
 
 void o2quo_exit(void)
 {
-	flush_scheduled_work();
+	struct o2quo_state *qs = &o2quo_state;
+
+	flush_work_sync(&qs->qs_work);
 }
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 895532ac..6d80ecc 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -52,9 +52,15 @@
 static int ocfs2_dentry_revalidate(struct dentry *dentry,
 				   struct nameidata *nd)
 {
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode;
 	int ret = 0;    /* if all else fails, just return false */
-	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+	struct ocfs2_super *osb;
+
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = dentry->d_inode;
+	osb = OCFS2_SB(dentry->d_sb);
 
 	mlog_entry("(0x%p, '%.*s')\n", dentry,
 		   dentry->d_name.len, dentry->d_name.name);
@@ -169,23 +175,25 @@
 	struct list_head *p;
 	struct dentry *dentry = NULL;
 
-	spin_lock(&dcache_lock);
-
+	spin_lock(&inode->i_lock);
 	list_for_each(p, &inode->i_dentry) {
 		dentry = list_entry(p, struct dentry, d_alias);
 
+		spin_lock(&dentry->d_lock);
 		if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
 			mlog(0, "dentry found: %.*s\n",
 			     dentry->d_name.len, dentry->d_name.name);
 
-			dget_locked(dentry);
+			dget_dlock(dentry);
+			spin_unlock(&dentry->d_lock);
 			break;
 		}
+		spin_unlock(&dentry->d_lock);
 
 		dentry = NULL;
 	}
 
-	spin_unlock(&dcache_lock);
+	spin_unlock(&inode->i_lock);
 
 	return dentry;
 }
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
index b2df490..8c5c0ed 100644
--- a/fs/ocfs2/dlmfs/dlmfs.c
+++ b/fs/ocfs2/dlmfs/dlmfs.c
@@ -351,9 +351,16 @@
 	return &ip->ip_vfs_inode;
 }
 
+static void dlmfs_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(dlmfs_inode_cache, DLMFS_I(inode));
+}
+
 static void dlmfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode));
+	call_rcu(&inode->i_rcu, dlmfs_i_callback);
 }
 
 static void dlmfs_evict_inode(struct inode *inode)
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 19ad145..6adafa5 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -138,7 +138,7 @@
 
 	result = d_obtain_alias(inode);
 	if (!IS_ERR(result))
-		result->d_op = &ocfs2_dentry_ops;
+		d_set_d_op(result, &ocfs2_dentry_ops);
 	else
 		mlog_errno(PTR_ERR(result));
 
@@ -176,7 +176,7 @@
 
 	parent = d_obtain_alias(ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0));
 	if (!IS_ERR(parent))
-		parent->d_op = &ocfs2_dentry_ops;
+		d_set_d_op(parent, &ocfs2_dentry_ops);
 
 bail_unlock:
 	ocfs2_inode_unlock(dir, 0);
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index f6cba56..bdadbae0 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1307,10 +1307,13 @@
 	return err;
 }
 
-int ocfs2_permission(struct inode *inode, int mask)
+int ocfs2_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	int ret;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	mlog_entry_void();
 
 	ret = ocfs2_inode_lock(inode, NULL, 0);
@@ -1320,7 +1323,7 @@
 		goto out;
 	}
 
-	ret = generic_permission(inode, mask, ocfs2_check_acl);
+	ret = generic_permission(inode, mask, flags, ocfs2_check_acl);
 
 	ocfs2_inode_unlock(inode, 0);
 out:
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 97bf761..f5afbbe 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -61,7 +61,7 @@
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
 int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		  struct kstat *stat);
-int ocfs2_permission(struct inode *inode, int mask);
+int ocfs2_permission(struct inode *inode, int mask, unsigned int flags);
 
 int ocfs2_should_update_atime(struct inode *inode,
 			      struct vfsmount *vfsmnt);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index ff5744e..d14cad6 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -147,7 +147,7 @@
 	spin_unlock(&oi->ip_lock);
 
 bail_add:
-	dentry->d_op = &ocfs2_dentry_ops;
+	d_set_d_op(dentry, &ocfs2_dentry_ops);
 	ret = d_splice_alias(inode, dentry);
 
 	if (inode) {
@@ -415,7 +415,7 @@
 		mlog_errno(status);
 		goto leave;
 	}
-	dentry->d_op = &ocfs2_dentry_ops;
+	d_set_d_op(dentry, &ocfs2_dentry_ops);
 
 	status = ocfs2_add_entry(handle, dentry, inode,
 				 OCFS2_I(inode)->ip_blkno, parent_fe_bh,
@@ -743,7 +743,7 @@
 	}
 
 	ihold(inode);
-	dentry->d_op = &ocfs2_dentry_ops;
+	d_set_d_op(dentry, &ocfs2_dentry_ops);
 	d_instantiate(dentry, inode);
 
 out_commit:
@@ -1794,7 +1794,7 @@
 		mlog_errno(status);
 		goto bail;
 	}
-	dentry->d_op = &ocfs2_dentry_ops;
+	d_set_d_op(dentry, &ocfs2_dentry_ops);
 
 	status = ocfs2_add_entry(handle, dentry, inode,
 				 le64_to_cpu(fe->i_blkno), parent_fe_bh,
@@ -2459,7 +2459,7 @@
 		goto out_commit;
 	}
 
-	dentry->d_op = &ocfs2_dentry_ops;
+	d_set_d_op(dentry, &ocfs2_dentry_ops);
 	d_instantiate(dentry, inode);
 	status = 0;
 out_commit:
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index cfeab7c..17ff46f 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -569,9 +569,16 @@
 	return &oi->vfs_inode;
 }
 
+static void ocfs2_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(ocfs2_inode_cachep, OCFS2_I(inode));
+}
+
 static void ocfs2_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(ocfs2_inode_cachep, OCFS2_I(inode));
+	call_rcu(&inode->i_rcu, ocfs2_i_callback);
 }
 
 static unsigned long long ocfs2_max_file_offset(unsigned int bbits,
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 911e61f..a2a5bff 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -343,9 +343,16 @@
 	return &oi->vfs_inode;
 }
 
+static void openprom_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(op_inode_cachep, OP_I(inode));
+}
+
 static void openprom_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(op_inode_cachep, OP_I(inode));
+	call_rcu(&inode->i_rcu, openprom_i_callback);
 }
 
 static struct inode *openprom_iget(struct super_block *sb, ino_t ino)
diff --git a/fs/pipe.c b/fs/pipe.c
index 04629f3..68f1f8e 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -999,12 +999,12 @@
 		goto err;
 
 	err = -ENOMEM;
-	path.dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
+	path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &name);
 	if (!path.dentry)
 		goto err_inode;
 	path.mnt = mntget(pipe_mnt);
 
-	path.dentry->d_op = &pipefs_dentry_operations;
+	d_set_d_op(path.dentry, &pipefs_dentry_operations);
 	d_instantiate(path.dentry, inode);
 
 	err = -ENFILE;
@@ -1253,6 +1253,10 @@
 	return ret;
 }
 
+static const struct super_operations pipefs_ops = {
+	.destroy_inode = free_inode_nonrcu,
+};
+
 /*
  * pipefs should _never_ be mounted by userland - too much of security hassle,
  * no real gain from having the whole whorehouse mounted. So we don't need
@@ -1262,7 +1266,7 @@
 static struct dentry *pipefs_mount(struct file_system_type *fs_type,
 			 int flags, const char *dev_name, void *data)
 {
-	return mount_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
+	return mount_pseudo(fs_type, "pipe:", &pipefs_ops, PIPEFS_MAGIC);
 }
 
 static struct file_system_type pipe_fs_type = {
@@ -1288,7 +1292,7 @@
 static void __exit exit_pipe_fs(void)
 {
 	unregister_filesystem(&pipe_fs_type);
-	mntput(pipe_mnt);
+	mntput_long(pipe_mnt);
 }
 
 fs_initcall(init_pipe_fs);
diff --git a/fs/pnode.c b/fs/pnode.c
index 8066b8d..d42514e 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -288,7 +288,7 @@
  */
 static inline int do_refcount_check(struct vfsmount *mnt, int count)
 {
-	int mycount = atomic_read(&mnt->mnt_count) - mnt->mnt_ghosts;
+	int mycount = mnt_get_count(mnt) - mnt->mnt_ghosts;
 	return (mycount > count);
 }
 
@@ -300,7 +300,7 @@
  * Check if any of these mounts that **do not have submounts**
  * have more references than 'refcnt'. If so return busy.
  *
- * vfsmount lock must be held for read or write
+ * vfsmount lock must be held for write
  */
 int propagate_mount_busy(struct vfsmount *mnt, int refcnt)
 {
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 2758e2a..288a49e0 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -15,6 +15,7 @@
 proc-y	+= interrupts.o
 proc-y	+= loadavg.o
 proc-y	+= meminfo.o
+proc-y	+= proc_console.o
 proc-y	+= stat.o
 proc-y	+= uptime.o
 proc-y	+= version.o
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1828451..b20962c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1407,6 +1407,82 @@
 
 #endif
 
+#ifdef CONFIG_SCHED_AUTOGROUP
+/*
+ * Print out autogroup related information:
+ */
+static int sched_autogroup_show(struct seq_file *m, void *v)
+{
+	struct inode *inode = m->private;
+	struct task_struct *p;
+
+	p = get_proc_task(inode);
+	if (!p)
+		return -ESRCH;
+	proc_sched_autogroup_show_task(p, m);
+
+	put_task_struct(p);
+
+	return 0;
+}
+
+static ssize_t
+sched_autogroup_write(struct file *file, const char __user *buf,
+	    size_t count, loff_t *offset)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct task_struct *p;
+	char buffer[PROC_NUMBUF];
+	long nice;
+	int err;
+
+	memset(buffer, 0, sizeof(buffer));
+	if (count > sizeof(buffer) - 1)
+		count = sizeof(buffer) - 1;
+	if (copy_from_user(buffer, buf, count))
+		return -EFAULT;
+
+	err = strict_strtol(strstrip(buffer), 0, &nice);
+	if (err)
+		return -EINVAL;
+
+	p = get_proc_task(inode);
+	if (!p)
+		return -ESRCH;
+
+	err = nice;
+	err = proc_sched_autogroup_set_nice(p, &err);
+	if (err)
+		count = err;
+
+	put_task_struct(p);
+
+	return count;
+}
+
+static int sched_autogroup_open(struct inode *inode, struct file *filp)
+{
+	int ret;
+
+	ret = single_open(filp, sched_autogroup_show, NULL);
+	if (!ret) {
+		struct seq_file *m = filp->private_data;
+
+		m->private = inode;
+	}
+	return ret;
+}
+
+static const struct file_operations proc_pid_sched_autogroup_operations = {
+	.open		= sched_autogroup_open,
+	.read		= seq_read,
+	.write		= sched_autogroup_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+#endif /* CONFIG_SCHED_AUTOGROUP */
+
 static ssize_t comm_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *offset)
 {
@@ -1719,10 +1795,16 @@
  */
 static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *inode = dentry->d_inode;
-	struct task_struct *task = get_proc_task(inode);
+	struct inode *inode;
+	struct task_struct *task;
 	const struct cred *cred;
 
+	if (nd && nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = dentry->d_inode;
+	task = get_proc_task(inode);
+
 	if (task) {
 		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
 		    task_dumpable(task)) {
@@ -1744,7 +1826,7 @@
 	return 0;
 }
 
-static int pid_delete_dentry(struct dentry * dentry)
+static int pid_delete_dentry(const struct dentry * dentry)
 {
 	/* Is the task we represent dead?
 	 * If so, then don't put the dentry on the lru list,
@@ -1888,12 +1970,19 @@
 
 static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *inode = dentry->d_inode;
-	struct task_struct *task = get_proc_task(inode);
-	int fd = proc_fd(inode);
+	struct inode *inode;
+	struct task_struct *task;
+	int fd;
 	struct files_struct *files;
 	const struct cred *cred;
 
+	if (nd && nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = dentry->d_inode;
+	task = get_proc_task(inode);
+	fd = proc_fd(inode);
+
 	if (task) {
 		files = get_files_struct(task);
 		if (files) {
@@ -1969,7 +2058,7 @@
 	inode->i_op = &proc_pid_link_inode_operations;
 	inode->i_size = 64;
 	ei->op.proc_get_link = proc_fd_link;
-	dentry->d_op = &tid_fd_dentry_operations;
+	d_set_d_op(dentry, &tid_fd_dentry_operations);
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
 	if (tid_fd_revalidate(dentry, NULL))
@@ -2101,11 +2190,13 @@
  * /proc/pid/fd needs a special permission handler so that a process can still
  * access /proc/self/fd after it has executed a setuid().
  */
-static int proc_fd_permission(struct inode *inode, int mask)
+static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags)
 {
 	int rv;
 
-	rv = generic_permission(inode, mask, NULL);
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+	rv = generic_permission(inode, mask, flags, NULL);
 	if (rv == 0)
 		return 0;
 	if (task_pid(current) == proc_pid(inode))
@@ -2137,7 +2228,7 @@
 	ei->fd = fd;
 	inode->i_mode = S_IFREG | S_IRUSR;
 	inode->i_fop = &proc_fdinfo_file_operations;
-	dentry->d_op = &tid_fd_dentry_operations;
+	d_set_d_op(dentry, &tid_fd_dentry_operations);
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
 	if (tid_fd_revalidate(dentry, NULL))
@@ -2196,7 +2287,7 @@
 	if (p->fop)
 		inode->i_fop = p->fop;
 	ei->op = p->op;
-	dentry->d_op = &pid_dentry_operations;
+	d_set_d_op(dentry, &pid_dentry_operations);
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
 	if (pid_revalidate(dentry, NULL))
@@ -2563,8 +2654,14 @@
  */
 static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *inode = dentry->d_inode;
-	struct task_struct *task = get_proc_task(inode);
+	struct inode *inode;
+	struct task_struct *task;
+
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = dentry->d_inode;
+	task = get_proc_task(inode);
 	if (task) {
 		put_task_struct(task);
 		return 1;
@@ -2615,7 +2712,7 @@
 	if (p->fop)
 		inode->i_fop = p->fop;
 	ei->op = p->op;
-	dentry->d_op = &proc_base_dentry_operations;
+	d_set_d_op(dentry, &proc_base_dentry_operations);
 	d_add(dentry, inode);
 	error = NULL;
 out:
@@ -2733,6 +2830,9 @@
 #ifdef CONFIG_SCHED_DEBUG
 	REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
 #endif
+#ifdef CONFIG_SCHED_AUTOGROUP
+	REG("autogroup",  S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
+#endif
 	REG("comm",      S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 	INF("syscall",    S_IRUSR, proc_pid_syscall),
@@ -2926,7 +3026,7 @@
 	inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff,
 		ARRAY_SIZE(tgid_base_stuff));
 
-	dentry->d_op = &pid_dentry_operations;
+	d_set_d_op(dentry, &pid_dentry_operations);
 
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
@@ -3169,7 +3269,7 @@
 	inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff,
 		ARRAY_SIZE(tid_base_stuff));
 
-	dentry->d_op = &pid_dentry_operations;
+	d_set_d_op(dentry, &pid_dentry_operations);
 
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index dd29f03..f766be2 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -400,7 +400,7 @@
  * smarter: we could keep a "volatile" flag in the 
  * inode to indicate which ones to keep.
  */
-static int proc_delete_dentry(struct dentry * dentry)
+static int proc_delete_dentry(const struct dentry * dentry)
 {
 	return 1;
 }
@@ -439,7 +439,7 @@
 out_unlock:
 
 	if (inode) {
-		dentry->d_op = &proc_dentry_operations;
+		d_set_d_op(dentry, &proc_dentry_operations);
 		d_add(dentry, inode);
 		return NULL;
 	}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 3ddb606..6bcb926 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -65,9 +65,16 @@
 	return inode;
 }
 
+static void proc_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(proc_inode_cachep, PROC_I(inode));
+}
+
 static void proc_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(proc_inode_cachep, PROC_I(inode));
+	call_rcu(&inode->i_rcu, proc_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/proc/proc_console.c b/fs/proc/proc_console.c
new file mode 100644
index 0000000..8a70760
--- /dev/null
+++ b/fs/proc/proc_console.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010 Werner Fink, Jiri Slaby
+ *
+ * Licensed under GPLv2
+ */
+
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/tty_driver.h>
+
+/*
+ * This is handler for /proc/consoles
+ */
+static int show_console_dev(struct seq_file *m, void *v)
+{
+	static const struct {
+		short flag;
+		char name;
+	} con_flags[] = {
+		{ CON_ENABLED,		'E' },
+		{ CON_CONSDEV,		'C' },
+		{ CON_BOOT,		'B' },
+		{ CON_PRINTBUFFER,	'p' },
+		{ CON_BRL,		'b' },
+		{ CON_ANYTIME,		'a' },
+	};
+	char flags[ARRAY_SIZE(con_flags) + 1];
+	struct console *con = v;
+	unsigned int a;
+	int len;
+	dev_t dev = 0;
+
+	if (con->device) {
+		const struct tty_driver *driver;
+		int index;
+		driver = con->device(con, &index);
+		if (driver) {
+			dev = MKDEV(driver->major, driver->minor_start);
+			dev += index;
+		}
+	}
+
+	for (a = 0; a < ARRAY_SIZE(con_flags); a++)
+		flags[a] = (con->flags & con_flags[a].flag) ?
+			con_flags[a].name : ' ';
+	flags[a] = 0;
+
+	seq_printf(m, "%s%d%n", con->name, con->index, &len);
+	len = 21 - len;
+	if (len < 1)
+		len = 1;
+	seq_printf(m, "%*c%c%c%c (%s)", len, ' ', con->read ? 'R' : '-',
+			con->write ? 'W' : '-', con->unblank ? 'U' : '-',
+			flags);
+	if (dev)
+		seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev));
+
+	seq_printf(m, "\n");
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	struct console *con;
+	loff_t off = 0;
+
+	acquire_console_sem();
+	for_each_console(con)
+		if (off++ == *pos)
+			break;
+
+	return con;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct console *con = v;
+	++*pos;
+	return con->next;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+	release_console_sem();
+}
+
+static const struct seq_operations consoles_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_console_dev
+};
+
+static int consoles_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &consoles_op);
+}
+
+static const struct file_operations proc_consoles_operations = {
+	.open		= consoles_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int register_proc_consoles(void)
+{
+	proc_create("consoles", 0, NULL, &proc_consoles_operations);
+	return 0;
+}
+module_init(register_proc_consoles);
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index b652cb0..09a1f92 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -5,6 +5,7 @@
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
 #include <linux/security.h>
+#include <linux/namei.h>
 #include "internal.h"
 
 static const struct dentry_operations proc_sys_dentry_operations;
@@ -120,7 +121,7 @@
 		goto out;
 
 	err = NULL;
-	dentry->d_op = &proc_sys_dentry_operations;
+	d_set_d_op(dentry, &proc_sys_dentry_operations);
 	d_add(dentry, inode);
 
 out:
@@ -201,7 +202,7 @@
 				dput(child);
 				return -ENOMEM;
 			} else {
-				child->d_op = &proc_sys_dentry_operations;
+				d_set_d_op(child, &proc_sys_dentry_operations);
 				d_add(child, inode);
 			}
 		} else {
@@ -294,7 +295,7 @@
 	return ret;
 }
 
-static int proc_sys_permission(struct inode *inode, int mask)
+static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags)
 {
 	/*
 	 * sysctl entries that are not writeable,
@@ -304,6 +305,9 @@
 	struct ctl_table *table;
 	int error;
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	/* Executable files are not allowed under /proc/sys/ */
 	if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))
 		return -EACCES;
@@ -389,23 +393,30 @@
 
 static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
 	return !PROC_I(dentry->d_inode)->sysctl->unregistering;
 }
 
-static int proc_sys_delete(struct dentry *dentry)
+static int proc_sys_delete(const struct dentry *dentry)
 {
 	return !!PROC_I(dentry->d_inode)->sysctl->unregistering;
 }
 
-static int proc_sys_compare(struct dentry *dir, struct qstr *qstr,
-			    struct qstr *name)
+static int proc_sys_compare(const struct dentry *parent,
+		const struct inode *pinode,
+		const struct dentry *dentry, const struct inode *inode,
+		unsigned int len, const char *str, const struct qstr *name)
 {
-	struct dentry *dentry = container_of(qstr, struct dentry, d_name);
-	if (qstr->len != name->len)
+	/* Although proc doesn't have negative dentries, rcu-walk means
+	 * that inode here can be NULL */
+	if (!inode)
+		return 0;
+	if (name->len != len)
 		return 1;
-	if (memcmp(qstr->name, name->name, name->len))
+	if (memcmp(name->name, str, len))
 		return 1;
-	return !sysctl_is_seen(PROC_I(dentry->d_inode)->sysctl);
+	return !sysctl_is_seen(PROC_I(inode)->sysctl);
 }
 
 static const struct dentry_operations proc_sys_dentry_operations = {
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 2367fb3..74802bc5 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -499,7 +499,7 @@
 	/* Do some basic Verification. */
 	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
 		(ehdr.e_type != ET_CORE) ||
-		!vmcore_elf_check_arch(&ehdr) ||
+		!vmcore_elf64_check_arch(&ehdr) ||
 		ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
 		ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
 		ehdr.e_version != EV_CURRENT ||
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index fcada42..e63b417 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -425,9 +425,16 @@
 	return &ei->vfs_inode;
 }
 
+static void qnx4_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(qnx4_inode_cachep, qnx4_i(inode));
+}
+
 static void qnx4_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode));
+	call_rcu(&inode->i_rcu, qnx4_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b243117..2575682 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -529,9 +529,16 @@
 	return &ei->vfs_inode;
 }
 
+static void reiserfs_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(reiserfs_inode_cachep, REISERFS_I(inode));
+}
+
 static void reiserfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
+	call_rcu(&inode->i_rcu, reiserfs_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 5d04a78..3cfb2e9 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -870,11 +870,14 @@
 	return err;
 }
 
-static int reiserfs_check_acl(struct inode *inode, int mask)
+static int reiserfs_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
 	struct posix_acl *acl;
 	int error = -EAGAIN; /* do regular unix permission checks by default */
 
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
 	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
 
 	if (acl) {
@@ -951,8 +954,10 @@
 	return 0;
 }
 
-int reiserfs_permission(struct inode *inode, int mask)
+int reiserfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
 	/*
 	 * We don't do permission checks on the internal objects.
 	 * Permissions are determined by the "owning" object.
@@ -965,13 +970,16 @@
 	 * Stat data v1 doesn't support ACLs.
 	 */
 	if (get_inode_sd_version(inode) != STAT_DATA_V1)
-		return generic_permission(inode, mask, reiserfs_check_acl);
+		return generic_permission(inode, mask, flags,
+					reiserfs_check_acl);
 #endif
-	return generic_permission(inode, mask, NULL);
+	return generic_permission(inode, mask, flags, NULL);
 }
 
 static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
 	return -EPERM;
 }
 
@@ -990,7 +998,7 @@
 				strlen(PRIVROOT_NAME));
 	if (!IS_ERR(dentry)) {
 		REISERFS_SB(s)->priv_root = dentry;
-		dentry->d_op = &xattr_lookup_poison_ops;
+		d_set_d_op(dentry, &xattr_lookup_poison_ops);
 		if (dentry->d_inode)
 			dentry->d_inode->i_flags |= S_PRIVATE;
 	} else
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 6647f90..2305e31 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -400,9 +400,16 @@
 /*
  * return a spent inode to the slab cache
  */
+static void romfs_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(romfs_inode_cachep, ROMFS_I(inode));
+}
+
 static void romfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
+	call_rcu(&inode->i_rcu, romfs_i_callback);
 }
 
 /*
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 24de30b..20700b9 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -440,9 +440,16 @@
 }
 
 
+static void squashfs_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(squashfs_inode_cachep, squashfs_i(inode));
+}
+
 static void squashfs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode));
+	call_rcu(&inode->i_rcu, squashfs_i_callback);
 }
 
 
diff --git a/fs/super.c b/fs/super.c
index ca69615..823e061 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -30,6 +30,7 @@
 #include <linux/idr.h>
 #include <linux/mutex.h>
 #include <linux/backing-dev.h>
+#include <linux/rculist_bl.h>
 #include "internal.h"
 
 
@@ -71,7 +72,7 @@
 		INIT_LIST_HEAD(&s->s_files);
 #endif
 		INIT_LIST_HEAD(&s->s_instances);
-		INIT_HLIST_HEAD(&s->s_anon);
+		INIT_HLIST_BL_HEAD(&s->s_anon);
 		INIT_LIST_HEAD(&s->s_inodes);
 		INIT_LIST_HEAD(&s->s_dentry_lru);
 		init_rwsem(&s->s_umount);
@@ -1139,7 +1140,7 @@
 	return mnt;
 
  err:
-	mntput(mnt);
+	mntput_long(mnt);
 	return ERR_PTR(err);
 }
 
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 7e54bac..ea9120a 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -231,7 +231,7 @@
 		goto repeat;
 }
 
-static int sysfs_dentry_delete(struct dentry *dentry)
+static int sysfs_dentry_delete(const struct dentry *dentry)
 {
 	struct sysfs_dirent *sd = dentry->d_fsdata;
 	return !!(sd->s_flags & SYSFS_FLAG_REMOVED);
@@ -239,9 +239,13 @@
 
 static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct sysfs_dirent *sd;
 	int is_dir;
 
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	sd = dentry->d_fsdata;
 	mutex_lock(&sysfs_mutex);
 
 	/* The sysfs dirent has been deleted */
@@ -701,7 +705,7 @@
 	/* instantiate and hash dentry */
 	ret = d_find_alias(inode);
 	if (!ret) {
-		dentry->d_op = &sysfs_dentry_ops;
+		d_set_d_op(dentry, &sysfs_dentry_ops);
 		dentry->d_fsdata = sysfs_get(sd);
 		d_add(dentry, inode);
 	} else {
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index cffb1fd..30ac273 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -348,13 +348,18 @@
 		return -ENOENT;
 }
 
-int sysfs_permission(struct inode *inode, int mask)
+int sysfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
-	struct sysfs_dirent *sd = inode->i_private;
+	struct sysfs_dirent *sd;
+
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
+	sd = inode->i_private;
 
 	mutex_lock(&sysfs_mutex);
 	sysfs_refresh_inode(sd, inode);
 	mutex_unlock(&sysfs_mutex);
 
-	return generic_permission(inode, mask, NULL);
+	return generic_permission(inode, mask, flags, NULL);
 }
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index d9be60a..ffaaa81 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -200,7 +200,7 @@
 struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd);
 void sysfs_evict_inode(struct inode *inode);
 int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
-int sysfs_permission(struct inode *inode, int mask);
+int sysfs_permission(struct inode *inode, int mask, unsigned int flags);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
 int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
 int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index de44d06..0630eb96 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -333,9 +333,16 @@
 	return &si->vfs_inode;
 }
 
+static void sysv_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(sysv_inode_cachep, SYSV_I(inode));
+}
+
 static void sysv_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(sysv_inode_cachep, SYSV_I(inode));
+	call_rcu(&inode->i_rcu, sysv_i_callback);
 }
 
 static void init_once(void *p)
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index 11e7f7d..b5e68da 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -27,7 +27,8 @@
 	return err;
 }
 
-static int sysv_hash(struct dentry *dentry, struct qstr *qstr)
+static int sysv_hash(const struct dentry *dentry, const struct inode *inode,
+		struct qstr *qstr)
 {
 	/* Truncate the name in place, avoids having to define a compare
 	   function. */
@@ -47,7 +48,7 @@
 	struct inode * inode = NULL;
 	ino_t ino;
 
-	dentry->d_op = dir->i_sb->s_root->d_op;
+	d_set_d_op(dentry, dir->i_sb->s_root->d_op);
 	if (dentry->d_name.len > SYSV_NAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
 	ino = sysv_inode_by_name(dentry);
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 3d9c62b..76712ae 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -346,7 +346,7 @@
 	if (sbi->s_forced_ro)
 		sb->s_flags |= MS_RDONLY;
 	if (sbi->s_truncate)
-		sb->s_root->d_op = &sysv_dentry_operations;
+		d_set_d_op(sb->s_root, &sysv_dentry_operations);
 	return 1;
 }
 
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 91fac54..6e11c29 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -272,12 +272,20 @@
 	return &ui->vfs_inode;
 };
 
+static void ubifs_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+	struct ubifs_inode *ui = ubifs_inode(inode);
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kmem_cache_free(ubifs_inode_slab, ui);
+}
+
 static void ubifs_destroy_inode(struct inode *inode)
 {
 	struct ubifs_inode *ui = ubifs_inode(inode);
 
 	kfree(ui->data);
-	kmem_cache_free(ubifs_inode_slab, inode);
+	call_rcu(&inode->i_rcu, ubifs_i_callback);
 }
 
 /*
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 4a5c7c6..b539d53 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -139,9 +139,16 @@
 	return &ei->vfs_inode;
 }
 
+static void udf_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(udf_inode_cachep, UDF_I(inode));
+}
+
 static void udf_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(udf_inode_cachep, UDF_I(inode));
+	call_rcu(&inode->i_rcu, udf_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 2c47dae..2c61ac5 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -1412,9 +1412,16 @@
 	return &ei->vfs_inode;
 }
 
+static void ufs_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(ufs_inode_cachep, UFS_I(inode));
+}
+
 static void ufs_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(ufs_inode_cachep, UFS_I(inode));
+	call_rcu(&inode->i_rcu, ufs_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c
index b277186..39f4f80 100644
--- a/fs/xfs/linux-2.6/xfs_acl.c
+++ b/fs/xfs/linux-2.6/xfs_acl.c
@@ -219,12 +219,13 @@
 }
 
 int
-xfs_check_acl(struct inode *inode, int mask)
+xfs_check_acl(struct inode *inode, int mask, unsigned int flags)
 {
-	struct xfs_inode *ip = XFS_I(inode);
+	struct xfs_inode *ip;
 	struct posix_acl *acl;
 	int error = -EAGAIN;
 
+	ip = XFS_I(inode);
 	trace_xfs_check_acl(ip);
 
 	/*
@@ -234,6 +235,12 @@
 	if (!XFS_IFORK_Q(ip))
 		return -EAGAIN;
 
+	if (flags & IPERM_FLAG_RCU) {
+		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
+			return -ECHILD;
+		return -EAGAIN;
+	}
+
 	acl = xfs_get_acl(inode, ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 0135e2a..11dd720 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -42,7 +42,7 @@
 #define SGI_ACL_DEFAULT_SIZE	(sizeof(SGI_ACL_DEFAULT)-1)
 
 #ifdef CONFIG_XFS_POSIX_ACL
-extern int xfs_check_acl(struct inode *inode, int mask);
+extern int xfs_check_acl(struct inode *inode, int mask, unsigned int flags);
 extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
 extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl);
 extern int xfs_acl_chmod(struct inode *inode);
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 0cdd269..d7de5a3 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -91,6 +91,17 @@
 	return ip;
 }
 
+STATIC void
+xfs_inode_free_callback(
+	struct rcu_head		*head)
+{
+	struct inode		*inode = container_of(head, struct inode, i_rcu);
+	struct xfs_inode	*ip = XFS_I(inode);
+
+	INIT_LIST_HEAD(&inode->i_dentry);
+	kmem_zone_free(xfs_inode_zone, ip);
+}
+
 void
 xfs_inode_free(
 	struct xfs_inode	*ip)
@@ -134,7 +145,7 @@
 	ASSERT(!spin_is_locked(&ip->i_flags_lock));
 	ASSERT(completion_done(&ip->i_flush));
 
-	kmem_zone_free(xfs_inode_zone, ip);
+	call_rcu(&ip->i_vnode.i_rcu, xfs_inode_free_callback);
 }
 
 /*
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
index 45ce15d..edfa178 100644
--- a/fs/xfs/xfs_mru_cache.c
+++ b/fs/xfs/xfs_mru_cache.c
@@ -408,7 +408,7 @@
 	spin_lock(&mru->lock);
 	if (mru->queued) {
 		spin_unlock(&mru->lock);
-		cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
+		cancel_delayed_work_sync(&mru->work);
 		spin_lock(&mru->lock);
 	}
 
diff --git a/include/asm-generic/ioctls.h b/include/asm-generic/ioctls.h
index a321665..3f3f2d1 100644
--- a/include/asm-generic/ioctls.h
+++ b/include/asm-generic/ioctls.h
@@ -67,6 +67,7 @@
 #endif
 #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 TCGETX		0x5432 /* SYS5 TCGETX compatibility */
 #define TCSETX		0x5433
 #define TCSETXF		0x5434
diff --git a/include/asm-generic/irq_regs.h b/include/asm-generic/irq_regs.h
index 5ae1d07..6bf9355 100644
--- a/include/asm-generic/irq_regs.h
+++ b/include/asm-generic/irq_regs.h
@@ -22,15 +22,15 @@
 
 static inline struct pt_regs *get_irq_regs(void)
 {
-	return __get_cpu_var(__irq_regs);
+	return __this_cpu_read(__irq_regs);
 }
 
 static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
 {
-	struct pt_regs *old_regs, **pp_regs = &__get_cpu_var(__irq_regs);
+	struct pt_regs *old_regs;
 
-	old_regs = *pp_regs;
-	*pp_regs = new_regs;
+	old_regs = __this_cpu_read(__irq_regs);
+	__this_cpu_write(__irq_regs, new_regs);
 	return old_regs;
 }
 
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 97319a8..a354c19 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -367,7 +367,6 @@
 header-y += utsname.h
 header-y += veth.h
 header-y += vhost.h
-header-y += videodev.h
 header-y += videodev2.h
 header-y += virtio_9p.h
 header-y += virtio_balloon.h
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index c6454cc..9e7f259 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/resource.h>
+#include <linux/regulator/consumer.h>
 
 #define AMBA_NR_IRQS	2
 #define AMBA_CID	0xb105f00d
@@ -28,6 +29,7 @@
 	struct device		dev;
 	struct resource		res;
 	struct clk		*pclk;
+	struct regulator	*vcore;
 	u64			dma_mask;
 	unsigned int		periphid;
 	unsigned int		irq[AMBA_NR_IRQS];
@@ -71,6 +73,12 @@
 #define amba_pclk_disable(d)	\
 	do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
 
+#define amba_vcore_enable(d)	\
+	(IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore))
+
+#define amba_vcore_disable(d)	\
+	do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0)
+
 /* Some drivers don't use the struct amba_device */
 #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
 #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index 6021588..5479fdc 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -113,6 +113,21 @@
 #define UART01x_LCRH_PEN	0x02
 #define UART01x_LCRH_BRK	0x01
 
+#define ST_UART011_DMAWM_RX_1	(0 << 3)
+#define ST_UART011_DMAWM_RX_2	(1 << 3)
+#define ST_UART011_DMAWM_RX_4	(2 << 3)
+#define ST_UART011_DMAWM_RX_8	(3 << 3)
+#define ST_UART011_DMAWM_RX_16	(4 << 3)
+#define ST_UART011_DMAWM_RX_32	(5 << 3)
+#define ST_UART011_DMAWM_RX_48	(6 << 3)
+#define ST_UART011_DMAWM_TX_1	0
+#define ST_UART011_DMAWM_TX_2	1
+#define ST_UART011_DMAWM_TX_4	2
+#define ST_UART011_DMAWM_TX_8	3
+#define ST_UART011_DMAWM_TX_16	4
+#define ST_UART011_DMAWM_TX_32	5
+#define ST_UART011_DMAWM_TX_48	6
+
 #define UART010_IIR_RTIS	0x08
 #define UART010_IIR_TIS		0x04
 #define UART010_IIR_RIS		0x02
@@ -180,6 +195,13 @@
 struct amba_pl010_data {
 	void (*set_mctrl)(struct amba_device *dev, void __iomem *base, unsigned int mctrl);
 };
+
+struct dma_chan;
+struct amba_pl011_data {
+	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+	void *dma_rx_param;
+	void *dma_tx_param;
+};
 #endif
 
 #endif
diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h
index 7113a32..e612575 100644
--- a/include/linux/bit_spinlock.h
+++ b/include/linux/bit_spinlock.h
@@ -1,6 +1,10 @@
 #ifndef __LINUX_BIT_SPINLOCK_H
 #define __LINUX_BIT_SPINLOCK_H
 
+#include <linux/kernel.h>
+#include <linux/preempt.h>
+#include <asm/atomic.h>
+
 /*
  *  bit-based spin_lock()
  *
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
new file mode 100644
index 0000000..457bcb0
--- /dev/null
+++ b/include/linux/clkdev.h
@@ -0,0 +1,36 @@
+/*
+ *  include/linux/clkdev.h
+ *
+ *  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.
+ */
+#ifndef __CLKDEV_H
+#define __CLKDEV_H
+
+#include <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, ...);
+
+void clkdev_add(struct clk_lookup *cl);
+void clkdev_drop(struct clk_lookup *cl);
+
+void clkdev_add_table(struct clk_lookup *, size_t);
+int clk_add_alias(const char *, const char *, char *, struct device *);
+
+#endif
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index 2e914d0..4ccc59c 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -37,7 +37,7 @@
 /* operations shared over more than one file */
 int coda_open(struct inode *i, struct file *f);
 int coda_release(struct inode *i, struct file *f);
-int coda_permission(struct inode *inode, int mask);
+int coda_permission(struct inode *inode, int mask, unsigned int flags);
 int coda_revalidate_inode(struct dentry *);
 int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int coda_setattr(struct dentry *, struct iattr *);
diff --git a/include/linux/completion.h b/include/linux/completion.h
index 36d57f74..51494e6 100644
--- a/include/linux/completion.h
+++ b/include/linux/completion.h
@@ -81,10 +81,10 @@
 extern int wait_for_completion_killable(struct completion *x);
 extern unsigned long wait_for_completion_timeout(struct completion *x,
 						   unsigned long timeout);
-extern unsigned long wait_for_completion_interruptible_timeout(
-			struct completion *x, unsigned long timeout);
-extern unsigned long wait_for_completion_killable_timeout(
-			struct completion *x, unsigned long timeout);
+extern long wait_for_completion_interruptible_timeout(
+	struct completion *x, unsigned long timeout);
+extern long wait_for_completion_killable_timeout(
+	struct completion *x, unsigned long timeout);
 extern bool try_wait_for_completion(struct completion *x);
 extern bool completion_done(struct completion *x);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 95cf6f0..9774fe6 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -126,6 +126,12 @@
 	struct	 console *next;
 };
 
+/*
+ * for_each_console() allows you to iterate on each console
+ */
+#define for_each_console(con) \
+	for (con = console_drivers; con != NULL; con = con->next)
+
 extern int console_set_on_cmdline;
 
 extern int add_preferred_console(char *name, int idx, char *options);
@@ -145,7 +151,7 @@
 extern int braille_register_console(struct console *, int index,
 		char *console_options, char *braille_options);
 extern int braille_unregister_console(struct console *);
-
+extern void console_sysfs_notify(void);
 extern int console_suspend_enabled;
 
 /* Suspend and resume console messages over PM events */
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 0026f26..088cd4a 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -20,7 +20,14 @@
 #define vmcore_elf_check_arch_cross(x) 0
 #endif
 
-#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+/*
+ * Architecture code can redefine this if there are any special checks
+ * needed for 64-bit ELF vmcores. In case of 32-bit only architecture,
+ * this can be set to zero.
+ */
+#ifndef vmcore_elf64_check_arch
+#define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+#endif
 
 /*
  * is_kdump_kernel() checks whether this kernel is booting after a panic of
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 6a4aea3..bd07758 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -4,7 +4,9 @@
 #include <asm/atomic.h>
 #include <linux/list.h>
 #include <linux/rculist.h>
+#include <linux/rculist_bl.h>
 #include <linux/spinlock.h>
+#include <linux/seqlock.h>
 #include <linux/cache.h>
 #include <linux/rcupdate.h>
 
@@ -45,6 +47,27 @@
 };
 extern struct dentry_stat_t dentry_stat;
 
+/*
+ * Compare 2 name strings, return 0 if they match, otherwise non-zero.
+ * The strings are both count bytes long, and count is non-zero.
+ */
+static inline int dentry_cmp(const unsigned char *cs, size_t scount,
+				const unsigned char *ct, size_t tcount)
+{
+	int ret;
+	if (scount != tcount)
+		return 1;
+	do {
+		ret = (*cs != *ct);
+		if (ret)
+			break;
+		cs++;
+		ct++;
+		tcount--;
+	} while (tcount);
+	return ret;
+}
+
 /* Name hashing routines. Initial hash value */
 /* Hash courtesy of the R5 hash in reiserfs modulo sign bits */
 #define init_name_hash()		0
@@ -81,25 +104,33 @@
  * large memory footprint increase).
  */
 #ifdef CONFIG_64BIT
-#define DNAME_INLINE_LEN_MIN 32 /* 192 bytes */
+# define DNAME_INLINE_LEN 32 /* 192 bytes */
 #else
-#define DNAME_INLINE_LEN_MIN 40 /* 128 bytes */
+# ifdef CONFIG_SMP
+#  define DNAME_INLINE_LEN 36 /* 128 bytes */
+# else
+#  define DNAME_INLINE_LEN 40 /* 128 bytes */
+# endif
 #endif
 
 struct dentry {
-	atomic_t d_count;
+	/* RCU lookup touched fields */
 	unsigned int d_flags;		/* protected by d_lock */
-	spinlock_t d_lock;		/* per dentry lock */
-	int d_mounted;
-	struct inode *d_inode;		/* Where the name belongs to - NULL is
-					 * negative */
-	/*
-	 * The next three fields are touched by __d_lookup.  Place them here
-	 * so they all fit in a cache line.
-	 */
-	struct hlist_node d_hash;	/* lookup hash list */
+	seqcount_t d_seq;		/* per dentry seqlock */
+	struct hlist_bl_node d_hash;	/* lookup hash list */
 	struct dentry *d_parent;	/* parent directory */
 	struct qstr d_name;
+	struct inode *d_inode;		/* Where the name belongs to - NULL is
+					 * negative */
+	unsigned char d_iname[DNAME_INLINE_LEN];	/* small names */
+
+	/* Ref lookup also touches following */
+	unsigned int d_count;		/* protected by d_lock */
+	spinlock_t d_lock;		/* per dentry lock */
+	const struct dentry_operations *d_op;
+	struct super_block *d_sb;	/* The root of the dentry tree */
+	unsigned long d_time;		/* used by d_revalidate */
+	void *d_fsdata;			/* fs-specific data */
 
 	struct list_head d_lru;		/* LRU list */
 	/*
@@ -111,12 +142,6 @@
 	} d_u;
 	struct list_head d_subdirs;	/* our children */
 	struct list_head d_alias;	/* inode alias list */
-	unsigned long d_time;		/* used by d_revalidate */
-	const struct dentry_operations *d_op;
-	struct super_block *d_sb;	/* The root of the dentry tree */
-	void *d_fsdata;			/* fs-specific data */
-
-	unsigned char d_iname[DNAME_INLINE_LEN_MIN];	/* small names */
 };
 
 /*
@@ -133,97 +158,62 @@
 
 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);
-};
-
-/* the dentry parameter passed to d_hash and d_compare is the parent
- * directory of the entries to be compared. It is used in case these
- * functions need any directory specific information for determining
- * equivalency classes.  Using the dentry itself might not work, as it
- * might be a negative dentry which has no information associated with
- * it */
+} ____cacheline_aligned;
 
 /*
-locking rules:
-		big lock	dcache_lock	d_lock   may block
-d_revalidate:	no		no		no       yes
-d_hash		no		no		no       yes
-d_compare:	no		yes		yes      no
-d_delete:	no		yes		no       no
-d_release:	no		no		no       yes
-d_iput:		no		no		no       yes
+ * Locking rules for dentry_operations callbacks are to be found in
+ * Documentation/filesystems/Locking. Keep it updated!
+ *
+ * FUrther descriptions are found in Documentation/filesystems/vfs.txt.
+ * Keep it updated too!
  */
 
 /* d_flags entries */
 #define DCACHE_AUTOFS_PENDING 0x0001    /* autofs: "under construction" */
-#define DCACHE_NFSFS_RENAMED  0x0002    /* this dentry has been "silly
-					 * renamed" and has to be
-					 * deleted on the last dput()
-					 */
-#define	DCACHE_DISCONNECTED 0x0004
-     /* This dentry is possibly not currently connected to the dcache tree,
-      * in which case its parent will either be itself, or will have this
-      * flag as well.  nfsd will not use a dentry with this bit set, but will
-      * first endeavour to clear the bit either by discovering that it is
-      * connected, or by performing lookup operations.   Any filesystem which
-      * supports nfsd_operations MUST have a lookup function which, if it finds
-      * a directory inode with a DCACHE_DISCONNECTED dentry, will d_move
-      * that dentry into place and return that dentry rather than the passed one,
-      * typically using d_splice_alias.
-      */
+#define DCACHE_NFSFS_RENAMED  0x0002
+     /* this dentry has been "silly renamed" and has to be deleted on the last
+      * dput() */
+
+#define	DCACHE_DISCONNECTED	0x0004
+     /* This dentry is possibly not currently connected to the dcache tree, in
+      * which case its parent will either be itself, or will have this flag as
+      * well.  nfsd will not use a dentry with this bit set, but will first
+      * endeavour to clear the bit either by discovering that it is connected,
+      * or by performing lookup operations.   Any filesystem which supports
+      * nfsd_operations MUST have a lookup function which, if it finds a
+      * directory inode with a DCACHE_DISCONNECTED dentry, will d_move that
+      * dentry into place and return that dentry rather than the passed one,
+      * typically using d_splice_alias. */
 
 #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
 #define DCACHE_UNHASHED		0x0010	
-
-#define DCACHE_INOTIFY_PARENT_WATCHED	0x0020 /* Parent inode is watched by inotify */
+#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
+     /* Parent inode is watched by inotify */
 
 #define DCACHE_COOKIE		0x0040	/* For use by dcookie subsystem */
-
-#define DCACHE_FSNOTIFY_PARENT_WATCHED	0x0080 /* Parent inode is watched by some fsnotify listener */
+#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080
+     /* Parent inode is watched by some fsnotify listener */
 
 #define DCACHE_CANT_MOUNT	0x0100
+#define DCACHE_GENOCIDE		0x0200
+#define DCACHE_MOUNTED		0x0400	/* is a mountpoint */
 
-extern spinlock_t dcache_lock;
+#define DCACHE_OP_HASH		0x1000
+#define DCACHE_OP_COMPARE	0x2000
+#define DCACHE_OP_REVALIDATE	0x4000
+#define DCACHE_OP_DELETE	0x8000
+
 extern seqlock_t rename_lock;
 
-/**
- * d_drop - drop a dentry
- * @dentry: dentry to drop
- *
- * d_drop() unhashes the entry from the parent dentry hashes, so that it won't
- * be found through a VFS lookup any more. Note that this is different from
- * deleting the dentry - d_delete will try to mark the dentry negative if
- * possible, giving a successful _negative_ lookup, while d_drop will
- * just make the cache lookup fail.
- *
- * d_drop() is used mainly for stuff that wants to invalidate a dentry for some
- * reason (NFS timeouts or autofs deletes).
- *
- * __d_drop requires dentry->d_lock.
- */
-
-static inline void __d_drop(struct dentry *dentry)
-{
-	if (!(dentry->d_flags & DCACHE_UNHASHED)) {
-		dentry->d_flags |= DCACHE_UNHASHED;
-		hlist_del_rcu(&dentry->d_hash);
-	}
-}
-
-static inline void d_drop(struct dentry *dentry)
-{
-	spin_lock(&dcache_lock);
-	spin_lock(&dentry->d_lock);
- 	__d_drop(dentry);
-	spin_unlock(&dentry->d_lock);
-	spin_unlock(&dcache_lock);
-}
-
 static inline int dname_external(struct dentry *dentry)
 {
 	return dentry->d_name.name != dentry->d_iname;
@@ -235,10 +225,14 @@
 extern void d_instantiate(struct dentry *, struct inode *);
 extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *);
 extern struct dentry * d_materialise_unique(struct dentry *, struct inode *);
+extern void __d_drop(struct dentry *dentry);
+extern void d_drop(struct dentry *dentry);
 extern void d_delete(struct dentry *);
+extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op);
 
 /* allocate/de-allocate */
 extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
+extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *);
 extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
 extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
 extern struct dentry * d_obtain_alias(struct inode *);
@@ -296,14 +290,40 @@
 	return res;
 }
 
+extern void dentry_update_name_case(struct dentry *, struct qstr *);
+
 /* used for rename() and baskets */
 extern void d_move(struct dentry *, struct dentry *);
 extern struct dentry *d_ancestor(struct dentry *, struct dentry *);
 
 /* appendix may either be NULL or be used for transname suffixes */
-extern struct dentry * d_lookup(struct dentry *, struct qstr *);
-extern struct dentry * __d_lookup(struct dentry *, struct qstr *);
-extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *);
+extern struct dentry *d_lookup(struct dentry *, struct qstr *);
+extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
+extern struct dentry *__d_lookup(struct dentry *, struct qstr *);
+extern struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
+				unsigned *seq, struct inode **inode);
+
+/**
+ * __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok
+ * @dentry: dentry to take a ref on
+ * @seq: seqcount to verify against
+ * @Returns: 0 on failure, else 1.
+ *
+ * __d_rcu_to_refcount operates on a dentry,seq pair that was returned
+ * by __d_lookup_rcu, to get a reference on an rcu-walk dentry.
+ */
+static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq)
+{
+	int ret = 0;
+
+	assert_spin_locked(&dentry->d_lock);
+	if (!read_seqcount_retry(&dentry->d_seq, seq)) {
+		ret = 1;
+		dentry->d_count++;
+	}
+
+	return ret;
+}
 
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
@@ -316,34 +336,37 @@
 extern char *__d_path(const struct path *path, struct path *root, char *, int);
 extern char *d_path(const struct path *, char *, int);
 extern char *d_path_with_unreachable(const struct path *, char *, int);
-extern char *__dentry_path(struct dentry *, char *, int);
+extern char *dentry_path_raw(struct dentry *, char *, int);
 extern char *dentry_path(struct dentry *, char *, int);
 
 /* Allocation counts.. */
 
 /**
- *	dget, dget_locked	-	get a reference to a dentry
+ *	dget, dget_dlock -	get a reference to a dentry
  *	@dentry: dentry to get a reference to
  *
  *	Given a dentry or %NULL pointer increment the reference count
  *	if appropriate and return the dentry. A dentry will not be 
- *	destroyed when it has references. dget() should never be
- *	called for dentries with zero reference counter. For these cases
- *	(preferably none, functions in dcache.c are sufficient for normal
- *	needs and they take necessary precautions) you should hold dcache_lock
- *	and call dget_locked() instead of dget().
+ *	destroyed when it has references.
  */
- 
+static inline struct dentry *dget_dlock(struct dentry *dentry)
+{
+	if (dentry)
+		dentry->d_count++;
+	return dentry;
+}
+
 static inline struct dentry *dget(struct dentry *dentry)
 {
 	if (dentry) {
-		BUG_ON(!atomic_read(&dentry->d_count));
-		atomic_inc(&dentry->d_count);
+		spin_lock(&dentry->d_lock);
+		dget_dlock(dentry);
+		spin_unlock(&dentry->d_lock);
 	}
 	return dentry;
 }
 
-extern struct dentry * dget_locked(struct dentry *);
+extern struct dentry *dget_parent(struct dentry *dentry);
 
 /**
  *	d_unhashed -	is dentry hashed
@@ -374,21 +397,11 @@
 	spin_unlock(&dentry->d_lock);
 }
 
-static inline struct dentry *dget_parent(struct dentry *dentry)
-{
-	struct dentry *ret;
-
-	spin_lock(&dentry->d_lock);
-	ret = dget(dentry->d_parent);
-	spin_unlock(&dentry->d_lock);
-	return ret;
-}
-
 extern void dput(struct dentry *);
 
 static inline int d_mountpoint(struct dentry *dentry)
 {
-	return dentry->d_mounted;
+	return dentry->d_flags & DCACHE_MOUNTED;
 }
 
 extern struct vfsmount *lookup_mnt(struct path *);
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 9d8688b..8cd00ad 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -824,6 +824,8 @@
 #ifdef CONFIG_DMA_ENGINE
 enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void dma_issue_pending_all(void);
+struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
+void dma_release_channel(struct dma_chan *chan);
 #else
 static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
 {
@@ -831,7 +833,14 @@
 }
 static inline void dma_issue_pending_all(void)
 {
-	do { } while (0);
+}
+static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+					      dma_filter_fn fn, void *fn_param)
+{
+	return NULL;
+}
+static inline void dma_release_channel(struct dma_chan *chan)
+{
 }
 #endif
 
@@ -842,8 +851,6 @@
 void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
 #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
-struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
-void dma_release_channel(struct dma_chan *chan);
 
 /* --- Helper iov-locking functions --- */
 
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 4fd978e..4d85797 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -195,15 +195,9 @@
 /*
  * io context count accounting
  */
-#define elv_ioc_count_mod(name, __val)				\
-	do {							\
-		preempt_disable();				\
-		__get_cpu_var(name) += (__val);			\
-		preempt_enable();				\
-	} while (0)
-
-#define elv_ioc_count_inc(name)	elv_ioc_count_mod(name, 1)
-#define elv_ioc_count_dec(name)	elv_ioc_count_mod(name, -1)
+#define elv_ioc_count_mod(name, __val) this_cpu_add(name, __val)
+#define elv_ioc_count_inc(name)	this_cpu_inc(name)
+#define elv_ioc_count_dec(name)	this_cpu_dec(name)
 
 #define elv_ioc_count_read(name)				\
 ({								\
diff --git a/include/linux/fb.h b/include/linux/fb.h
index d1631d3..68ba85a 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1092,6 +1092,8 @@
 extern const unsigned char *fb_firmware_edid(struct device *device);
 extern void fb_edid_to_monspecs(unsigned char *edid,
 				struct fb_monspecs *specs);
+extern void fb_edid_add_monspecs(unsigned char *edid,
+				 struct fb_monspecs *specs);
 extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
@@ -1150,6 +1152,7 @@
 
 extern const char *fb_mode_option;
 extern const struct fb_videomode vesa_modes[];
+extern const struct fb_videomode cea_modes[64];
 
 struct fb_modelist {
 	struct list_head list;
diff --git a/include/linux/fec.h b/include/linux/fec.h
index 5d3523d..bcff455 100644
--- a/include/linux/fec.h
+++ b/include/linux/fec.h
@@ -3,6 +3,8 @@
  * Copyright (c) 2009 Orex Computed Radiography
  *   Baruch Siach <baruch@tkos.co.il>
  *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
  * Header file for the FEC platform data
  *
  * This program is free software; you can redistribute it and/or modify
@@ -16,6 +18,7 @@
 
 struct fec_platform_data {
 	phy_interface_t phy;
+	unsigned char mac[ETH_ALEN];
 };
 
 #endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 090f0ea..baf3e55 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -392,6 +392,7 @@
 #include <linux/capability.h>
 #include <linux/semaphore.h>
 #include <linux/fiemap.h>
+#include <linux/rculist_bl.h>
 
 #include <asm/atomic.h>
 #include <asm/byteorder.h>
@@ -733,16 +734,31 @@
 #define ACL_NOT_CACHED ((void *)(-1))
 
 struct inode {
+	/* RCU path lookup touches following: */
+	umode_t			i_mode;
+	uid_t			i_uid;
+	gid_t			i_gid;
+	const struct inode_operations	*i_op;
+	struct super_block	*i_sb;
+
+	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
+	unsigned int		i_flags;
+	struct mutex		i_mutex;
+
+	unsigned long		i_state;
+	unsigned long		dirtied_when;	/* jiffies of first dirtying */
+
 	struct hlist_node	i_hash;
 	struct list_head	i_wb_list;	/* backing dev IO list */
 	struct list_head	i_lru;		/* inode LRU list */
 	struct list_head	i_sb_list;
-	struct list_head	i_dentry;
+	union {
+		struct list_head	i_dentry;
+		struct rcu_head		i_rcu;
+	};
 	unsigned long		i_ino;
 	atomic_t		i_count;
 	unsigned int		i_nlink;
-	uid_t			i_uid;
-	gid_t			i_gid;
 	dev_t			i_rdev;
 	unsigned int		i_blkbits;
 	u64			i_version;
@@ -755,13 +771,8 @@
 	struct timespec		i_ctime;
 	blkcnt_t		i_blocks;
 	unsigned short          i_bytes;
-	umode_t			i_mode;
-	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
-	struct mutex		i_mutex;
 	struct rw_semaphore	i_alloc_sem;
-	const struct inode_operations	*i_op;
 	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
-	struct super_block	*i_sb;
 	struct file_lock	*i_flock;
 	struct address_space	*i_mapping;
 	struct address_space	i_data;
@@ -782,11 +793,6 @@
 	struct hlist_head	i_fsnotify_marks;
 #endif
 
-	unsigned long		i_state;
-	unsigned long		dirtied_when;	/* jiffies of first dirtying */
-
-	unsigned int		i_flags;
-
 #ifdef CONFIG_IMA
 	/* protected by i_lock */
 	unsigned int		i_readcount; /* struct files open RO */
@@ -1372,13 +1378,13 @@
 	const struct xattr_handler **s_xattr;
 
 	struct list_head	s_inodes;	/* all inodes */
-	struct hlist_head	s_anon;		/* anonymous dentries for (nfs) exporting */
+	struct hlist_bl_head	s_anon;		/* anonymous dentries for (nfs) exporting */
 #ifdef CONFIG_SMP
 	struct list_head __percpu *s_files;
 #else
 	struct list_head	s_files;
 #endif
-	/* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
+	/* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
 	struct list_head	s_dentry_lru;	/* unused dentry lru */
 	int			s_nr_dentry_unused;	/* # of dentry on lru */
 
@@ -1545,9 +1551,18 @@
 	int (*setlease)(struct file *, long, struct file_lock **);
 };
 
+#define IPERM_FLAG_RCU	0x0001
+
 struct inode_operations {
-	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
 	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+	void * (*follow_link) (struct dentry *, struct nameidata *);
+	int (*permission) (struct inode *, int, unsigned int);
+	int (*check_acl)(struct inode *, int, unsigned int);
+
+	int (*readlink) (struct dentry *, char __user *,int);
+	void (*put_link) (struct dentry *, struct nameidata *, void *);
+
+	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
 	int (*link) (struct dentry *,struct inode *,struct dentry *);
 	int (*unlink) (struct inode *,struct dentry *);
 	int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -1556,12 +1571,7 @@
 	int (*mknod) (struct inode *,struct dentry *,int,dev_t);
 	int (*rename) (struct inode *, struct dentry *,
 			struct inode *, struct dentry *);
-	int (*readlink) (struct dentry *, char __user *,int);
-	void * (*follow_link) (struct dentry *, struct nameidata *);
-	void (*put_link) (struct dentry *, struct nameidata *, void *);
 	void (*truncate) (struct inode *);
-	int (*permission) (struct inode *, int);
-	int (*check_acl)(struct inode *, 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);
@@ -1573,7 +1583,7 @@
 			  loff_t len);
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
 		      u64 len);
-};
+} ____cacheline_aligned;
 
 struct seq_file;
 
@@ -2158,8 +2168,8 @@
 #endif
 extern int notify_change(struct dentry *, struct iattr *);
 extern int inode_permission(struct inode *, int);
-extern int generic_permission(struct inode *, int,
-		int (*check_acl)(struct inode *, int));
+extern int generic_permission(struct inode *, int, unsigned int,
+		int (*check_acl)(struct inode *, int, unsigned int));
 
 static inline bool execute_ok(struct inode *inode)
 {
@@ -2230,6 +2240,7 @@
 extern void end_writeback(struct inode *);
 extern void __destroy_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
+extern void free_inode_nonrcu(struct inode *inode);
 extern int should_remove_suid(struct dentry *);
 extern int file_remove_suid(struct file *);
 
@@ -2446,6 +2457,10 @@
 {
 	ino_t res;
 
+	/*
+	 * Don't strictly need d_lock here? If the parent ino could change
+	 * then surely we'd have a deeper race in the caller?
+	 */
 	spin_lock(&dentry->d_lock);
 	res = dentry->d_parent->d_inode->i_ino;
 	spin_unlock(&dentry->d_lock);
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h
index a42b5bf..003dc0f 100644
--- a/include/linux/fs_struct.h
+++ b/include/linux/fs_struct.h
@@ -2,10 +2,13 @@
 #define _LINUX_FS_STRUCT_H
 
 #include <linux/path.h>
+#include <linux/spinlock.h>
+#include <linux/seqlock.h>
 
 struct fs_struct {
 	int users;
 	spinlock_t lock;
+	seqcount_t seq;
 	int umask;
 	int in_exec;
 	struct path root, pwd;
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index b10bcde..2a53f10 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -17,7 +17,6 @@
 
 /*
  * fsnotify_d_instantiate - instantiate a dentry for inode
- * Called with dcache_lock held.
  */
 static inline void fsnotify_d_instantiate(struct dentry *dentry,
 					  struct inode *inode)
@@ -62,7 +61,6 @@
 
 /*
  * fsnotify_d_move - dentry has been moved
- * Called with dcache_lock and dentry->d_lock held.
  */
 static inline void fsnotify_d_move(struct dentry *dentry)
 {
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 7380763..69ad89b 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -329,9 +329,15 @@
 {
 	struct dentry *parent;
 
-	assert_spin_locked(&dcache_lock);
 	assert_spin_locked(&dentry->d_lock);
 
+	/*
+	 * Serialisation of setting PARENT_WATCHED on the dentries is provided
+	 * by d_lock. If inotify_inode_watched changes after we have taken
+	 * d_lock, the following __fsnotify_update_child_dentry_flags call will
+	 * find our entry, so it will spin until we complete here, and update
+	 * us with the new state.
+	 */
 	parent = dentry->d_parent;
 	if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode))
 		dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
@@ -341,15 +347,12 @@
 
 /*
  * fsnotify_d_instantiate - instantiate a dentry for inode
- * Called with dcache_lock held.
  */
 static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode *inode)
 {
 	if (!inode)
 		return;
 
-	assert_spin_locked(&dcache_lock);
-
 	spin_lock(&dentry->d_lock);
 	__fsnotify_update_dcache_flags(dentry);
 	spin_unlock(&dentry->d_lock);
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 8beabb9..47e3997 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -154,12 +154,14 @@
 	TRACE_EVENT_FL_ENABLED_BIT,
 	TRACE_EVENT_FL_FILTERED_BIT,
 	TRACE_EVENT_FL_RECORDED_CMD_BIT,
+	TRACE_EVENT_FL_CAP_ANY_BIT,
 };
 
 enum {
 	TRACE_EVENT_FL_ENABLED		= (1 << TRACE_EVENT_FL_ENABLED_BIT),
 	TRACE_EVENT_FL_FILTERED		= (1 << TRACE_EVENT_FL_FILTERED_BIT),
 	TRACE_EVENT_FL_RECORDED_CMD	= (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT),
+	TRACE_EVENT_FL_CAP_ANY		= (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
 };
 
 struct ftrace_event_call {
@@ -196,6 +198,14 @@
 #endif
 };
 
+#define __TRACE_EVENT_FLAGS(name, value)				\
+	static int __init trace_init_flags_##name(void)			\
+	{								\
+		event_##name.flags = value;				\
+		return 0;						\
+	}								\
+	early_initcall(trace_init_flags_##name);
+
 #define PERF_MAX_TRACE_SIZE	2048
 
 #define MAX_FILTER_PRED		32
@@ -215,6 +225,10 @@
 	FILTER_PTR_STRING,
 };
 
+#define EVENT_STORAGE_SIZE 128
+extern struct mutex event_storage_mutex;
+extern char event_storage[EVENT_STORAGE_SIZE];
+
 extern int trace_event_raw_init(struct ftrace_event_call *call);
 extern int trace_define_field(struct ftrace_event_call *call, const char *type,
 			      const char *name, int offset, int size,
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h
index 574bea4..0437e37 100644
--- a/include/linux/generic_acl.h
+++ b/include/linux/generic_acl.h
@@ -10,6 +10,6 @@
 
 int generic_acl_init(struct inode *, struct inode *);
 int generic_acl_chmod(struct inode *);
-int generic_check_acl(struct inode *inode, int mask);
+int generic_check_acl(struct inode *inode, int mask, unsigned int flags);
 
 #endif /* LINUX_GENERIC_ACL_H */
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index b676c58..3a93f73 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -81,7 +81,8 @@
 
 static inline int kmap_atomic_idx_push(void)
 {
-	int idx = __get_cpu_var(__kmap_atomic_idx)++;
+	int idx = __this_cpu_inc_return(__kmap_atomic_idx) - 1;
+
 #ifdef CONFIG_DEBUG_HIGHMEM
 	WARN_ON_ONCE(in_irq() && !irqs_disabled());
 	BUG_ON(idx > KM_TYPE_NR);
@@ -91,16 +92,18 @@
 
 static inline int kmap_atomic_idx(void)
 {
-	return __get_cpu_var(__kmap_atomic_idx) - 1;
+	return __this_cpu_read(__kmap_atomic_idx) - 1;
 }
 
-static inline int kmap_atomic_idx_pop(void)
+static inline void kmap_atomic_idx_pop(void)
 {
-	int idx = --__get_cpu_var(__kmap_atomic_idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
+	int idx = __this_cpu_dec_return(__kmap_atomic_idx);
+
 	BUG_ON(idx < 0);
+#else
+	__this_cpu_dec(__kmap_atomic_idx);
 #endif
-	return idx;
 }
 
 #endif
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index fd0c1b8..330586f 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -22,7 +22,7 @@
 #include <linux/wait.h>
 #include <linux/percpu.h>
 #include <linux/timer.h>
-
+#include <linux/timerqueue.h>
 
 struct hrtimer_clock_base;
 struct hrtimer_cpu_base;
@@ -79,8 +79,8 @@
 
 /**
  * struct hrtimer - the basic hrtimer structure
- * @node:	red black tree node for time ordered insertion
- * @_expires:	the absolute expiry time in the hrtimers internal
+ * @node:	timerqueue node, which also manages node.expires,
+ *		the absolute expiry time in the hrtimers internal
  *		representation. The time is related to the clock on
  *		which the timer is based. Is setup by adding
  *		slack to the _softexpires value. For non range timers
@@ -101,8 +101,7 @@
  * The hrtimer structure must be initialized by hrtimer_init()
  */
 struct hrtimer {
-	struct rb_node			node;
-	ktime_t				_expires;
+	struct timerqueue_node		node;
 	ktime_t				_softexpires;
 	enum hrtimer_restart		(*function)(struct hrtimer *);
 	struct hrtimer_clock_base	*base;
@@ -141,8 +140,7 @@
 struct hrtimer_clock_base {
 	struct hrtimer_cpu_base	*cpu_base;
 	clockid_t		index;
-	struct rb_root		active;
-	struct rb_node		*first;
+	struct timerqueue_head	active;
 	ktime_t			resolution;
 	ktime_t			(*get_time)(void);
 	ktime_t			softirq_time;
@@ -158,7 +156,6 @@
  * @lock:		lock protecting the base and associated clock bases
  *			and timers
  * @clock_base:		array of clock bases for this cpu
- * @curr_timer:		the timer which is executing a callback right now
  * @expires_next:	absolute time of the next event which was scheduled
  *			via clock_set_next_event()
  * @hres_active:	State of high resolution mode
@@ -184,43 +181,43 @@
 
 static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
 {
-	timer->_expires = time;
+	timer->node.expires = time;
 	timer->_softexpires = time;
 }
 
 static inline void hrtimer_set_expires_range(struct hrtimer *timer, ktime_t time, ktime_t delta)
 {
 	timer->_softexpires = time;
-	timer->_expires = ktime_add_safe(time, delta);
+	timer->node.expires = ktime_add_safe(time, delta);
 }
 
 static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t time, unsigned long delta)
 {
 	timer->_softexpires = time;
-	timer->_expires = ktime_add_safe(time, ns_to_ktime(delta));
+	timer->node.expires = ktime_add_safe(time, ns_to_ktime(delta));
 }
 
 static inline void hrtimer_set_expires_tv64(struct hrtimer *timer, s64 tv64)
 {
-	timer->_expires.tv64 = tv64;
+	timer->node.expires.tv64 = tv64;
 	timer->_softexpires.tv64 = tv64;
 }
 
 static inline void hrtimer_add_expires(struct hrtimer *timer, ktime_t time)
 {
-	timer->_expires = ktime_add_safe(timer->_expires, time);
+	timer->node.expires = ktime_add_safe(timer->node.expires, time);
 	timer->_softexpires = ktime_add_safe(timer->_softexpires, time);
 }
 
 static inline void hrtimer_add_expires_ns(struct hrtimer *timer, u64 ns)
 {
-	timer->_expires = ktime_add_ns(timer->_expires, ns);
+	timer->node.expires = ktime_add_ns(timer->node.expires, ns);
 	timer->_softexpires = ktime_add_ns(timer->_softexpires, ns);
 }
 
 static inline ktime_t hrtimer_get_expires(const struct hrtimer *timer)
 {
-	return timer->_expires;
+	return timer->node.expires;
 }
 
 static inline ktime_t hrtimer_get_softexpires(const struct hrtimer *timer)
@@ -230,7 +227,7 @@
 
 static inline s64 hrtimer_get_expires_tv64(const struct hrtimer *timer)
 {
-	return timer->_expires.tv64;
+	return timer->node.expires.tv64;
 }
 static inline s64 hrtimer_get_softexpires_tv64(const struct hrtimer *timer)
 {
@@ -239,12 +236,12 @@
 
 static inline s64 hrtimer_get_expires_ns(const struct hrtimer *timer)
 {
-	return ktime_to_ns(timer->_expires);
+	return ktime_to_ns(timer->node.expires);
 }
 
 static inline ktime_t hrtimer_expires_remaining(const struct hrtimer *timer)
 {
-    return ktime_sub(timer->_expires, timer->base->get_time());
+	return ktime_sub(timer->node.expires, timer->base->get_time());
 }
 
 #ifdef CONFIG_HIGH_RES_TIMERS
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index 78ebf50..7472449 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -1,9 +1,14 @@
 #ifndef __I2C_OMAP_H__
 #define __I2C_OMAP_H__
 
+#include <linux/platform_device.h>
+
 struct omap_i2c_bus_platform_data {
 	u32		clkrate;
 	void		(*set_mpu_wkup_lat)(struct device *dev, long set);
+	int		(*device_enable) (struct platform_device *pdev);
+	int		(*device_shutdown) (struct platform_device *pdev);
+	int		(*device_idle) (struct platform_device *pdev);
 };
 
 #endif
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index c760991..61b9609 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -593,6 +593,13 @@
 
 struct twl4030_usb_data {
 	enum twl4030_usb_mode	usb_mode;
+
+	int		(*phy_init)(struct device *dev);
+	int		(*phy_exit)(struct device *dev);
+	/* Power on/off the PHY */
+	int		(*phy_power)(struct device *dev, int iD, int on);
+	/* enable/disable  phy clocks */
+	int		(*phy_set_clock)(struct device *dev, int on);
 };
 
 struct twl4030_ins {
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 1f8c06c..caa151f 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -12,6 +12,13 @@
 #include <linux/securebits.h>
 #include <net/net_namespace.h>
 
+#ifdef CONFIG_SMP
+# define INIT_PUSHABLE_TASKS(tsk)					\
+	.pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO),
+#else
+# define INIT_PUSHABLE_TASKS(tsk)
+#endif
+
 extern struct files_struct init_files;
 extern struct fs_struct init_fs;
 
@@ -83,6 +90,12 @@
  */
 # define CAP_INIT_BSET  CAP_FULL_SET
 
+#ifdef CONFIG_RCU_BOOST
+#define INIT_TASK_RCU_BOOST()						\
+	.rcu_boost_mutex = NULL,
+#else
+#define INIT_TASK_RCU_BOOST()
+#endif
 #ifdef CONFIG_TREE_PREEMPT_RCU
 #define INIT_TASK_RCU_TREE_PREEMPT()					\
 	.rcu_blocked_node = NULL,
@@ -94,7 +107,8 @@
 	.rcu_read_lock_nesting = 0,					\
 	.rcu_read_unlock_special = 0,					\
 	.rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry),		\
-	INIT_TASK_RCU_TREE_PREEMPT()
+	INIT_TASK_RCU_TREE_PREEMPT()					\
+	INIT_TASK_RCU_BOOST()
 #else
 #define INIT_TASK_RCU_PREEMPT(tsk)
 #endif
@@ -137,7 +151,7 @@
 		.nr_cpus_allowed = NR_CPUS,				\
 	},								\
 	.tasks		= LIST_HEAD_INIT(tsk.tasks),			\
-	.pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), \
+	INIT_PUSHABLE_TASKS(tsk)					\
 	.ptraced	= LIST_HEAD_INIT(tsk.ptraced),			\
 	.ptrace_entry	= LIST_HEAD_INIT(tsk.ptrace_entry),		\
 	.real_parent	= &tsk,						\
diff --git a/include/linux/input.h b/include/linux/input.h
index 9777668..c4e9d91 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -112,6 +112,7 @@
 #define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */
 #define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */
 #define EVIOCGUNIQ(len)		_IOC(_IOC_READ, 'E', 0x08, len)		/* get unique identifier */
+#define EVIOCGPROP(len)		_IOC(_IOC_READ, 'E', 0x09, len)		/* get device properties */
 
 #define EVIOCGKEY(len)		_IOC(_IOC_READ, 'E', 0x18, len)		/* get global key state */
 #define EVIOCGLED(len)		_IOC(_IOC_READ, 'E', 0x19, len)		/* get all LEDs */
@@ -129,6 +130,18 @@
 #define EVIOCGRAB		_IOW('E', 0x90, int)			/* Grab/Release device */
 
 /*
+ * Device properties and quirks
+ */
+
+#define INPUT_PROP_POINTER		0x00	/* needs a pointer */
+#define INPUT_PROP_DIRECT		0x01	/* direct input devices */
+#define INPUT_PROP_BUTTONPAD		0x02	/* has button(s) under pad */
+#define INPUT_PROP_SEMI_MT		0x03	/* touch rectangle only */
+
+#define INPUT_PROP_MAX			0x1f
+#define INPUT_PROP_CNT			(INPUT_PROP_MAX + 1)
+
+/*
  * Event types
  */
 
@@ -590,6 +603,8 @@
 #define KEY_FRAMEFORWARD	0x1b5
 #define KEY_CONTEXT_MENU	0x1b6	/* GenDesc - system context menu */
 #define KEY_MEDIA_REPEAT	0x1b7	/* Consumer - transport control */
+#define KEY_10CHANNELSUP        0x1b8   /* 10 channels up (10+) */
+#define KEY_10CHANNELSDOWN      0x1b9   /* 10 channels down (10-) */
 
 #define KEY_DEL_EOL		0x1c0
 #define KEY_DEL_EOS		0x1c1
@@ -758,11 +773,12 @@
 #define ABS_MT_BLOB_ID		0x38	/* Group a set of packets as a blob */
 #define ABS_MT_TRACKING_ID	0x39	/* Unique ID of initiated contact */
 #define ABS_MT_PRESSURE		0x3a	/* Pressure on contact area */
+#define ABS_MT_DISTANCE		0x3b	/* Contact hover distance */
 
 #ifdef __KERNEL__
 /* Implementation details, userspace should not care about these */
 #define ABS_MT_FIRST		ABS_MT_TOUCH_MAJOR
-#define ABS_MT_LAST		ABS_MT_PRESSURE
+#define ABS_MT_LAST		ABS_MT_DISTANCE
 #endif
 
 #define ABS_MAX			0x3f
@@ -873,6 +889,7 @@
  */
 #define MT_TOOL_FINGER		0
 #define MT_TOOL_PEN		1
+#define MT_TOOL_MAX		1
 
 /*
  * Values describing the status of a force-feedback effect
@@ -1108,19 +1125,12 @@
 #include <linux/mod_devicetable.h>
 
 /**
- * struct input_mt_slot - represents the state of an input MT slot
- * @abs: holds current values of ABS_MT axes for this slot
- */
-struct input_mt_slot {
-	int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
-};
-
-/**
  * struct input_dev - represents an input device
  * @name: name of the device
  * @phys: physical path to the device in the system hierarchy
  * @uniq: unique identification code for the device (if device has it)
  * @id: id of the device (struct input_id)
+ * @propbit: bitmap of device properties and quirks
  * @evbit: bitmap of types of events supported by the device (EV_KEY,
  *	EV_REL, etc.)
  * @keybit: bitmap of keys/buttons this device has
@@ -1155,6 +1165,7 @@
  *	of tracked contacts
  * @mtsize: number of MT slots the device uses
  * @slot: MT slot currently being transmitted
+ * @trkid: stores MT tracking ID for the current contact
  * @absinfo: array of &struct input_absinfo elements holding information
  *	about absolute axes (current value, min, max, flat, fuzz,
  *	resolution)
@@ -1203,6 +1214,8 @@
 	const char *uniq;
 	struct input_id id;
 
+	unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
+
 	unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
 	unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
 	unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
@@ -1239,6 +1252,7 @@
 	struct input_mt_slot *mt;
 	int mtsize;
 	int slot;
+	int trkid;
 
 	struct input_absinfo *absinfo;
 
@@ -1488,11 +1502,6 @@
 	input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
 }
 
-static inline void input_mt_slot(struct input_dev *dev, int slot)
-{
-	input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
-}
-
 void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
 
 /**
@@ -1605,8 +1614,5 @@
 int input_ff_create_memless(struct input_dev *dev, void *data,
 		int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
 
-int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots);
-void input_mt_destroy_slots(struct input_dev *dev);
-
 #endif
 #endif
diff --git a/include/linux/input/cma3000.h b/include/linux/input/cma3000.h
new file mode 100644
index 0000000..cbbaac2
--- /dev/null
+++ b/include/linux/input/cma3000.h
@@ -0,0 +1,59 @@
+/*
+ * VTI CMA3000_Dxx 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 _LINUX_CMA3000_H
+#define _LINUX_CMA3000_H
+
+#define CMAMODE_DEFAULT    0
+#define CMAMODE_MEAS100    1
+#define CMAMODE_MEAS400    2
+#define CMAMODE_MEAS40     3
+#define CMAMODE_MOTDET     4
+#define CMAMODE_FF100      5
+#define CMAMODE_FF400      6
+#define CMAMODE_POFF       7
+
+#define CMARANGE_2G   2000
+#define CMARANGE_8G   8000
+
+/**
+ * struct cma3000_i2c_platform_data - CMA3000 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: Operating mode
+ * @mdthr: Motion detect threshold value
+ * @mdfftmr: Motion detect and free fall time value
+ * @ffthr: Free fall threshold value
+ */
+
+struct cma3000_platform_data {
+	int fuzz_x;
+	int fuzz_y;
+	int fuzz_z;
+	int g_range;
+	uint8_t mode;
+	uint8_t mdthr;
+	uint8_t mdfftmr;
+	uint8_t ffthr;
+	unsigned long irqflags;
+};
+
+#endif
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
index 80352ad..6974746 100644
--- a/include/linux/input/matrix_keypad.h
+++ b/include/linux/input/matrix_keypad.h
@@ -9,7 +9,7 @@
 
 #define KEY(row, col, val)	((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
 				 (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
-				 (val & 0xffff))
+				 ((val) & 0xffff))
 
 #define KEY_ROW(k)		(((k) >> 24) & 0xff)
 #define KEY_COL(k)		(((k) >> 16) & 0xff)
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
new file mode 100644
index 0000000..b3ac06a
--- /dev/null
+++ b/include/linux/input/mt.h
@@ -0,0 +1,57 @@
+#ifndef _INPUT_MT_H
+#define _INPUT_MT_H
+
+/*
+ * Input Multitouch Library
+ *
+ * Copyright (c) 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.h>
+
+#define TRKID_MAX	0xffff
+
+/**
+ * struct input_mt_slot - represents the state of an input MT slot
+ * @abs: holds current values of ABS_MT axes for this slot
+ */
+struct input_mt_slot {
+	int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
+};
+
+static inline void input_mt_set_value(struct input_mt_slot *slot,
+				      unsigned code, int value)
+{
+	slot->abs[code - ABS_MT_FIRST] = value;
+}
+
+static inline int input_mt_get_value(const struct input_mt_slot *slot,
+				     unsigned code)
+{
+	return slot->abs[code - ABS_MT_FIRST];
+}
+
+int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots);
+void input_mt_destroy_slots(struct input_dev *dev);
+
+static inline int input_mt_new_trkid(struct input_dev *dev)
+{
+	return dev->trkid++ & TRKID_MAX;
+}
+
+static inline void input_mt_slot(struct input_dev *dev, int slot)
+{
+	input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
+}
+
+void input_mt_report_slot_state(struct input_dev *dev,
+				unsigned int tool_type, bool active);
+
+void input_mt_report_finger_count(struct input_dev *dev, int count);
+void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count);
+
+#endif
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 79d0c4f..55e0d42 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -114,15 +114,15 @@
 struct irqaction {
 	irq_handler_t handler;
 	unsigned long flags;
-	const char *name;
 	void *dev_id;
 	struct irqaction *next;
 	int irq;
-	struct proc_dir_entry *dir;
 	irq_handler_t thread_fn;
 	struct task_struct *thread;
 	unsigned long thread_flags;
-};
+	const char *name;
+	struct proc_dir_entry *dir;
+} ____cacheline_internodealigned_in_smp;
 
 extern irqreturn_t no_action(int cpl, void *dev_id);
 
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index ad54c84..44e83ba 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -47,7 +47,7 @@
 
 #ifndef CONFIG_GENERIC_HARDIRQS
 #define kstat_irqs_this_cpu(irq) \
-	(kstat_this_cpu.irqs[irq])
+	(this_cpu_read(kstat.irqs[irq])
 
 struct irq_desc;
 
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index e7d1b2e..dd7c12e 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -275,7 +275,9 @@
 extern int arch_check_optimized_kprobe(struct optimized_kprobe *op);
 extern int arch_prepare_optimized_kprobe(struct optimized_kprobe *op);
 extern void arch_remove_optimized_kprobe(struct optimized_kprobe *op);
-extern int  arch_optimize_kprobe(struct optimized_kprobe *op);
+extern void arch_optimize_kprobes(struct list_head *oplist);
+extern void arch_unoptimize_kprobes(struct list_head *oplist,
+				    struct list_head *done_list);
 extern void arch_unoptimize_kprobe(struct optimized_kprobe *op);
 extern kprobe_opcode_t *get_optinsn_slot(void);
 extern void free_optinsn_slot(kprobe_opcode_t *slot, int dirty);
@@ -303,12 +305,12 @@
 /* kprobe_running() will just return the current_kprobe on this CPU */
 static inline struct kprobe *kprobe_running(void)
 {
-	return (__get_cpu_var(current_kprobe));
+	return (__this_cpu_read(current_kprobe));
 }
 
 static inline void reset_current_kprobe(void)
 {
-	__get_cpu_var(current_kprobe) = NULL;
+	__this_cpu_write(current_kprobe, NULL);
 }
 
 static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h
new file mode 100644
index 0000000..9ee97e7
--- /dev/null
+++ b/include/linux/list_bl.h
@@ -0,0 +1,144 @@
+#ifndef _LINUX_LIST_BL_H
+#define _LINUX_LIST_BL_H
+
+#include <linux/list.h>
+
+/*
+ * Special version of lists, where head of the list has a lock in the lowest
+ * bit. This is useful for scalable hash tables without increasing memory
+ * footprint overhead.
+ *
+ * For modification operations, the 0 bit of hlist_bl_head->first
+ * pointer must be set.
+ *
+ * With some small modifications, this can easily be adapted to store several
+ * arbitrary bits (not just a single lock bit), if the need arises to store
+ * some fast and compact auxiliary data.
+ */
+
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+#define LIST_BL_LOCKMASK	1UL
+#else
+#define LIST_BL_LOCKMASK	0UL
+#endif
+
+#ifdef CONFIG_DEBUG_LIST
+#define LIST_BL_BUG_ON(x) BUG_ON(x)
+#else
+#define LIST_BL_BUG_ON(x)
+#endif
+
+
+struct hlist_bl_head {
+	struct hlist_bl_node *first;
+};
+
+struct hlist_bl_node {
+	struct hlist_bl_node *next, **pprev;
+};
+#define INIT_HLIST_BL_HEAD(ptr) \
+	((ptr)->first = NULL)
+
+static inline void INIT_HLIST_BL_NODE(struct hlist_bl_node *h)
+{
+	h->next = NULL;
+	h->pprev = NULL;
+}
+
+#define hlist_bl_entry(ptr, type, member) container_of(ptr,type,member)
+
+static inline int hlist_bl_unhashed(const struct hlist_bl_node *h)
+{
+	return !h->pprev;
+}
+
+static inline struct hlist_bl_node *hlist_bl_first(struct hlist_bl_head *h)
+{
+	return (struct hlist_bl_node *)
+		((unsigned long)h->first & ~LIST_BL_LOCKMASK);
+}
+
+static inline void hlist_bl_set_first(struct hlist_bl_head *h,
+					struct hlist_bl_node *n)
+{
+	LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK);
+	LIST_BL_BUG_ON(!((unsigned long)h->first & LIST_BL_LOCKMASK));
+	h->first = (struct hlist_bl_node *)((unsigned long)n | LIST_BL_LOCKMASK);
+}
+
+static inline int hlist_bl_empty(const struct hlist_bl_head *h)
+{
+	return !((unsigned long)h->first & ~LIST_BL_LOCKMASK);
+}
+
+static inline void hlist_bl_add_head(struct hlist_bl_node *n,
+					struct hlist_bl_head *h)
+{
+	struct hlist_bl_node *first = hlist_bl_first(h);
+
+	n->next = first;
+	if (first)
+		first->pprev = &n->next;
+	n->pprev = &h->first;
+	hlist_bl_set_first(h, n);
+}
+
+static inline void __hlist_bl_del(struct hlist_bl_node *n)
+{
+	struct hlist_bl_node *next = n->next;
+	struct hlist_bl_node **pprev = n->pprev;
+
+	LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK);
+
+	/* pprev may be `first`, so be careful not to lose the lock bit */
+	*pprev = (struct hlist_bl_node *)
+			((unsigned long)next |
+			 ((unsigned long)*pprev & LIST_BL_LOCKMASK));
+	if (next)
+		next->pprev = pprev;
+}
+
+static inline void hlist_bl_del(struct hlist_bl_node *n)
+{
+	__hlist_bl_del(n);
+	n->next = LIST_POISON1;
+	n->pprev = LIST_POISON2;
+}
+
+static inline void hlist_bl_del_init(struct hlist_bl_node *n)
+{
+	if (!hlist_bl_unhashed(n)) {
+		__hlist_bl_del(n);
+		INIT_HLIST_BL_NODE(n);
+	}
+}
+
+/**
+ * hlist_bl_for_each_entry	- iterate over list of given type
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ *
+ */
+#define hlist_bl_for_each_entry(tpos, pos, head, member)		\
+	for (pos = hlist_bl_first(head);				\
+	     pos &&							\
+		({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_bl_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
+ * @n:		another &struct hlist_node to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_bl_for_each_entry_safe(tpos, pos, n, head, member)	 \
+	for (pos = hlist_bl_first(head);				 \
+	     pos && ({ n = pos->next; 1; }) && 				 \
+		({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = n)
+
+#endif
diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc35892.h
deleted file mode 100644
index eff3094..0000000
--- a/include/linux/mfd/tc35892.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License, version 2
- */
-
-#ifndef __LINUX_MFD_TC35892_H
-#define __LINUX_MFD_TC35892_H
-
-#include <linux/device.h>
-
-#define TC35892_RSTCTRL_IRQRST	(1 << 4)
-#define TC35892_RSTCTRL_TIMRST	(1 << 3)
-#define TC35892_RSTCTRL_ROTRST	(1 << 2)
-#define TC35892_RSTCTRL_KBDRST	(1 << 1)
-#define TC35892_RSTCTRL_GPIRST	(1 << 0)
-
-#define TC35892_IRQST		0x91
-
-#define TC35892_MANFCODE_MAGIC	0x03
-#define TC35892_MANFCODE	0x80
-#define TC35892_VERSION		0x81
-#define TC35892_IOCFG		0xA7
-
-#define TC35892_CLKMODE		0x88
-#define TC35892_CLKCFG		0x89
-#define TC35892_CLKEN		0x8A
-
-#define TC35892_RSTCTRL		0x82
-#define TC35892_EXTRSTN		0x83
-#define TC35892_RSTINTCLR	0x84
-
-#define TC35892_GPIOIS0		0xC9
-#define TC35892_GPIOIS1		0xCA
-#define TC35892_GPIOIS2		0xCB
-#define TC35892_GPIOIBE0	0xCC
-#define TC35892_GPIOIBE1	0xCD
-#define TC35892_GPIOIBE2	0xCE
-#define TC35892_GPIOIEV0	0xCF
-#define TC35892_GPIOIEV1	0xD0
-#define TC35892_GPIOIEV2	0xD1
-#define TC35892_GPIOIE0		0xD2
-#define TC35892_GPIOIE1		0xD3
-#define TC35892_GPIOIE2		0xD4
-#define TC35892_GPIORIS0	0xD6
-#define TC35892_GPIORIS1	0xD7
-#define TC35892_GPIORIS2	0xD8
-#define TC35892_GPIOMIS0	0xD9
-#define TC35892_GPIOMIS1	0xDA
-#define TC35892_GPIOMIS2	0xDB
-#define TC35892_GPIOIC0		0xDC
-#define TC35892_GPIOIC1		0xDD
-#define TC35892_GPIOIC2		0xDE
-
-#define TC35892_GPIODATA0	0xC0
-#define TC35892_GPIOMASK0	0xc1
-#define TC35892_GPIODATA1	0xC2
-#define TC35892_GPIOMASK1	0xc3
-#define TC35892_GPIODATA2	0xC4
-#define TC35892_GPIOMASK2	0xC5
-
-#define TC35892_GPIODIR0	0xC6
-#define TC35892_GPIODIR1	0xC7
-#define TC35892_GPIODIR2	0xC8
-
-#define TC35892_GPIOSYNC0	0xE6
-#define TC35892_GPIOSYNC1	0xE7
-#define TC35892_GPIOSYNC2	0xE8
-
-#define TC35892_GPIOWAKE0	0xE9
-#define TC35892_GPIOWAKE1	0xEA
-#define TC35892_GPIOWAKE2	0xEB
-
-#define TC35892_GPIOODM0	0xE0
-#define TC35892_GPIOODE0	0xE1
-#define TC35892_GPIOODM1	0xE2
-#define TC35892_GPIOODE1	0xE3
-#define TC35892_GPIOODM2	0xE4
-#define TC35892_GPIOODE2	0xE5
-
-#define TC35892_INT_GPIIRQ	0
-#define TC35892_INT_TI0IRQ	1
-#define TC35892_INT_TI1IRQ	2
-#define TC35892_INT_TI2IRQ	3
-#define TC35892_INT_ROTIRQ	5
-#define TC35892_INT_KBDIRQ	6
-#define TC35892_INT_PORIRQ	7
-
-#define TC35892_NR_INTERNAL_IRQS	8
-#define TC35892_INT_GPIO(x)	(TC35892_NR_INTERNAL_IRQS + (x))
-
-struct tc35892 {
-	struct mutex lock;
-	struct device *dev;
-	struct i2c_client *i2c;
-
-	int irq_base;
-	int num_gpio;
-	struct tc35892_platform_data *pdata;
-};
-
-extern int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data);
-extern int tc35892_reg_read(struct tc35892 *tc35892, u8 reg);
-extern int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length,
-			      u8 *values);
-extern int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
-			       const u8 *values);
-extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val);
-
-/**
- * struct tc35892_gpio_platform_data - TC35892 GPIO platform data
- * @gpio_base: first gpio number assigned to TC35892.  A maximum of
- *	       %TC35892_NR_GPIOS GPIOs will be allocated.
- * @setup: callback for board-specific initialization
- * @remove: callback for board-specific teardown
- */
-struct tc35892_gpio_platform_data {
-	int gpio_base;
-	void (*setup)(struct tc35892 *tc35892, unsigned gpio_base);
-	void (*remove)(struct tc35892 *tc35892, unsigned gpio_base);
-};
-
-/**
- * struct tc35892_platform_data - TC35892 platform data
- * @irq_base: base IRQ number.  %TC35892_NR_IRQS irqs will be used.
- * @gpio: GPIO-specific platform data
- */
-struct tc35892_platform_data {
-	int irq_base;
-	struct tc35892_gpio_platform_data *gpio;
-};
-
-#define TC35892_NR_GPIOS	24
-#define TC35892_NR_IRQS		TC35892_INT_GPIO(TC35892_NR_GPIOS)
-
-#endif
diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h
new file mode 100644
index 0000000..16c76e1
--- /dev/null
+++ b/include/linux/mfd/tc3589x.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ */
+
+#ifndef __LINUX_MFD_TC3589x_H
+#define __LINUX_MFD_TC3589x_H
+
+#include <linux/device.h>
+
+enum tx3589x_block {
+	TC3589x_BLOCK_GPIO        = 1 << 0,
+	TC3589x_BLOCK_KEYPAD      = 1 << 1,
+};
+
+#define TC3589x_RSTCTRL_IRQRST	(1 << 4)
+#define TC3589x_RSTCTRL_TIMRST	(1 << 3)
+#define TC3589x_RSTCTRL_ROTRST	(1 << 2)
+#define TC3589x_RSTCTRL_KBDRST	(1 << 1)
+#define TC3589x_RSTCTRL_GPIRST	(1 << 0)
+
+/* Keyboard Configuration Registers */
+#define TC3589x_KBDSETTLE_REG   0x01
+#define TC3589x_KBDBOUNCE       0x02
+#define TC3589x_KBDSIZE         0x03
+#define TC3589x_KBCFG_LSB       0x04
+#define TC3589x_KBCFG_MSB       0x05
+#define TC3589x_KBDIC           0x08
+#define TC3589x_KBDMSK          0x09
+#define TC3589x_EVTCODE_FIFO    0x10
+#define TC3589x_KBDMFS		0x8F
+
+#define TC3589x_IRQST		0x91
+
+#define TC3589x_MANFCODE_MAGIC	0x03
+#define TC3589x_MANFCODE	0x80
+#define TC3589x_VERSION		0x81
+#define TC3589x_IOCFG		0xA7
+
+#define TC3589x_CLKMODE		0x88
+#define TC3589x_CLKCFG		0x89
+#define TC3589x_CLKEN		0x8A
+
+#define TC3589x_RSTCTRL		0x82
+#define TC3589x_EXTRSTN		0x83
+#define TC3589x_RSTINTCLR	0x84
+
+/* Pull up/down configuration registers */
+#define TC3589x_IOCFG           0xA7
+#define TC3589x_IOPULLCFG0_LSB  0xAA
+#define TC3589x_IOPULLCFG0_MSB  0xAB
+#define TC3589x_IOPULLCFG1_LSB  0xAC
+#define TC3589x_IOPULLCFG1_MSB  0xAD
+#define TC3589x_IOPULLCFG2_LSB  0xAE
+
+#define TC3589x_GPIOIS0		0xC9
+#define TC3589x_GPIOIS1		0xCA
+#define TC3589x_GPIOIS2		0xCB
+#define TC3589x_GPIOIBE0	0xCC
+#define TC3589x_GPIOIBE1	0xCD
+#define TC3589x_GPIOIBE2	0xCE
+#define TC3589x_GPIOIEV0	0xCF
+#define TC3589x_GPIOIEV1	0xD0
+#define TC3589x_GPIOIEV2	0xD1
+#define TC3589x_GPIOIE0		0xD2
+#define TC3589x_GPIOIE1		0xD3
+#define TC3589x_GPIOIE2		0xD4
+#define TC3589x_GPIORIS0	0xD6
+#define TC3589x_GPIORIS1	0xD7
+#define TC3589x_GPIORIS2	0xD8
+#define TC3589x_GPIOMIS0	0xD9
+#define TC3589x_GPIOMIS1	0xDA
+#define TC3589x_GPIOMIS2	0xDB
+#define TC3589x_GPIOIC0		0xDC
+#define TC3589x_GPIOIC1		0xDD
+#define TC3589x_GPIOIC2		0xDE
+
+#define TC3589x_GPIODATA0	0xC0
+#define TC3589x_GPIOMASK0	0xc1
+#define TC3589x_GPIODATA1	0xC2
+#define TC3589x_GPIOMASK1	0xc3
+#define TC3589x_GPIODATA2	0xC4
+#define TC3589x_GPIOMASK2	0xC5
+
+#define TC3589x_GPIODIR0	0xC6
+#define TC3589x_GPIODIR1	0xC7
+#define TC3589x_GPIODIR2	0xC8
+
+#define TC3589x_GPIOSYNC0	0xE6
+#define TC3589x_GPIOSYNC1	0xE7
+#define TC3589x_GPIOSYNC2	0xE8
+
+#define TC3589x_GPIOWAKE0	0xE9
+#define TC3589x_GPIOWAKE1	0xEA
+#define TC3589x_GPIOWAKE2	0xEB
+
+#define TC3589x_GPIOODM0	0xE0
+#define TC3589x_GPIOODE0	0xE1
+#define TC3589x_GPIOODM1	0xE2
+#define TC3589x_GPIOODE1	0xE3
+#define TC3589x_GPIOODM2	0xE4
+#define TC3589x_GPIOODE2	0xE5
+
+#define TC3589x_INT_GPIIRQ	0
+#define TC3589x_INT_TI0IRQ	1
+#define TC3589x_INT_TI1IRQ	2
+#define TC3589x_INT_TI2IRQ	3
+#define TC3589x_INT_ROTIRQ	5
+#define TC3589x_INT_KBDIRQ	6
+#define TC3589x_INT_PORIRQ	7
+
+#define TC3589x_NR_INTERNAL_IRQS	8
+#define TC3589x_INT_GPIO(x)	(TC3589x_NR_INTERNAL_IRQS + (x))
+
+struct tc3589x {
+	struct mutex lock;
+	struct device *dev;
+	struct i2c_client *i2c;
+
+	int irq_base;
+	int num_gpio;
+	struct tc3589x_platform_data *pdata;
+};
+
+extern int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data);
+extern int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg);
+extern int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length,
+			      u8 *values);
+extern int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
+			       const u8 *values);
+extern int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val);
+
+/*
+ * Keypad related platform specific constants
+ * These values may be modified for fine tuning
+ */
+#define TC_KPD_ROWS             0x8
+#define TC_KPD_COLUMNS          0x8
+#define TC_KPD_DEBOUNCE_PERIOD  0xA3
+#define TC_KPD_SETTLE_TIME      0xA3
+
+/**
+ * struct tc35893_platform_data - data structure for platform specific data
+ * @keymap_data:        matrix scan code table for keycodes
+ * @krow:               mask for available rows, value is 0xFF
+ * @kcol:               mask for available columns, value is 0xFF
+ * @debounce_period:    platform specific debounce time
+ * @settle_time:        platform specific settle down time
+ * @irqtype:            type of interrupt, falling or rising edge
+ * @enable_wakeup:      specifies if keypad event can wake up system from sleep
+ * @no_autorepeat:      flag for auto repetition
+ */
+struct tc3589x_keypad_platform_data {
+	const struct matrix_keymap_data *keymap_data;
+	u8                      krow;
+	u8                      kcol;
+	u8                      debounce_period;
+	u8                      settle_time;
+	unsigned long           irqtype;
+	bool                    enable_wakeup;
+	bool                    no_autorepeat;
+};
+
+/**
+ * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data
+ * @gpio_base: first gpio number assigned to TC3589x.  A maximum of
+ *	       %TC3589x_NR_GPIOS GPIOs will be allocated.
+ * @setup: callback for board-specific initialization
+ * @remove: callback for board-specific teardown
+ */
+struct tc3589x_gpio_platform_data {
+	int gpio_base;
+	void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base);
+	void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base);
+};
+
+/**
+ * struct tc3589x_platform_data - TC3589x platform data
+ * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*)
+ * @irq_base: base IRQ number.  %TC3589x_NR_IRQS irqs will be used.
+ * @gpio: GPIO-specific platform data
+ * @keypad: keypad-specific platform data
+ */
+struct tc3589x_platform_data {
+	unsigned int block;
+	int irq_base;
+	struct tc3589x_gpio_platform_data *gpio;
+	const struct tc3589x_keypad_platform_data *keypad;
+};
+
+#define TC3589x_NR_GPIOS	24
+#define TC3589x_NR_IRQS		TC3589x_INT_GPIO(TC3589x_NR_GPIOS)
+
+#endif
diff --git a/include/linux/mfd/wl1273-core.h b/include/linux/mfd/wl1273-core.h
new file mode 100644
index 0000000..9787293
--- /dev/null
+++ b/include/linux/mfd/wl1273-core.h
@@ -0,0 +1,288 @@
+/*
+ * include/linux/mfd/wl1273-core.h
+ *
+ * Some definitions for the wl1273 radio receiver/transmitter chip.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef WL1273_CORE_H
+#define WL1273_CORE_H
+
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+
+#define WL1273_FM_DRIVER_NAME	"wl1273-fm"
+#define RX71_FM_I2C_ADDR	0x22
+
+#define WL1273_STEREO_GET		0
+#define WL1273_RSSI_LVL_GET		1
+#define WL1273_IF_COUNT_GET		2
+#define WL1273_FLAG_GET			3
+#define WL1273_RDS_SYNC_GET		4
+#define WL1273_RDS_DATA_GET		5
+#define WL1273_FREQ_SET			10
+#define WL1273_AF_FREQ_SET		11
+#define WL1273_MOST_MODE_SET		12
+#define WL1273_MOST_BLEND_SET		13
+#define WL1273_DEMPH_MODE_SET		14
+#define WL1273_SEARCH_LVL_SET		15
+#define WL1273_BAND_SET			16
+#define WL1273_MUTE_STATUS_SET		17
+#define WL1273_RDS_PAUSE_LVL_SET	18
+#define WL1273_RDS_PAUSE_DUR_SET	19
+#define WL1273_RDS_MEM_SET		20
+#define WL1273_RDS_BLK_B_SET		21
+#define WL1273_RDS_MSK_B_SET		22
+#define WL1273_RDS_PI_MASK_SET		23
+#define WL1273_RDS_PI_SET		24
+#define WL1273_RDS_SYSTEM_SET		25
+#define WL1273_INT_MASK_SET		26
+#define WL1273_SEARCH_DIR_SET		27
+#define WL1273_VOLUME_SET		28
+#define WL1273_AUDIO_ENABLE		29
+#define WL1273_PCM_MODE_SET		30
+#define WL1273_I2S_MODE_CONFIG_SET	31
+#define WL1273_POWER_SET		32
+#define WL1273_INTX_CONFIG_SET		33
+#define WL1273_PULL_EN_SET		34
+#define WL1273_HILO_SET			35
+#define WL1273_SWITCH2FREF		36
+#define WL1273_FREQ_DRIFT_REPORT	37
+
+#define WL1273_PCE_GET			40
+#define WL1273_FIRM_VER_GET		41
+#define WL1273_ASIC_VER_GET		42
+#define WL1273_ASIC_ID_GET		43
+#define WL1273_MAN_ID_GET		44
+#define WL1273_TUNER_MODE_SET		45
+#define WL1273_STOP_SEARCH		46
+#define WL1273_RDS_CNTRL_SET		47
+
+#define WL1273_WRITE_HARDWARE_REG	100
+#define WL1273_CODE_DOWNLOAD		101
+#define WL1273_RESET			102
+
+#define WL1273_FM_POWER_MODE		254
+#define WL1273_FM_INTERRUPT		255
+
+/* Transmitter API */
+
+#define WL1273_CHANL_SET			55
+#define WL1273_SCAN_SPACING_SET			56
+#define WL1273_REF_SET				57
+#define WL1273_POWER_ENB_SET			90
+#define WL1273_POWER_ATT_SET			58
+#define WL1273_POWER_LEV_SET			59
+#define WL1273_AUDIO_DEV_SET			60
+#define WL1273_PILOT_DEV_SET			61
+#define WL1273_RDS_DEV_SET			62
+#define WL1273_PUPD_SET				91
+#define WL1273_AUDIO_IO_SET			63
+#define WL1273_PREMPH_SET			64
+#define WL1273_MONO_SET				66
+#define WL1273_MUTE				92
+#define WL1273_MPX_LMT_ENABLE			67
+#define WL1273_PI_SET				93
+#define WL1273_ECC_SET				69
+#define WL1273_PTY				70
+#define WL1273_AF				71
+#define WL1273_DISPLAY_MODE			74
+#define WL1273_RDS_REP_SET			77
+#define WL1273_RDS_CONFIG_DATA_SET		98
+#define WL1273_RDS_DATA_SET			99
+#define WL1273_RDS_DATA_ENB			94
+#define WL1273_TA_SET				78
+#define WL1273_TP_SET				79
+#define WL1273_DI_SET				80
+#define WL1273_MS_SET				81
+#define WL1273_PS_SCROLL_SPEED			82
+#define WL1273_TX_AUDIO_LEVEL_TEST		96
+#define WL1273_TX_AUDIO_LEVEL_TEST_THRESHOLD	73
+#define WL1273_TX_AUDIO_INPUT_LEVEL_RANGE_SET	54
+#define WL1273_RX_ANTENNA_SELECT		87
+#define WL1273_I2C_DEV_ADDR_SET			86
+#define WL1273_REF_ERR_CALIB_PARAM_SET		88
+#define WL1273_REF_ERR_CALIB_PERIODICITY_SET	89
+#define WL1273_SOC_INT_TRIGGER			52
+#define WL1273_SOC_AUDIO_PATH_SET		83
+#define WL1273_SOC_PCMI_OVERRIDE		84
+#define WL1273_SOC_I2S_OVERRIDE			85
+#define WL1273_RSSI_BLOCK_SCAN_FREQ_SET		95
+#define WL1273_RSSI_BLOCK_SCAN_START		97
+#define WL1273_RSSI_BLOCK_SCAN_DATA_GET		5
+#define WL1273_READ_FMANT_TUNE_VALUE		104
+
+#define WL1273_RDS_OFF		0
+#define WL1273_RDS_ON		1
+#define WL1273_RDS_RESET	2
+
+#define WL1273_AUDIO_DIGITAL	0
+#define WL1273_AUDIO_ANALOG	1
+
+#define WL1273_MODE_RX		BIT(0)
+#define WL1273_MODE_TX		BIT(1)
+#define WL1273_MODE_OFF		BIT(2)
+#define WL1273_MODE_SUSPENDED	BIT(3)
+
+#define WL1273_RADIO_CHILD	BIT(0)
+#define WL1273_CODEC_CHILD	BIT(1)
+
+#define WL1273_RX_MONO		1
+#define WL1273_RX_STEREO	0
+#define WL1273_TX_MONO		0
+#define WL1273_TX_STEREO	1
+
+#define WL1273_MAX_VOLUME	0xffff
+#define WL1273_DEFAULT_VOLUME	0x78b8
+
+/* I2S protocol, left channel first, data width 16 bits */
+#define WL1273_PCM_DEF_MODE		0x00
+
+/* Rx */
+#define WL1273_AUDIO_ENABLE_I2S		BIT(0)
+#define WL1273_AUDIO_ENABLE_ANALOG	BIT(1)
+
+/* Tx */
+#define WL1273_AUDIO_IO_SET_ANALOG	0
+#define WL1273_AUDIO_IO_SET_I2S		1
+
+#define WL1273_PUPD_SET_OFF		0x00
+#define WL1273_PUPD_SET_ON		0x01
+#define WL1273_PUPD_SET_RETENTION	0x10
+
+/* I2S mode */
+#define WL1273_IS2_WIDTH_32	0x0
+#define WL1273_IS2_WIDTH_40	0x1
+#define WL1273_IS2_WIDTH_22_23	0x2
+#define WL1273_IS2_WIDTH_23_22	0x3
+#define WL1273_IS2_WIDTH_48	0x4
+#define WL1273_IS2_WIDTH_50	0x5
+#define WL1273_IS2_WIDTH_60	0x6
+#define WL1273_IS2_WIDTH_64	0x7
+#define WL1273_IS2_WIDTH_80	0x8
+#define WL1273_IS2_WIDTH_96	0x9
+#define WL1273_IS2_WIDTH_128	0xa
+#define WL1273_IS2_WIDTH	0xf
+
+#define WL1273_IS2_FORMAT_STD	(0x0 << 4)
+#define WL1273_IS2_FORMAT_LEFT	(0x1 << 4)
+#define WL1273_IS2_FORMAT_RIGHT	(0x2 << 4)
+#define WL1273_IS2_FORMAT_USER	(0x3 << 4)
+
+#define WL1273_IS2_MASTER	(0x0 << 6)
+#define WL1273_IS2_SLAVEW	(0x1 << 6)
+
+#define WL1273_IS2_TRI_AFTER_SENDING	(0x0 << 7)
+#define WL1273_IS2_TRI_ALWAYS_ACTIVE	(0x1 << 7)
+
+#define WL1273_IS2_SDOWS_RR	(0x0 << 8)
+#define WL1273_IS2_SDOWS_RF	(0x1 << 8)
+#define WL1273_IS2_SDOWS_FR	(0x2 << 8)
+#define WL1273_IS2_SDOWS_FF	(0x3 << 8)
+
+#define WL1273_IS2_TRI_OPT	(0x0 << 10)
+#define WL1273_IS2_TRI_ALWAYS	(0x1 << 10)
+
+#define WL1273_IS2_RATE_48K	(0x0 << 12)
+#define WL1273_IS2_RATE_44_1K	(0x1 << 12)
+#define WL1273_IS2_RATE_32K	(0x2 << 12)
+#define WL1273_IS2_RATE_22_05K	(0x4 << 12)
+#define WL1273_IS2_RATE_16K	(0x5 << 12)
+#define WL1273_IS2_RATE_12K	(0x8 << 12)
+#define WL1273_IS2_RATE_11_025	(0x9 << 12)
+#define WL1273_IS2_RATE_8K	(0xa << 12)
+#define WL1273_IS2_RATE		(0xf << 12)
+
+#define WL1273_I2S_DEF_MODE	(WL1273_IS2_WIDTH_32 | \
+				 WL1273_IS2_FORMAT_STD | \
+				 WL1273_IS2_MASTER | \
+				 WL1273_IS2_TRI_AFTER_SENDING | \
+				 WL1273_IS2_SDOWS_RR | \
+				 WL1273_IS2_TRI_OPT | \
+				 WL1273_IS2_RATE_48K)
+
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+#define WL1273_FR_EVENT			BIT(0)
+#define WL1273_BL_EVENT			BIT(1)
+#define WL1273_RDS_EVENT		BIT(2)
+#define WL1273_BBLK_EVENT		BIT(3)
+#define WL1273_LSYNC_EVENT		BIT(4)
+#define WL1273_LEV_EVENT		BIT(5)
+#define WL1273_IFFR_EVENT		BIT(6)
+#define WL1273_PI_EVENT			BIT(7)
+#define WL1273_PD_EVENT			BIT(8)
+#define WL1273_STIC_EVENT		BIT(9)
+#define WL1273_MAL_EVENT		BIT(10)
+#define WL1273_POW_ENB_EVENT		BIT(11)
+#define WL1273_SCAN_OVER_EVENT		BIT(12)
+#define WL1273_ERROR_EVENT		BIT(13)
+
+#define TUNER_MODE_STOP_SEARCH		0
+#define TUNER_MODE_PRESET		1
+#define TUNER_MODE_AUTO_SEEK		2
+#define TUNER_MODE_AF			3
+#define TUNER_MODE_AUTO_SEEK_PI		4
+#define TUNER_MODE_AUTO_SEEK_BULK	5
+
+#define RDS_BLOCK_SIZE	3
+
+struct wl1273_fm_platform_data {
+	int (*request_resources) (struct i2c_client *client);
+	void (*free_resources) (void);
+	void (*enable) (void);
+	void (*disable) (void);
+
+	u8 forbidden_modes;
+	unsigned int children;
+};
+
+#define WL1273_FM_CORE_CELLS	2
+
+#define WL1273_BAND_OTHER	0
+#define WL1273_BAND_JAPAN	1
+
+#define WL1273_BAND_JAPAN_LOW	76000
+#define WL1273_BAND_JAPAN_HIGH	90000
+#define WL1273_BAND_OTHER_LOW	87500
+#define WL1273_BAND_OTHER_HIGH	108000
+
+#define WL1273_BAND_TX_LOW	76000
+#define WL1273_BAND_TX_HIGH	108000
+
+struct wl1273_core {
+	struct mfd_cell cells[WL1273_FM_CORE_CELLS];
+	struct wl1273_fm_platform_data *pdata;
+
+	unsigned int mode;
+	unsigned int i2s_mode;
+	unsigned int volume;
+	unsigned int audio_mode;
+	unsigned int channel_number;
+	struct mutex lock; /* for serializing fm radio operations */
+
+	struct i2c_client *client;
+
+	int (*write)(struct wl1273_core *core, u8, u16);
+	int (*set_audio)(struct wl1273_core *core, unsigned int);
+	int (*set_volume)(struct wl1273_core *core, unsigned int);
+};
+
+#endif	/* ifndef WL1273_CORE_H */
diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h
index 5c99da1..44fc534 100644
--- a/include/linux/mmc/sh_mmcif.h
+++ b/include/linux/mmc/sh_mmcif.h
@@ -14,8 +14,9 @@
 #ifndef __SH_MMCIF_H__
 #define __SH_MMCIF_H__
 
-#include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/sh_dma.h>
 
 /*
  * MMCIF : CE_CLK_CTRL [19:16]
@@ -31,13 +32,19 @@
  * 1111 : Peripheral clock (sup_pclk set '1')
  */
 
+struct sh_mmcif_dma {
+	struct sh_dmae_slave chan_priv_tx;
+	struct sh_dmae_slave chan_priv_rx;
+};
+
 struct sh_mmcif_plat_data {
 	void (*set_pwr)(struct platform_device *pdev, int state);
 	void (*down_pwr)(struct platform_device *pdev);
 	int (*get_cd)(struct platform_device *pdef);
-	u8	sup_pclk;	/* 1 :SH7757, 0: SH7724/SH7372 */
-	unsigned long caps;
-	u32	ocr;
+	struct sh_mmcif_dma	*dma;
+	u8			sup_pclk;	/* 1 :SH7757, 0: SH7724/SH7372 */
+	unsigned long		caps;
+	u32			ocr;
 };
 
 #define MMCIF_CE_CMD_SET	0x00000000
@@ -59,6 +66,32 @@
 #define MMCIF_CE_HOST_STS2	0x0000004C
 #define MMCIF_CE_VERSION	0x0000007C
 
+/* 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_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 CLKDIV_4		(1<<16) /* mmc clock frequency.
+					 * n: bus clock/(2^(n+1)) */
+#define CLKDIV_256		(7<<16) /* mmc clock frequency. (see above) */
+#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_VERSION */
+#define SOFT_RST_ON		(1 << 31)
+#define SOFT_RST_OFF		0
+
 static inline u32 sh_mmcif_readl(void __iomem *addr, int reg)
 {
 	return readl(addr + reg);
@@ -145,21 +178,20 @@
 
 static inline void sh_mmcif_boot_init(void __iomem *base)
 {
-	unsigned long tmp;
-
 	/* reset */
-	tmp = sh_mmcif_readl(base, MMCIF_CE_VERSION);
-	sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp | 0x80000000);
-	sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp & ~0x80000000);
+	sh_mmcif_writel(base, MMCIF_CE_VERSION, SOFT_RST_ON);
+	sh_mmcif_writel(base, MMCIF_CE_VERSION, SOFT_RST_OFF);
 
 	/* byte swap */
-	sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, 0x00010000);
+	sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP);
 
 	/* Set block size in MMCIF hardware */
 	sh_mmcif_writel(base, MMCIF_CE_BLOCK_SET, SH_MMCIF_BBS);
 
-	/* Enable the clock, set it to Bus clock/256 (about 325Khz)*/
-	sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01072fff);
+	/* Enable the clock, set it to Bus clock/256 (about 325Khz). */
+	sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL,
+			CLK_ENABLE | CLKDIV_256 | SRSPTO_256 |
+			SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
 
 	/* CMD0 */
 	sh_mmcif_boot_cmd(base, 0x00000040, 0);
@@ -184,7 +216,9 @@
 	unsigned long tmp;
 
 	/* In data transfer mode: Set clock to Bus clock/4 (about 20Mhz) */
-	sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01012fff);
+	sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL,
+			CLK_ENABLE | CLKDIV_4 | SRSPTO_256 |
+			SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
 
 	/* CMD9 - Get CSD */
 	sh_mmcif_boot_cmd(base, 0x09806000, 0x00010000);
diff --git a/include/linux/module.h b/include/linux/module.h
index 7575bbb..8b17fd8 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -308,6 +308,9 @@
 	/* The size of the executable code in each section.  */
 	unsigned int init_text_size, core_text_size;
 
+	/* Size of RO sections of the module (text+rodata) */
+	unsigned int init_ro_size, core_ro_size;
+
 	/* Arch-specific module values */
 	struct mod_arch_specific arch;
 
@@ -672,7 +675,6 @@
 {
 	return 0;
 }
-
 #endif /* CONFIG_MODULES */
 
 #ifdef CONFIG_SYSFS
@@ -687,6 +689,13 @@
 
 #define __MODULE_STRING(x) __stringify(x)
 
+#ifdef CONFIG_DEBUG_SET_MODULE_RONX
+extern void set_all_modules_text_rw(void);
+extern void set_all_modules_text_ro(void);
+#else
+static inline void set_all_modules_text_rw(void) { }
+static inline void set_all_modules_text_ro(void) { }
+#endif
 
 #ifdef CONFIG_GENERIC_BUG
 void module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 5e7a594..1869ea2 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -13,6 +13,7 @@
 #include <linux/list.h>
 #include <linux/nodemask.h>
 #include <linux/spinlock.h>
+#include <linux/seqlock.h>
 #include <asm/atomic.h>
 
 struct super_block;
@@ -46,12 +47,24 @@
 
 #define MNT_INTERNAL	0x4000
 
+struct mnt_pcp {
+	int mnt_count;
+	int mnt_writers;
+};
+
 struct vfsmount {
 	struct list_head mnt_hash;
 	struct vfsmount *mnt_parent;	/* fs we are mounted on */
 	struct dentry *mnt_mountpoint;	/* dentry of mountpoint */
 	struct dentry *mnt_root;	/* root of the mounted tree */
 	struct super_block *mnt_sb;	/* pointer to superblock */
+#ifdef CONFIG_SMP
+	struct mnt_pcp __percpu *mnt_pcp;
+	atomic_t mnt_longrefs;
+#else
+	int mnt_count;
+	int mnt_writers;
+#endif
 	struct list_head mnt_mounts;	/* list of children, anchored here */
 	struct list_head mnt_child;	/* and going through their mnt_child */
 	int mnt_flags;
@@ -70,57 +83,25 @@
 	struct mnt_namespace *mnt_ns;	/* containing namespace */
 	int mnt_id;			/* mount identifier */
 	int mnt_group_id;		/* peer group identifier */
-	/*
-	 * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
-	 * to let these frequently modified fields in a separate cache line
-	 * (so that reads of mnt_flags wont ping-pong on SMP machines)
-	 */
-	atomic_t mnt_count;
 	int mnt_expiry_mark;		/* true if marked for expiry */
 	int mnt_pinned;
 	int mnt_ghosts;
-#ifdef CONFIG_SMP
-	int __percpu *mnt_writers;
-#else
-	int mnt_writers;
-#endif
 };
 
-static inline int *get_mnt_writers_ptr(struct vfsmount *mnt)
-{
-#ifdef CONFIG_SMP
-	return mnt->mnt_writers;
-#else
-	return &mnt->mnt_writers;
-#endif
-}
-
-static inline struct vfsmount *mntget(struct vfsmount *mnt)
-{
-	if (mnt)
-		atomic_inc(&mnt->mnt_count);
-	return mnt;
-}
-
 struct file; /* forward dec */
 
 extern int mnt_want_write(struct vfsmount *mnt);
 extern int mnt_want_write_file(struct file *file);
 extern int mnt_clone_write(struct vfsmount *mnt);
 extern void mnt_drop_write(struct vfsmount *mnt);
-extern void mntput_no_expire(struct vfsmount *mnt);
+extern void mntput(struct vfsmount *mnt);
+extern struct vfsmount *mntget(struct vfsmount *mnt);
+extern void mntput_long(struct vfsmount *mnt);
+extern struct vfsmount *mntget_long(struct vfsmount *mnt);
 extern void mnt_pin(struct vfsmount *mnt);
 extern void mnt_unpin(struct vfsmount *mnt);
 extern int __mnt_is_readonly(struct vfsmount *mnt);
 
-static inline void mntput(struct vfsmount *mnt)
-{
-	if (mnt) {
-		mnt->mnt_expiry_mark = 0;
-		mntput_no_expire(mnt);
-	}
-}
-
 extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
 				      const char *name, void *data);
 
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index f363bc8..94b48bd 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -160,4 +160,8 @@
 extern void mutex_unlock(struct mutex *lock);
 extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
 
+#ifndef CONFIG_HAVE_ARCH_MUTEX_CPU_RELAX
+#define arch_mutex_cpu_relax()	cpu_relax()
+#endif
+
 #endif
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 05b441d..18d06ad 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -19,7 +19,10 @@
 	struct path	path;
 	struct qstr	last;
 	struct path	root;
+	struct file	*file;
+	struct inode	*inode; /* path.dentry.d_inode */
 	unsigned int	flags;
+	unsigned	seq;
 	int		last_type;
 	unsigned	depth;
 	char *saved_names[MAX_NESTED_LINKS + 1];
@@ -41,14 +44,15 @@
  *  - require a directory
  *  - ending slashes ok even for nonexistent files
  *  - internal "there are more path components" flag
- *  - locked when lookup done with dcache_lock held
  *  - dentry cache is untrusted; force a real lookup
  */
-#define LOOKUP_FOLLOW		 1
-#define LOOKUP_DIRECTORY	 2
-#define LOOKUP_CONTINUE		 4
-#define LOOKUP_PARENT		16
-#define LOOKUP_REVAL		64
+#define LOOKUP_FOLLOW		0x0001
+#define LOOKUP_DIRECTORY	0x0002
+#define LOOKUP_CONTINUE		0x0004
+
+#define LOOKUP_PARENT		0x0010
+#define LOOKUP_REVAL		0x0020
+#define LOOKUP_RCU		0x0040
 /*
  * Intent data
  */
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index ef66306..1c27f20 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -184,13 +184,13 @@
 	__u8			file_handle[6];
 };
 
-static inline struct ncp_server *NCP_SBP(struct super_block *sb)
+static inline struct ncp_server *NCP_SBP(const struct super_block *sb)
 {
 	return sb->s_fs_info;
 }
 
 #define NCP_SERVER(inode)	NCP_SBP((inode)->i_sb)
-static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode)
+static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode)
 {
 	return container_of(inode, struct ncp_inode_info, vfs_inode);
 }
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 29d504d..0779bb8 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -351,7 +351,7 @@
 extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int nfs_permission(struct inode *, int);
+extern int nfs_permission(struct inode *, int, unsigned int);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
 extern int nfs_attribute_timeout(struct inode *inode);
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index 06aab5e..c536f85 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -14,22 +14,14 @@
  * may be used to reset the timeout - for code which intentionally
  * disables interrupts for a long time. This call is stateless.
  */
-#ifdef ARCH_HAS_NMI_WATCHDOG
+#if defined(ARCH_HAS_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
 #include <asm/nmi.h>
 extern void touch_nmi_watchdog(void);
-extern void acpi_nmi_disable(void);
-extern void acpi_nmi_enable(void);
 #else
-#ifndef CONFIG_HARDLOCKUP_DETECTOR
 static inline void touch_nmi_watchdog(void)
 {
 	touch_softlockup_watchdog();
 }
-#else
-extern void touch_nmi_watchdog(void);
-#endif
-static inline void acpi_nmi_disable(void) { }
-static inline void acpi_nmi_enable(void) { }
 #endif
 
 /*
diff --git a/include/linux/path.h b/include/linux/path.h
index edc98de..a581e8c 100644
--- a/include/linux/path.h
+++ b/include/linux/path.h
@@ -10,7 +10,9 @@
 };
 
 extern void path_get(struct path *);
+extern void path_get_long(struct path *);
 extern void path_put(struct path *);
+extern void path_put_long(struct path *);
 
 static inline int path_equal(const struct path *path1, const struct path *path2)
 {
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 5095b83..27c3c6f 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -240,6 +240,21 @@
 	pscr_ret__;							\
 })
 
+#define __pcpu_size_call_return2(stem, variable, ...)			\
+({									\
+	typeof(variable) pscr2_ret__;					\
+	__verify_pcpu_ptr(&(variable));					\
+	switch(sizeof(variable)) {					\
+	case 1: pscr2_ret__ = stem##1(variable, __VA_ARGS__); break;	\
+	case 2: pscr2_ret__ = stem##2(variable, __VA_ARGS__); break;	\
+	case 4: pscr2_ret__ = stem##4(variable, __VA_ARGS__); break;	\
+	case 8: pscr2_ret__ = stem##8(variable, __VA_ARGS__); break;	\
+	default:							\
+		__bad_size_call_parameter(); break;			\
+	}								\
+	pscr2_ret__;							\
+})
+
 #define __pcpu_size_call(stem, variable, ...)				\
 do {									\
 	__verify_pcpu_ptr(&(variable));					\
@@ -402,6 +417,89 @@
 # define this_cpu_xor(pcp, val)		__pcpu_size_call(this_cpu_or_, (pcp), (val))
 #endif
 
+#define _this_cpu_generic_add_return(pcp, val)				\
+({									\
+	typeof(pcp) ret__;						\
+	preempt_disable();						\
+	__this_cpu_add(pcp, val);					\
+	ret__ = __this_cpu_read(pcp);					\
+	preempt_enable();						\
+	ret__;								\
+})
+
+#ifndef this_cpu_add_return
+# ifndef this_cpu_add_return_1
+#  define this_cpu_add_return_1(pcp, val)	_this_cpu_generic_add_return(pcp, val)
+# endif
+# ifndef this_cpu_add_return_2
+#  define this_cpu_add_return_2(pcp, val)	_this_cpu_generic_add_return(pcp, val)
+# endif
+# ifndef this_cpu_add_return_4
+#  define this_cpu_add_return_4(pcp, val)	_this_cpu_generic_add_return(pcp, val)
+# endif
+# ifndef this_cpu_add_return_8
+#  define this_cpu_add_return_8(pcp, val)	_this_cpu_generic_add_return(pcp, val)
+# endif
+# define this_cpu_add_return(pcp, val)	__pcpu_size_call_return2(this_cpu_add_return_, pcp, val)
+#endif
+
+#define this_cpu_sub_return(pcp, val)	this_cpu_add_return(pcp, -(val))
+#define this_cpu_inc_return(pcp)	this_cpu_add_return(pcp, 1)
+#define this_cpu_dec_return(pcp)	this_cpu_add_return(pcp, -1)
+
+#define _this_cpu_generic_xchg(pcp, nval)				\
+({	typeof(pcp) ret__;						\
+	preempt_disable();						\
+	ret__ = __this_cpu_read(pcp);					\
+	__this_cpu_write(pcp, nval);					\
+	preempt_enable();						\
+	ret__;								\
+})
+
+#ifndef this_cpu_xchg
+# ifndef this_cpu_xchg_1
+#  define this_cpu_xchg_1(pcp, nval)	_this_cpu_generic_xchg(pcp, nval)
+# endif
+# ifndef this_cpu_xchg_2
+#  define this_cpu_xchg_2(pcp, nval)	_this_cpu_generic_xchg(pcp, nval)
+# endif
+# ifndef this_cpu_xchg_4
+#  define this_cpu_xchg_4(pcp, nval)	_this_cpu_generic_xchg(pcp, nval)
+# endif
+# ifndef this_cpu_xchg_8
+#  define this_cpu_xchg_8(pcp, nval)	_this_cpu_generic_xchg(pcp, nval)
+# endif
+# define this_cpu_xchg(pcp, nval)	\
+	__pcpu_size_call_return2(this_cpu_xchg_, (pcp), nval)
+#endif
+
+#define _this_cpu_generic_cmpxchg(pcp, oval, nval)			\
+({	typeof(pcp) ret__;						\
+	preempt_disable();						\
+	ret__ = __this_cpu_read(pcp);					\
+	if (ret__ == (oval))						\
+		__this_cpu_write(pcp, nval);				\
+	preempt_enable();						\
+	ret__;								\
+})
+
+#ifndef this_cpu_cmpxchg
+# ifndef this_cpu_cmpxchg_1
+#  define this_cpu_cmpxchg_1(pcp, oval, nval)	_this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef this_cpu_cmpxchg_2
+#  define this_cpu_cmpxchg_2(pcp, oval, nval)	_this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef this_cpu_cmpxchg_4
+#  define this_cpu_cmpxchg_4(pcp, oval, nval)	_this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef this_cpu_cmpxchg_8
+#  define this_cpu_cmpxchg_8(pcp, oval, nval)	_this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# define this_cpu_cmpxchg(pcp, oval, nval)	\
+	__pcpu_size_call_return2(this_cpu_cmpxchg_, pcp, oval, nval)
+#endif
+
 /*
  * Generic percpu operations that do not require preemption handling.
  * Either we do not care about races or the caller has the
@@ -529,11 +627,87 @@
 # define __this_cpu_xor(pcp, val)	__pcpu_size_call(__this_cpu_xor_, (pcp), (val))
 #endif
 
+#define __this_cpu_generic_add_return(pcp, val)				\
+({									\
+	__this_cpu_add(pcp, val);					\
+	__this_cpu_read(pcp);						\
+})
+
+#ifndef __this_cpu_add_return
+# ifndef __this_cpu_add_return_1
+#  define __this_cpu_add_return_1(pcp, val)	__this_cpu_generic_add_return(pcp, val)
+# endif
+# ifndef __this_cpu_add_return_2
+#  define __this_cpu_add_return_2(pcp, val)	__this_cpu_generic_add_return(pcp, val)
+# endif
+# ifndef __this_cpu_add_return_4
+#  define __this_cpu_add_return_4(pcp, val)	__this_cpu_generic_add_return(pcp, val)
+# endif
+# ifndef __this_cpu_add_return_8
+#  define __this_cpu_add_return_8(pcp, val)	__this_cpu_generic_add_return(pcp, val)
+# endif
+# define __this_cpu_add_return(pcp, val)	__pcpu_size_call_return2(this_cpu_add_return_, pcp, val)
+#endif
+
+#define __this_cpu_sub_return(pcp, val)	this_cpu_add_return(pcp, -(val))
+#define __this_cpu_inc_return(pcp)	this_cpu_add_return(pcp, 1)
+#define __this_cpu_dec_return(pcp)	this_cpu_add_return(pcp, -1)
+
+#define __this_cpu_generic_xchg(pcp, nval)				\
+({	typeof(pcp) ret__;						\
+	ret__ = __this_cpu_read(pcp);					\
+	__this_cpu_write(pcp, nval);					\
+	ret__;								\
+})
+
+#ifndef __this_cpu_xchg
+# ifndef __this_cpu_xchg_1
+#  define __this_cpu_xchg_1(pcp, nval)	__this_cpu_generic_xchg(pcp, nval)
+# endif
+# ifndef __this_cpu_xchg_2
+#  define __this_cpu_xchg_2(pcp, nval)	__this_cpu_generic_xchg(pcp, nval)
+# endif
+# ifndef __this_cpu_xchg_4
+#  define __this_cpu_xchg_4(pcp, nval)	__this_cpu_generic_xchg(pcp, nval)
+# endif
+# ifndef __this_cpu_xchg_8
+#  define __this_cpu_xchg_8(pcp, nval)	__this_cpu_generic_xchg(pcp, nval)
+# endif
+# define __this_cpu_xchg(pcp, nval)	\
+	__pcpu_size_call_return2(__this_cpu_xchg_, (pcp), nval)
+#endif
+
+#define __this_cpu_generic_cmpxchg(pcp, oval, nval)			\
+({									\
+	typeof(pcp) ret__;						\
+	ret__ = __this_cpu_read(pcp);					\
+	if (ret__ == (oval))						\
+		__this_cpu_write(pcp, nval);				\
+	ret__;								\
+})
+
+#ifndef __this_cpu_cmpxchg
+# ifndef __this_cpu_cmpxchg_1
+#  define __this_cpu_cmpxchg_1(pcp, oval, nval)	__this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef __this_cpu_cmpxchg_2
+#  define __this_cpu_cmpxchg_2(pcp, oval, nval)	__this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef __this_cpu_cmpxchg_4
+#  define __this_cpu_cmpxchg_4(pcp, oval, nval)	__this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef __this_cpu_cmpxchg_8
+#  define __this_cpu_cmpxchg_8(pcp, oval, nval)	__this_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# define __this_cpu_cmpxchg(pcp, oval, nval)	\
+	__pcpu_size_call_return2(__this_cpu_cmpxchg_, pcp, oval, nval)
+#endif
+
 /*
  * IRQ safe versions of the per cpu RMW operations. Note that these operations
  * are *not* safe against modification of the same variable from another
  * processors (which one gets when using regular atomic operations)
- . They are guaranteed to be atomic vs. local interrupts and
+ * They are guaranteed to be atomic vs. local interrupts and
  * preemption only.
  */
 #define irqsafe_cpu_generic_to_op(pcp, val, op)				\
@@ -620,4 +794,33 @@
 # define irqsafe_cpu_xor(pcp, val) __pcpu_size_call(irqsafe_cpu_xor_, (val))
 #endif
 
+#define irqsafe_cpu_generic_cmpxchg(pcp, oval, nval)			\
+({									\
+	typeof(pcp) ret__;						\
+	unsigned long flags;						\
+	local_irq_save(flags);						\
+	ret__ = __this_cpu_read(pcp);					\
+	if (ret__ == (oval))						\
+		__this_cpu_write(pcp, nval);				\
+	local_irq_restore(flags);					\
+	ret__;								\
+})
+
+#ifndef irqsafe_cpu_cmpxchg
+# ifndef irqsafe_cpu_cmpxchg_1
+#  define irqsafe_cpu_cmpxchg_1(pcp, oval, nval)	irqsafe_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_2
+#  define irqsafe_cpu_cmpxchg_2(pcp, oval, nval)	irqsafe_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_4
+#  define irqsafe_cpu_cmpxchg_4(pcp, oval, nval)	irqsafe_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_8
+#  define irqsafe_cpu_cmpxchg_8(pcp, oval, nval)	irqsafe_cpu_generic_cmpxchg(pcp, oval, nval)
+# endif
+# define irqsafe_cpu_cmpxchg(pcp, oval, nval)		\
+	__pcpu_size_call_return2(irqsafe_cpu_cmpxchg_, (pcp), oval, nval)
+#endif
+
 #endif /* __LINUX_PERCPU_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 4f1279e..dda5b0a 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -215,8 +215,9 @@
 				 */
 				precise_ip     :  2, /* skid constraint       */
 				mmap_data      :  1, /* non-exec mmap data    */
+				sample_id_all  :  1, /* sample_type all events */
 
-				__reserved_1   : 46;
+				__reserved_1   : 45;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
@@ -327,6 +328,15 @@
 enum perf_event_type {
 
 	/*
+	 * If perf_event_attr.sample_id_all is set then all event types will
+	 * have the sample_type selected fields related to where/when
+	 * (identity) an event took place (TID, TIME, ID, CPU, STREAM_ID)
+	 * described in PERF_RECORD_SAMPLE below, it will be stashed just after
+	 * the perf_event_header and the fields already present for the existing
+	 * fields, i.e. at the end of the payload. That way a newer perf.data
+	 * file will be supported by older perf tools, with these new optional
+	 * fields being ignored.
+	 *
 	 * The MMAP events record the PROT_EXEC mappings so that we can
 	 * correlate userspace IPs to code. They have the following structure:
 	 *
@@ -578,6 +588,10 @@
 struct pmu {
 	struct list_head		entry;
 
+	struct device			*dev;
+	char				*name;
+	int				type;
+
 	int * __percpu			pmu_disable_count;
 	struct perf_cpu_context * __percpu pmu_cpu_context;
 	int				task_ctx_nr;
@@ -758,6 +772,9 @@
 	u64				shadow_ctx_time;
 
 	struct perf_event_attr		attr;
+	u16				header_size;
+	u16				id_header_size;
+	u16				read_size;
 	struct hw_perf_event		hw;
 
 	struct perf_event_context	*ctx;
@@ -903,7 +920,7 @@
 
 #ifdef CONFIG_PERF_EVENTS
 
-extern int perf_pmu_register(struct pmu *pmu);
+extern int perf_pmu_register(struct pmu *pmu, char *name, int type);
 extern void perf_pmu_unregister(struct pmu *pmu);
 
 extern int perf_num_counters(void);
@@ -970,6 +987,11 @@
 				 struct perf_sample_data *data,
 				 struct pt_regs *regs);
 
+static inline bool is_sampling_event(struct perf_event *event)
+{
+	return event->attr.sample_period != 0;
+}
+
 /*
  * Return 1 for a software event, 0 for a hardware event
  */
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 6760816..d68283a 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -108,6 +108,25 @@
 	return acl;
 }
 
+static inline int negative_cached_acl(struct inode *inode, int type)
+{
+	struct posix_acl **p, *acl;
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		p = &inode->i_acl;
+		break;
+	case ACL_TYPE_DEFAULT:
+		p = &inode->i_default_acl;
+		break;
+	default:
+		BUG();
+	}
+	acl = ACCESS_ONCE(*p);
+	if (acl)
+		return 0;
+	return 1;
+}
+
 static inline void set_cached_acl(struct inode *inode,
 				  int type,
 				  struct posix_acl *acl)
diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h
new file mode 100644
index 0000000..2f691e4
--- /dev/null
+++ b/include/linux/pxa2xx_ssp.h
@@ -0,0 +1,209 @@
+/*
+ *  pxa2xx_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 __LINUX_SSP_H
+#define __LINUX_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 SSSR_ALT_FRM_MASK	3	/* Masks the SFRM signal number */
+#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 */
+
+#ifdef CONFIG_ARCH_PXA
+#define RX_THRESH_DFLT	8
+#define TX_THRESH_DFLT	8
+
+#define SSSR_TFL_MASK	(0xf << 8)	/* Transmit FIFO Level mask */
+#define SSSR_RFL_MASK	(0xf << 12)	/* Receive FIFO Level mask */
+
+#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] */
+
+#else
+
+#define RX_THRESH_DFLT	2
+#define TX_THRESH_DFLT	2
+
+#define SSSR_TFL_MASK	(0x3 << 8)	/* Transmit FIFO Level mask */
+#define SSSR_RFL_MASK	(0x3 << 12)	/* Receive FIFO Level mask */
+
+#define SSCR1_TFT	(0x000000c0)	/* Transmit FIFO Threshold (mask) */
+#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */
+#define SSCR1_RFT	(0x00000c00)	/* Receive FIFO Threshold (mask) */
+#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
+#endif
+
+/* 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,
+	CE4100_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
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index f31ef61..2dea94f 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -241,11 +241,6 @@
 #define list_first_entry_rcu(ptr, type, member) \
 	list_entry_rcu((ptr)->next, type, member)
 
-#define __list_for_each_rcu(pos, head) \
-	for (pos = rcu_dereference_raw(list_next_rcu(head)); \
-		pos != (head); \
-		pos = rcu_dereference_raw(list_next_rcu((pos)))
-
 /**
  * list_for_each_entry_rcu	-	iterate over rcu list of given type
  * @pos:	the type * to use as a loop cursor.
diff --git a/include/linux/rculist_bl.h b/include/linux/rculist_bl.h
new file mode 100644
index 0000000..b872b49
--- /dev/null
+++ b/include/linux/rculist_bl.h
@@ -0,0 +1,127 @@
+#ifndef _LINUX_RCULIST_BL_H
+#define _LINUX_RCULIST_BL_H
+
+/*
+ * RCU-protected bl list version. See include/linux/list_bl.h.
+ */
+#include <linux/list_bl.h>
+#include <linux/rcupdate.h>
+
+static inline void hlist_bl_set_first_rcu(struct hlist_bl_head *h,
+					struct hlist_bl_node *n)
+{
+	LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK);
+	LIST_BL_BUG_ON(!((unsigned long)h->first & LIST_BL_LOCKMASK));
+	rcu_assign_pointer(h->first,
+		(struct hlist_bl_node *)((unsigned long)n | LIST_BL_LOCKMASK));
+}
+
+static inline struct hlist_bl_node *hlist_bl_first_rcu(struct hlist_bl_head *h)
+{
+	return (struct hlist_bl_node *)
+		((unsigned long)rcu_dereference(h->first) & ~LIST_BL_LOCKMASK);
+}
+
+/**
+ * hlist_bl_del_init_rcu - deletes entry from hash list with re-initialization
+ * @n: the element to delete from the hash list.
+ *
+ * Note: hlist_bl_unhashed() on the node returns true after this. It is
+ * useful for RCU based read lockfree traversal if the writer side
+ * must know if the list entry is still hashed or already unhashed.
+ *
+ * In particular, it means that we can not poison the forward pointers
+ * that may still be used for walking the hash list and we can only
+ * zero the pprev pointer so list_unhashed() will return true after
+ * this.
+ *
+ * The caller must take whatever precautions are necessary (such as
+ * holding appropriate locks) to avoid racing with another
+ * list-mutation primitive, such as hlist_bl_add_head_rcu() or
+ * hlist_bl_del_rcu(), running on this same list.  However, it is
+ * perfectly legal to run concurrently with the _rcu list-traversal
+ * primitives, such as hlist_bl_for_each_entry_rcu().
+ */
+static inline void hlist_bl_del_init_rcu(struct hlist_bl_node *n)
+{
+	if (!hlist_bl_unhashed(n)) {
+		__hlist_bl_del(n);
+		n->pprev = NULL;
+	}
+}
+
+/**
+ * hlist_bl_del_rcu - deletes entry from hash list without re-initialization
+ * @n: the element to delete from the hash list.
+ *
+ * Note: hlist_bl_unhashed() on entry does not return true after this,
+ * the entry is in an undefined state. It is useful for RCU based
+ * lockfree traversal.
+ *
+ * In particular, it means that we can not poison the forward
+ * pointers that may still be used for walking the hash list.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
+ * or hlist_bl_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * hlist_bl_for_each_entry().
+ */
+static inline void hlist_bl_del_rcu(struct hlist_bl_node *n)
+{
+	__hlist_bl_del(n);
+	n->pprev = LIST_POISON2;
+}
+
+/**
+ * hlist_bl_add_head_rcu
+ * @n: the element to add to the hash list.
+ * @h: the list to add to.
+ *
+ * Description:
+ * Adds the specified element to the specified hlist_bl,
+ * while permitting racing traversals.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
+ * or hlist_bl_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * hlist_bl_for_each_entry_rcu(), used to prevent memory-consistency
+ * problems on Alpha CPUs.  Regardless of the type of CPU, the
+ * list-traversal primitive must be guarded by rcu_read_lock().
+ */
+static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n,
+					struct hlist_bl_head *h)
+{
+	struct hlist_bl_node *first;
+
+	/* don't need hlist_bl_first_rcu because we're under lock */
+	first = hlist_bl_first(h);
+
+	n->next = first;
+	if (first)
+		first->pprev = &n->next;
+	n->pprev = &h->first;
+
+	/* need _rcu because we can have concurrent lock free readers */
+	hlist_bl_set_first_rcu(h, n);
+}
+/**
+ * hlist_bl_for_each_entry_rcu - iterate over rcu list of given type
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_bl_node to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_bl_node within the struct.
+ *
+ */
+#define hlist_bl_for_each_entry_rcu(tpos, pos, head, member)		\
+	for (pos = hlist_bl_first_rcu(head);				\
+		pos &&							\
+		({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \
+		pos = rcu_dereference_raw(pos->next))
+
+#endif
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 03cda7b..af56148 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -47,6 +47,8 @@
 extern int rcutorture_runnable; /* for sysctl */
 #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
 
+#define UINT_CMP_GE(a, b)	(UINT_MAX / 2 >= (a) - (b))
+#define UINT_CMP_LT(a, b)	(UINT_MAX / 2 < (a) - (b))
 #define ULONG_CMP_GE(a, b)	(ULONG_MAX / 2 >= (a) - (b))
 #define ULONG_CMP_LT(a, b)	(ULONG_MAX / 2 < (a) - (b))
 
@@ -66,7 +68,6 @@
 extern void synchronize_sched(void);
 extern void rcu_barrier_bh(void);
 extern void rcu_barrier_sched(void);
-extern void synchronize_sched_expedited(void);
 extern int sched_expedited_torture_stats(char *page);
 
 static inline void __rcu_read_lock_bh(void)
@@ -118,7 +119,6 @@
 #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
 
 /* Internal to kernel */
-extern void rcu_init(void);
 extern void rcu_sched_qs(int cpu);
 extern void rcu_bh_qs(int cpu);
 extern void rcu_check_callbacks(int cpu, int user);
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index 13877cb..30ebd7c 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -27,7 +27,9 @@
 
 #include <linux/cache.h>
 
-#define rcu_init_sched()	do { } while (0)
+static inline void rcu_init(void)
+{
+}
 
 #ifdef CONFIG_TINY_RCU
 
@@ -58,6 +60,11 @@
 	synchronize_sched();
 }
 
+static inline void synchronize_sched_expedited(void)
+{
+	synchronize_sched();
+}
+
 #ifdef CONFIG_TINY_RCU
 
 static inline void rcu_preempt_note_context_switch(void)
@@ -125,16 +132,12 @@
 }
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-
 extern int rcu_scheduler_active __read_mostly;
 extern void rcu_scheduler_starting(void);
-
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
-
 static inline void rcu_scheduler_starting(void)
 {
 }
-
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 #endif /* __LINUX_RCUTINY_H */
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 95518e6..3a93348 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -30,6 +30,7 @@
 #ifndef __LINUX_RCUTREE_H
 #define __LINUX_RCUTREE_H
 
+extern void rcu_init(void);
 extern void rcu_note_context_switch(int cpu);
 extern int rcu_needs_cpu(int cpu);
 extern void rcu_cpu_stall_reset(void);
@@ -47,6 +48,7 @@
 #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
 
 extern void synchronize_rcu_bh(void);
+extern void synchronize_sched_expedited(void);
 extern void synchronize_rcu_expedited(void);
 
 static inline void synchronize_rcu_bh_expedited(void)
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index b2cf208..3b94c91 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -41,7 +41,7 @@
 int reiserfs_lookup_privroot(struct super_block *sb);
 int reiserfs_delete_xattrs(struct inode *inode);
 int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
-int reiserfs_permission(struct inode *inode, int mask);
+int reiserfs_permission(struct inode *inode, int mask, unsigned int flags);
 
 #ifdef CONFIG_REISERFS_FS_XATTR
 #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2238745..341acbbc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -316,6 +316,7 @@
 				  size_t *lenp, loff_t *ppos);
 extern unsigned int  softlockup_panic;
 extern int softlockup_thresh;
+void lockup_detector_init(void);
 #else
 static inline void touch_softlockup_watchdog(void)
 {
@@ -326,6 +327,9 @@
 static inline void touch_all_softlockup_watchdogs(void)
 {
 }
+static inline void lockup_detector_init(void)
+{
+}
 #endif
 
 #ifdef CONFIG_DETECT_HUNG_TASK
@@ -509,6 +513,8 @@
 	spinlock_t lock;
 };
 
+struct autogroup;
+
 /*
  * NOTE! "signal_struct" does not have it's own
  * locking, because a shared signal_struct always
@@ -576,6 +582,9 @@
 
 	struct tty_struct *tty; /* NULL if no tty */
 
+#ifdef CONFIG_SCHED_AUTOGROUP
+	struct autogroup *autogroup;
+#endif
 	/*
 	 * Cumulative resource counters for dead threads in the group,
 	 * and for reaped dead child processes forked by this group.
@@ -1229,13 +1238,18 @@
 #ifdef CONFIG_TREE_PREEMPT_RCU
 	struct rcu_node *rcu_blocked_node;
 #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
+#ifdef CONFIG_RCU_BOOST
+	struct rt_mutex *rcu_boost_mutex;
+#endif /* #ifdef CONFIG_RCU_BOOST */
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
 	struct sched_info sched_info;
 #endif
 
 	struct list_head tasks;
+#ifdef CONFIG_SMP
 	struct plist_node pushable_tasks;
+#endif
 
 	struct mm_struct *mm, *active_mm;
 #if defined(SPLIT_RSS_COUNTING)
@@ -1759,7 +1773,8 @@
 #ifdef CONFIG_PREEMPT_RCU
 
 #define RCU_READ_UNLOCK_BLOCKED (1 << 0) /* blocked while in RCU read-side. */
-#define RCU_READ_UNLOCK_NEED_QS (1 << 1) /* RCU core needs CPU response. */
+#define RCU_READ_UNLOCK_BOOSTED (1 << 1) /* boosted while in RCU read-side. */
+#define RCU_READ_UNLOCK_NEED_QS (1 << 2) /* RCU core needs CPU response. */
 
 static inline void rcu_copy_process(struct task_struct *p)
 {
@@ -1767,7 +1782,10 @@
 	p->rcu_read_unlock_special = 0;
 #ifdef CONFIG_TREE_PREEMPT_RCU
 	p->rcu_blocked_node = NULL;
-#endif
+#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
+#ifdef CONFIG_RCU_BOOST
+	p->rcu_boost_mutex = NULL;
+#endif /* #ifdef CONFIG_RCU_BOOST */
 	INIT_LIST_HEAD(&p->rcu_node_entry);
 }
 
@@ -1872,14 +1890,11 @@
 extern void sched_clock_idle_wakeup_event(u64 delta_ns);
 
 #ifdef CONFIG_HOTPLUG_CPU
-extern void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p);
 extern void idle_task_exit(void);
 #else
 static inline void idle_task_exit(void) {}
 #endif
 
-extern void sched_idle_next(void);
-
 #if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
 extern void wake_up_idle_cpu(int cpu);
 #else
@@ -1889,8 +1904,6 @@
 extern unsigned int sysctl_sched_latency;
 extern unsigned int sysctl_sched_min_granularity;
 extern unsigned int sysctl_sched_wakeup_granularity;
-extern unsigned int sysctl_sched_shares_ratelimit;
-extern unsigned int sysctl_sched_shares_thresh;
 extern unsigned int sysctl_sched_child_runs_first;
 
 enum sched_tunable_scaling {
@@ -1906,6 +1919,7 @@
 extern unsigned int sysctl_sched_nr_migrate;
 extern unsigned int sysctl_sched_time_avg;
 extern unsigned int sysctl_timer_migration;
+extern unsigned int sysctl_sched_shares_window;
 
 int sched_proc_update_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *length,
@@ -1931,6 +1945,24 @@
 
 extern unsigned int sysctl_sched_compat_yield;
 
+#ifdef CONFIG_SCHED_AUTOGROUP
+extern unsigned int sysctl_sched_autogroup_enabled;
+
+extern void sched_autogroup_create_attach(struct task_struct *p);
+extern void sched_autogroup_detach(struct task_struct *p);
+extern void sched_autogroup_fork(struct signal_struct *sig);
+extern void sched_autogroup_exit(struct signal_struct *sig);
+#ifdef CONFIG_PROC_FS
+extern void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m);
+extern int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice);
+#endif
+#else
+static inline void sched_autogroup_create_attach(struct task_struct *p) { }
+static inline void sched_autogroup_detach(struct task_struct *p) { }
+static inline void sched_autogroup_fork(struct signal_struct *sig) { }
+static inline void sched_autogroup_exit(struct signal_struct *sig) { }
+#endif
+
 #ifdef CONFIG_RT_MUTEXES
 extern int rt_mutex_getprio(struct task_struct *p);
 extern void rt_mutex_setprio(struct task_struct *p, int prio);
@@ -1949,9 +1981,10 @@
 extern int can_nice(const struct task_struct *p, const int nice);
 extern int task_curr(const struct task_struct *p);
 extern int idle_cpu(int cpu);
-extern int sched_setscheduler(struct task_struct *, int, struct sched_param *);
+extern int sched_setscheduler(struct task_struct *, int,
+			      const struct sched_param *);
 extern int sched_setscheduler_nocheck(struct task_struct *, int,
-				      struct sched_param *);
+				      const struct sched_param *);
 extern struct task_struct *idle_task(int cpu);
 extern struct task_struct *curr_task(int cpu);
 extern void set_curr_task(int cpu, struct task_struct *p);
@@ -2478,7 +2511,7 @@
 
 #ifdef CONFIG_CGROUP_SCHED
 
-extern struct task_group init_task_group;
+extern struct task_group root_task_group;
 
 extern struct task_group *sched_create_group(struct task_group *parent);
 extern void sched_destroy_group(struct task_group *tg);
diff --git a/include/linux/security.h b/include/linux/security.h
index d47a4c2..1ac42475 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -457,7 +457,6 @@
  *	called when the actual read/write operations are performed.
  *	@inode contains the inode structure to check.
  *	@mask contains the permission mask.
- *	@nd contains the nameidata (may be NULL).
  *	Return 0 if permission is granted.
  * @inode_setattr:
  *	Check permission before setting file attributes.  Note that the kernel
@@ -1713,6 +1712,7 @@
 int security_inode_readlink(struct dentry *dentry);
 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
 int security_inode_permission(struct inode *inode, int mask);
+int security_inode_exec_permission(struct inode *inode, unsigned int flags);
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
 int security_inode_setxattr(struct dentry *dentry, const char *name,
@@ -2102,6 +2102,12 @@
 	return 0;
 }
 
+static inline int security_inode_exec_permission(struct inode *inode,
+						  unsigned int flags)
+{
+	return 0;
+}
+
 static inline int security_inode_setattr(struct dentry *dentry,
 					  struct iattr *attr)
 {
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 632205c..e98cd2e 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -107,7 +107,7 @@
 {
 	smp_rmb();
 
-	return (sl->sequence != start);
+	return unlikely(sl->sequence != start);
 }
 
 
@@ -125,14 +125,25 @@
 #define SEQCNT_ZERO { 0 }
 #define seqcount_init(x)	do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0)
 
-/* Start of read using pointer to a sequence counter only.  */
-static inline unsigned read_seqcount_begin(const seqcount_t *s)
+/**
+ * __read_seqcount_begin - begin a seq-read critical section (without barrier)
+ * @s: pointer to seqcount_t
+ * Returns: count to be passed to read_seqcount_retry
+ *
+ * __read_seqcount_begin is like read_seqcount_begin, but has no smp_rmb()
+ * barrier. Callers should ensure that smp_rmb() or equivalent ordering is
+ * provided before actually loading any of the variables that are to be
+ * protected in this critical section.
+ *
+ * Use carefully, only in critical code, and comment how the barrier is
+ * provided.
+ */
+static inline unsigned __read_seqcount_begin(const seqcount_t *s)
 {
 	unsigned ret;
 
 repeat:
 	ret = s->sequence;
-	smp_rmb();
 	if (unlikely(ret & 1)) {
 		cpu_relax();
 		goto repeat;
@@ -140,14 +151,56 @@
 	return ret;
 }
 
-/*
- * Test if reader processed invalid data because sequence number has changed.
+/**
+ * read_seqcount_begin - begin a seq-read critical section
+ * @s: pointer to seqcount_t
+ * Returns: count to be passed to read_seqcount_retry
+ *
+ * read_seqcount_begin opens a read critical section of the given seqcount.
+ * Validity of the critical section is tested by checking read_seqcount_retry
+ * function.
+ */
+static inline unsigned read_seqcount_begin(const seqcount_t *s)
+{
+	unsigned ret = __read_seqcount_begin(s);
+	smp_rmb();
+	return ret;
+}
+
+/**
+ * __read_seqcount_retry - end a seq-read critical section (without barrier)
+ * @s: pointer to seqcount_t
+ * @start: count, from read_seqcount_begin
+ * Returns: 1 if retry is required, else 0
+ *
+ * __read_seqcount_retry is like read_seqcount_retry, but has no smp_rmb()
+ * barrier. Callers should ensure that smp_rmb() or equivalent ordering is
+ * provided before actually loading any of the variables that are to be
+ * protected in this critical section.
+ *
+ * Use carefully, only in critical code, and comment how the barrier is
+ * provided.
+ */
+static inline int __read_seqcount_retry(const seqcount_t *s, unsigned start)
+{
+	return unlikely(s->sequence != start);
+}
+
+/**
+ * read_seqcount_retry - end a seq-read critical section
+ * @s: pointer to seqcount_t
+ * @start: count, from read_seqcount_begin
+ * Returns: 1 if retry is required, else 0
+ *
+ * read_seqcount_retry closes a read critical section of the given seqcount.
+ * If the critical section was invalid, it must be ignored (and typically
+ * retried).
  */
 static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
 {
 	smp_rmb();
 
-	return s->sequence != start;
+	return __read_seqcount_retry(s, start);
 }
 
 
@@ -167,6 +220,19 @@
 	s->sequence++;
 }
 
+/**
+ * write_seqcount_barrier - invalidate in-progress read-side seq operations
+ * @s: pointer to seqcount_t
+ *
+ * After write_seqcount_barrier, no read-side seq operations will complete
+ * successfully and see data older than this.
+ */
+static inline void write_seqcount_barrier(seqcount_t *s)
+{
+	smp_wmb();
+	s->sequence+=2;
+}
+
 /*
  * Possible sw/hw IRQ protected versions of the interfaces.
  */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 212eb4c..a23fa29 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -95,7 +95,7 @@
 /* PPC CPM type number */
 #define PORT_CPM        58
 
-/* MPC52xx type numbers */
+/* MPC52xx (and MPC512x) type numbers */
 #define PORT_MPC52xx	59
 
 /* IBM icom */
@@ -199,6 +199,9 @@
 /* TI OMAP-UART */
 #define PORT_OMAP	96
 
+/* VIA VT8500 SoC */
+#define PORT_VT8500	97
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
@@ -311,6 +314,7 @@
 #define UPIO_TSI		(5)			/* Tsi108/109 type IO */
 #define UPIO_DWAPB		(6)			/* DesignWare APB UART */
 #define UPIO_RM9000		(7)			/* RM9000 type IO */
+#define UPIO_DWAPB32		(8)			/* DesignWare APB UART (32 bit accesses) */
 
 	unsigned int		read_status_mask;	/* driver specific */
 	unsigned int		ignore_status_mask;	/* driver specific */
@@ -361,6 +365,7 @@
 	struct device		*dev;			/* parent device */
 	unsigned char		hub6;			/* this should be in the 8250 driver */
 	unsigned char		suspended;
+	unsigned char		irq_wake;
 	unsigned char		unused[2];
 	void			*private_data;		/* generic platform data pointer */
 };
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index c7a0ce1..3ecb71a 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -99,6 +99,13 @@
 #define UART_LCR_WLEN7		0x02 /* Wordlength: 7 bits */
 #define UART_LCR_WLEN8		0x03 /* Wordlength: 8 bits */
 
+/*
+ * Access to some registers depends on register access / configuration
+ * mode.
+ */
+#define UART_LCR_CONF_MODE_A	UART_LCR_DLAB	/* Configutation mode A */
+#define UART_LCR_CONF_MODE_B	0xBF		/* Configutation mode B */
+
 #define UART_MCR	4	/* Out: Modem Control Register */
 #define UART_MCR_CLKSEL		0x80 /* Divide clock by 4 (TI16C752, EFR[4]=1) */
 #define UART_MCR_TCRTLR		0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
@@ -341,5 +348,17 @@
 #define UART_OMAP_SYSS		0x16	/* System status register */
 #define UART_OMAP_WER		0x17	/* Wake-up enable register */
 
+/*
+ * These are the definitions for the MDR1 register
+ */
+#define UART_OMAP_MDR1_16X_MODE		0x00	/* UART 16x mode */
+#define UART_OMAP_MDR1_SIR_MODE		0x01	/* SIR mode */
+#define UART_OMAP_MDR1_16X_ABAUD_MODE	0x02	/* UART 16x auto-baud */
+#define UART_OMAP_MDR1_13X_MODE		0x03	/* UART 13x mode */
+#define UART_OMAP_MDR1_MIR_MODE		0x04	/* MIR mode */
+#define UART_OMAP_MDR1_FIR_MODE		0x05	/* FIR mode */
+#define UART_OMAP_MDR1_CIR_MODE		0x06	/* CIR mode */
+#define UART_OMAP_MDR1_DISABLE		0x07	/* Disable (default state) */
+
 #endif /* _LINUX_SERIAL_REG_H */
 
diff --git a/include/linux/sfi.h b/include/linux/sfi.h
index 7f770c6..fe81791 100644
--- a/include/linux/sfi.h
+++ b/include/linux/sfi.h
@@ -77,6 +77,8 @@
 #define SFI_OEM_ID_SIZE		6
 #define SFI_OEM_TABLE_ID_SIZE	8
 
+#define SFI_NAME_LEN		16
+
 #define SFI_SYST_SEARCH_BEGIN		0x000E0000
 #define SFI_SYST_SEARCH_END		0x000FFFFF
 
@@ -156,13 +158,13 @@
 	u16	addr;
 	u8	irq;
 	u32	max_freq;
-	char	name[16];
+	char	name[SFI_NAME_LEN];
 } __packed;
 
 struct sfi_gpio_table_entry {
-	char	controller_name[16];
+	char	controller_name[SFI_NAME_LEN];
 	u16	pin_no;
-	char	pin_name[16];
+	char	pin_name[SFI_NAME_LEN];
 } __packed;
 
 typedef int (*sfi_table_handler) (struct sfi_table_header *table);
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 59260e2..fa90866 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -106,8 +106,6 @@
 void kmem_cache_free(struct kmem_cache *, void *);
 unsigned int kmem_cache_size(struct kmem_cache *);
 const char *kmem_cache_name(struct kmem_cache *);
-int kern_ptr_validate(const void *ptr, unsigned long size);
-int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
 
 /*
  * Please use this macro to create slab caches. Simply specify the
diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h
index c91302f..6cd10f6 100644
--- a/include/linux/spi/dw_spi.h
+++ b/include/linux/spi/dw_spi.h
@@ -1,5 +1,6 @@
 #ifndef DW_SPI_HEADER_H
 #define DW_SPI_HEADER_H
+
 #include <linux/io.h>
 
 /* Bit fields in CTRLR0 */
@@ -82,6 +83,13 @@
 				though only low 16 bits matters */
 } __packed;
 
+struct dw_spi;
+struct dw_spi_dma_ops {
+	int (*dma_init)(struct dw_spi *dws);
+	void (*dma_exit)(struct dw_spi *dws);
+	int (*dma_transfer)(struct dw_spi *dws, int cs_change);
+};
+
 struct dw_spi {
 	struct spi_master	*master;
 	struct spi_device	*cur_dev;
@@ -136,13 +144,15 @@
 	/* Dma info */
 	int			dma_inited;
 	struct dma_chan		*txchan;
+	struct scatterlist	tx_sgl;
 	struct dma_chan		*rxchan;
-	int			txdma_done;
-	int			rxdma_done;
-	u64			tx_param;
-	u64			rx_param;
+	struct scatterlist	rx_sgl;
+	int			dma_chan_done;
 	struct device		*dma_dev;
-	dma_addr_t		dma_addr;
+	dma_addr_t		dma_addr; /* phy address of the Data register */
+	struct dw_spi_dma_ops	*dma_ops;
+	void			*dma_priv; /* platform relate info */
+	struct pci_dev		*dmac;
 
 	/* Bus interface info */
 	void			*priv;
@@ -216,4 +226,8 @@
 extern void dw_spi_remove_host(struct dw_spi *dws);
 extern int dw_spi_suspend_host(struct dw_spi *dws);
 extern int dw_spi_resume_host(struct dw_spi *dws);
+extern void dw_spi_xfer_done(struct dw_spi *dws);
+
+/* platform related setup */
+extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
 #endif /* DW_SPI_HEADER_H */
diff --git a/include/linux/spi/ifx_modem.h b/include/linux/spi/ifx_modem.h
new file mode 100644
index 0000000..a68f3b1
--- /dev/null
+++ b/include/linux/spi/ifx_modem.h
@@ -0,0 +1,14 @@
+#ifndef LINUX_IFX_MODEM_H
+#define LINUX_IFX_MODEM_H
+
+struct ifx_modem_platform_data {
+	unsigned short rst_out; /* modem reset out */
+	unsigned short pwr_on;  /* power on */
+	unsigned short rst_pmu; /* reset modem */
+	unsigned short tx_pwr;  /* modem power threshold */
+	unsigned short srdy;    /* SRDY */
+	unsigned short mrdy;    /* MRDY */
+	unsigned short is_6160;	/* Modem type */
+};
+
+#endif
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
new file mode 100644
index 0000000..d3e1075
--- /dev/null
+++ b/include/linux/spi/pxa2xx_spi.h
@@ -0,0 +1,152 @@
+/*
+ * 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 __linux_pxa2xx_spi_h
+#define __linux_pxa2xx_spi_h
+
+#include <linux/pxa2xx_ssp.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);
+};
+
+#ifdef CONFIG_ARCH_PXA
+
+#include <linux/clk.h>
+#include <mach/dma.h>
+
+extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
+
+#else
+/*
+ * This is the implemtation for CE4100 on x86. ARM defines them in mach/ or
+ * plat/ include path.
+ * The CE4100 does not provide DMA support. This bits are here to let the driver
+ * compile and will never be used. Maybe we get DMA support at a later point in
+ * time.
+ */
+
+#define DCSR(n)         (n)
+#define DSADR(n)        (n)
+#define DTADR(n)        (n)
+#define DCMD(n)         (n)
+#define DRCMR(n)        (n)
+
+#define DCSR_RUN	(1 << 31)	/* Run Bit */
+#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch */
+#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable */
+#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
+#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
+#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt */
+#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt */
+#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt */
+
+#define DCSR_EORIRQEN	(1 << 28)	/* End of Receive Interrupt Enable */
+#define DCSR_EORJMPEN	(1 << 27)	/* Jump to next descriptor on EOR */
+#define DCSR_EORSTOPEN	(1 << 26)	/* STOP on an EOR */
+#define DCSR_SETCMPST	(1 << 25)	/* Set Descriptor Compare Status */
+#define DCSR_CLRCMPST	(1 << 24)	/* Clear Descriptor Compare Status */
+#define DCSR_CMPST	(1 << 10)	/* The Descriptor Compare Status */
+#define DCSR_EORINTR	(1 << 9)	/* The end of Receive */
+
+#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid */
+#define DRCMR_CHLNUM	0x1f		/* mask for Channel Number */
+
+#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor */
+#define DDADR_STOP	(1 << 0)	/* Stop */
+
+#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
+#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
+#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
+#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
+#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
+#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
+#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
+#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
+#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
+#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
+#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
+#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
+#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
+#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
+
+/*
+ * Descriptor structure for PXA's DMA engine
+ * Note: this structure must always be aligned to a 16-byte boundary.
+ */
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
+} pxa_dma_prio;
+
+/*
+ * DMA registration
+ */
+
+static inline int pxa_request_dma(char *name,
+		pxa_dma_prio prio,
+		void (*irq_handler)(int, void *),
+		void *data)
+{
+	return -ENODEV;
+}
+
+static inline void pxa_free_dma(int dma_ch)
+{
+}
+
+/*
+ * The CE4100 does not have the clk framework implemented and SPI clock can
+ * not be switched on/off or the divider changed.
+ */
+static inline void clk_disable(struct clk *clk)
+{
+}
+
+static inline int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+static inline unsigned long clk_get_rate(struct clk *clk)
+{
+	return 3686400;
+}
+
+#endif
+#endif
diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h
index 51efbef..25310f1 100644
--- a/include/linux/stacktrace.h
+++ b/include/linux/stacktrace.h
@@ -2,6 +2,7 @@
 #define __LINUX_STACKTRACE_H
 
 struct task_struct;
+struct pt_regs;
 
 #ifdef CONFIG_STACKTRACE
 struct task_struct;
@@ -13,7 +14,8 @@
 };
 
 extern void save_stack_trace(struct stack_trace *trace);
-extern void save_stack_trace_bp(struct stack_trace *trace, unsigned long bp);
+extern void save_stack_trace_regs(struct stack_trace *trace,
+				  struct pt_regs *regs);
 extern void save_stack_trace_tsk(struct task_struct *tsk,
 				struct stack_trace *trace);
 
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index cacc27a..18cd068 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -127,8 +127,6 @@
 #define SYSCALL_TRACE_ENTER_EVENT(sname)				\
 	static struct syscall_metadata					\
 	__attribute__((__aligned__(4))) __syscall_meta_##sname;		\
-	static struct ftrace_event_call					\
-	__attribute__((__aligned__(4))) event_enter_##sname;		\
 	static struct ftrace_event_call __used				\
 	  __attribute__((__aligned__(4)))				\
 	  __attribute__((section("_ftrace_events")))			\
@@ -137,13 +135,12 @@
 		.class			= &event_class_syscall_enter,	\
 		.event.funcs            = &enter_syscall_print_funcs,	\
 		.data			= (void *)&__syscall_meta_##sname,\
-	}
+	};								\
+	__TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY)
 
 #define SYSCALL_TRACE_EXIT_EVENT(sname)					\
 	static struct syscall_metadata					\
 	__attribute__((__aligned__(4))) __syscall_meta_##sname;		\
-	static struct ftrace_event_call					\
-	__attribute__((__aligned__(4))) event_exit_##sname;		\
 	static struct ftrace_event_call __used				\
 	  __attribute__((__aligned__(4)))				\
 	  __attribute__((section("_ftrace_events")))			\
@@ -152,7 +149,8 @@
 		.class			= &event_class_syscall_exit,	\
 		.event.funcs		= &exit_syscall_print_funcs,	\
 		.data			= (void *)&__syscall_meta_##sname,\
-	}
+	};								\
+	__TRACE_EVENT_FLAGS(exit_##sname, TRACE_EVENT_FL_CAP_ANY)
 
 #define SYSCALL_METADATA(sname, nb)				\
 	SYSCALL_TRACE_ENTER_EVENT(sname);			\
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 38cf093..6abd913 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -24,9 +24,9 @@
 	int slack;
 
 #ifdef CONFIG_TIMER_STATS
+	int start_pid;
 	void *start_site;
 	char start_comm[16];
-	int start_pid;
 #endif
 #ifdef CONFIG_LOCKDEP
 	struct lockdep_map lockdep_map;
@@ -48,12 +48,38 @@
 #define __TIMER_LOCKDEP_MAP_INITIALIZER(_kn)
 #endif
 
+/*
+ * Note that all tvec_bases are 2 byte aligned and lower bit of
+ * base in timer_list is guaranteed to be zero. Use the LSB to
+ * indicate whether the timer is deferrable.
+ *
+ * A deferrable timer will work normally when the system is busy, but
+ * will not cause a CPU to come out of idle just to service it; instead,
+ * the timer will be serviced when the CPU eventually wakes up with a
+ * subsequent non-deferrable timer.
+ */
+#define TBASE_DEFERRABLE_FLAG		(0x1)
+
 #define TIMER_INITIALIZER(_function, _expires, _data) {		\
 		.entry = { .prev = TIMER_ENTRY_STATIC },	\
 		.function = (_function),			\
 		.expires = (_expires),				\
 		.data = (_data),				\
 		.base = &boot_tvec_bases,			\
+		.slack = -1,					\
+		__TIMER_LOCKDEP_MAP_INITIALIZER(		\
+			__FILE__ ":" __stringify(__LINE__))	\
+	}
+
+#define TBASE_MAKE_DEFERRED(ptr) ((struct tvec_base *)		\
+		  ((unsigned char *)(ptr) + TBASE_DEFERRABLE_FLAG))
+
+#define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) {\
+		.entry = { .prev = TIMER_ENTRY_STATIC },	\
+		.function = (_function),			\
+		.expires = (_expires),				\
+		.data = (_data),				\
+		.base = TBASE_MAKE_DEFERRED(&boot_tvec_bases),	\
 		__TIMER_LOCKDEP_MAP_INITIALIZER(		\
 			__FILE__ ":" __stringify(__LINE__))	\
 	}
@@ -248,11 +274,11 @@
 
 extern void add_timer(struct timer_list *timer);
 
+extern int try_to_del_timer_sync(struct timer_list *timer);
+
 #ifdef CONFIG_SMP
-  extern int try_to_del_timer_sync(struct timer_list *timer);
   extern int del_timer_sync(struct timer_list *timer);
 #else
-# define try_to_del_timer_sync(t)	del_timer(t)
 # define del_timer_sync(t)		del_timer(t)
 #endif
 
diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h
new file mode 100644
index 0000000..d24aaba
--- /dev/null
+++ b/include/linux/timerqueue.h
@@ -0,0 +1,50 @@
+#ifndef _LINUX_TIMERQUEUE_H
+#define _LINUX_TIMERQUEUE_H
+
+#include <linux/rbtree.h>
+#include <linux/ktime.h>
+
+
+struct timerqueue_node {
+	struct rb_node node;
+	ktime_t expires;
+};
+
+struct timerqueue_head {
+	struct rb_root head;
+	struct timerqueue_node *next;
+};
+
+
+extern void timerqueue_add(struct timerqueue_head *head,
+				struct timerqueue_node *node);
+extern void timerqueue_del(struct timerqueue_head *head,
+				struct timerqueue_node *node);
+extern struct timerqueue_node *timerqueue_iterate_next(
+						struct timerqueue_node *node);
+
+/**
+ * timerqueue_getnext - Returns the timer with the earlies expiration time
+ *
+ * @head: head of timerqueue
+ *
+ * Returns a pointer to the timer node that has the
+ * earliest expiration time.
+ */
+static inline
+struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head)
+{
+	return head->next;
+}
+
+static inline void timerqueue_init(struct timerqueue_node *node)
+{
+	RB_CLEAR_NODE(&node->node);
+}
+
+static inline void timerqueue_init_head(struct timerqueue_head *head)
+{
+	head->head = RB_ROOT;
+	head->next = NULL;
+}
+#endif /* _LINUX_TIMERQUEUE_H */
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index a4a90b6..d3e4f87 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -106,6 +106,7 @@
 
 #define TP_PROTO(args...)	args
 #define TP_ARGS(args...)	args
+#define TP_CONDITION(args...)	args
 
 #ifdef CONFIG_TRACEPOINTS
 
@@ -119,12 +120,14 @@
  * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
  * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
  */
-#define __DO_TRACE(tp, proto, args)					\
+#define __DO_TRACE(tp, proto, args, cond)				\
 	do {								\
 		struct tracepoint_func *it_func_ptr;			\
 		void *it_func;						\
 		void *__data;						\
 									\
+		if (!(cond))						\
+			return;						\
 		rcu_read_lock_sched_notrace();				\
 		it_func_ptr = rcu_dereference_sched((tp)->funcs);	\
 		if (it_func_ptr) {					\
@@ -142,7 +145,7 @@
  * not add unwanted padding between the beginning of the section and the
  * structure. Force alignment to the same alignment as the section start.
  */
-#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
+#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args)	\
 	extern struct tracepoint __tracepoint_##name;			\
 	static inline void trace_##name(proto)				\
 	{								\
@@ -151,7 +154,8 @@
 do_trace:								\
 			__DO_TRACE(&__tracepoint_##name,		\
 				TP_PROTO(data_proto),			\
-				TP_ARGS(data_args));			\
+				TP_ARGS(data_args),			\
+				TP_CONDITION(cond));			\
 	}								\
 	static inline int						\
 	register_trace_##name(void (*probe)(data_proto), void *data)	\
@@ -186,7 +190,7 @@
 	EXPORT_SYMBOL(__tracepoint_##name)
 
 #else /* !CONFIG_TRACEPOINTS */
-#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
+#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args)	\
 	static inline void trace_##name(proto)				\
 	{ }								\
 	static inline int						\
@@ -227,13 +231,20 @@
  * "void *__data, proto" as the callback prototype.
  */
 #define DECLARE_TRACE_NOARGS(name)					\
-		__DECLARE_TRACE(name, void, , void *__data, __data)
+		__DECLARE_TRACE(name, void, , 1, void *__data, __data)
 
 #define DECLARE_TRACE(name, proto, args)				\
-		__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),	\
+		__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1,	\
 				PARAMS(void *__data, proto),		\
 				PARAMS(__data, args))
 
+#define DECLARE_TRACE_CONDITION(name, proto, args, cond)		\
+	__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \
+			PARAMS(void *__data, proto),			\
+			PARAMS(__data, args))
+
+#define TRACE_EVENT_FLAGS(event, flag)
+
 #endif /* DECLARE_TRACE */
 
 #ifndef TRACE_EVENT
@@ -347,11 +358,21 @@
 	DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
 #define DEFINE_EVENT_PRINT(template, name, proto, args, print)	\
 	DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
+#define DEFINE_EVENT_CONDITION(template, name, proto,		\
+			       args, cond)			\
+	DECLARE_TRACE_CONDITION(name, PARAMS(proto),		\
+				PARAMS(args), PARAMS(cond))
 
 #define TRACE_EVENT(name, proto, args, struct, assign, print)	\
 	DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
 #define TRACE_EVENT_FN(name, proto, args, struct,		\
 		assign, print, reg, unreg)			\
 	DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
+#define TRACE_EVENT_CONDITION(name, proto, args, cond,		\
+			      struct, assign, print)		\
+	DECLARE_TRACE_CONDITION(name, PARAMS(proto),		\
+				PARAMS(args), PARAMS(cond))
+
+#define TRACE_EVENT_FLAGS(event, flag)
 
 #endif /* ifdef TRACE_EVENT (see note above) */
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index db2d227..c3d43eb 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -102,7 +102,7 @@
  * 	    unsigned int cmd, unsigned long arg);
  *
  * 	This routine allows the tty driver to implement
- *	device-specific ioctl's.  If the ioctl number passed in cmd
+ *	device-specific ioctls.  If the ioctl number passed in cmd
  * 	is not recognized by the driver, it should return ENOIOCTLCMD.
  *
  *	Optional
@@ -167,12 +167,12 @@
  * 
  * void (*hangup)(struct tty_struct *tty);
  *
- * 	This routine notifies the tty driver that it should hangup the
+ * 	This routine notifies the tty driver that it should hang up the
  * 	tty device.
  *
  *	Optional:
  *
- * int (*break_ctl)(struct tty_stuct *tty, int state);
+ * int (*break_ctl)(struct tty_struct *tty, int state);
  *
  * 	This optional routine requests the tty driver to turn on or
  * 	off BREAK status on the RS-232 port.  If state is -1,
@@ -235,6 +235,7 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/cdev.h>
+#include <linux/termios.h>
 
 struct tty_struct;
 struct tty_driver;
@@ -357,7 +358,7 @@
  * 	overruns, either.)
  *
  * TTY_DRIVER_DYNAMIC_DEV --- if set, the individual tty devices need
- *	to be registered with a call to tty_register_driver() when the
+ *	to be registered with a call to tty_register_device() when the
  *	device is found in the system and unregistered with a call to
  *	tty_unregister_device() so the devices will be show up
  *	properly in sysfs.  If not set, driver->num entries will be
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index 05f7fed2..d28c726 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -104,6 +104,7 @@
 #define UI_SET_FFBIT		_IOW(UINPUT_IOCTL_BASE, 107, int)
 #define UI_SET_PHYS		_IOW(UINPUT_IOCTL_BASE, 108, char*)
 #define UI_SET_SWBIT		_IOW(UINPUT_IOCTL_BASE, 109, int)
+#define UI_SET_PROPBIT		_IOW(UINPUT_IOCTL_BASE, 110, int)
 
 #define UI_BEGIN_FF_UPLOAD	_IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
 #define UI_END_FF_UPLOAD	_IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index a28eb25..bd69b65 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -20,6 +20,7 @@
 #include <linux/completion.h>	/* for struct completion */
 #include <linux/sched.h>	/* for current && schedule_timeout */
 #include <linux/mutex.h>	/* for struct mutex */
+#include <linux/pm_runtime.h>	/* for runtime PM */
 
 struct usb_device;
 struct usb_driver;
@@ -411,8 +412,6 @@
  * @quirks: quirks of the whole device
  * @urbnum: number of URBs submitted for the whole device
  * @active_duration: total time device is not suspended
- * @last_busy: time of last use
- * @autosuspend_delay: in jiffies
  * @connect_time: time device was first connected
  * @do_remote_wakeup:  remote wakeup should be enabled
  * @reset_resume: needs reset instead of resume
@@ -485,8 +484,6 @@
 	unsigned long active_duration;
 
 #ifdef CONFIG_PM
-	unsigned long last_busy;
-	int autosuspend_delay;
 	unsigned long connect_time;
 
 	unsigned do_remote_wakeup:1;
@@ -531,7 +528,7 @@
 
 static inline void usb_mark_last_busy(struct usb_device *udev)
 {
-	udev->last_busy = jiffies;
+	pm_runtime_mark_last_busy(&udev->dev);
 }
 
 #else
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
index 119194c..10ec069 100644
--- a/include/linux/usb/ch11.h
+++ b/include/linux/usb/ch11.h
@@ -28,6 +28,13 @@
 #define HUB_STOP_TT		11
 
 /*
+ * Hub class additional requests defined by USB 3.0 spec
+ * See USB 3.0 spec Table 10-6
+ */
+#define HUB_SET_DEPTH		12
+#define HUB_GET_PORT_ERR_COUNT	13
+
+/*
  * Hub Class feature numbers
  * See USB 2.0 spec Table 11-17
  */
@@ -56,6 +63,20 @@
 #define USB_PORT_FEAT_C_PORT_L1         23
 
 /*
+ * Port feature selectors added by USB 3.0 spec.
+ * See USB 3.0 spec Table 10-7
+ */
+#define USB_PORT_FEAT_LINK_STATE		5
+#define USB_PORT_FEAT_U1_TIMEOUT		23
+#define USB_PORT_FEAT_U2_TIMEOUT		24
+#define USB_PORT_FEAT_C_LINK_STATE		25
+#define USB_PORT_FEAT_C_CONFIG_ERR		26
+#define USB_PORT_FEAT_REMOTE_WAKE_MASK		27
+#define USB_PORT_FEAT_BH_PORT_RESET		28
+#define USB_PORT_FEAT_C_BH_PORT_RESET		29
+#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT	30
+
+/*
  * Hub Status and Hub Change results
  * See USB 2.0 spec Table 11-19 and Table 11-20
  */
@@ -84,6 +105,32 @@
 #define USB_PORT_STAT_SUPER_SPEED	0x8000	/* Linux-internal */
 
 /*
+ * Additions to wPortStatus bit field from USB 3.0
+ * See USB 3.0 spec Table 10-10
+ */
+#define USB_PORT_STAT_LINK_STATE	0x01e0
+#define USB_SS_PORT_STAT_POWER		0x0200
+#define USB_PORT_STAT_SPEED_5GBPS	0x0000
+/* Valid only if port is enabled */
+
+/*
+ * Definitions for PORT_LINK_STATE values
+ * (bits 5-8) in wPortStatus
+ */
+#define USB_SS_PORT_LS_U0		0x0000
+#define USB_SS_PORT_LS_U1		0x0020
+#define USB_SS_PORT_LS_U2		0x0040
+#define USB_SS_PORT_LS_U3		0x0060
+#define USB_SS_PORT_LS_SS_DISABLED	0x0080
+#define USB_SS_PORT_LS_RX_DETECT	0x00a0
+#define USB_SS_PORT_LS_SS_INACTIVE	0x00c0
+#define USB_SS_PORT_LS_POLLING		0x00e0
+#define USB_SS_PORT_LS_RECOVERY		0x0100
+#define USB_SS_PORT_LS_HOT_RESET	0x0120
+#define USB_SS_PORT_LS_COMP_MOD		0x0140
+#define USB_SS_PORT_LS_LOOPBACK		0x0160
+
+/*
  * wPortChange bit field
  * See USB 2.0 spec Table 11-22
  * Bits 0 to 4 shown, bits 5 to 15 are reserved
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index f917bbb..ab46194 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -124,6 +124,16 @@
 #define USB_DEVICE_DEBUG_MODE		6	/* (special devices only) */
 
 /*
+ * Test Mode Selectors
+ * See USB 2.0 spec Table 9-7
+ */
+#define	TEST_J		1
+#define	TEST_K		2
+#define	TEST_SE0_NAK	3
+#define	TEST_PACKET	4
+#define	TEST_FORCE_EN	5
+
+/*
  * New Feature Selectors as added by USB 3.0
  * See USB 3.0 spec Table 9-6
  */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 0b6e751..dd6ee49 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -471,6 +471,10 @@
 
 /*-------------------------------------------------------------------------*/
 
+/* class requests from USB 3.0 hub spec, table 10-5 */
+#define SetHubDepth		(0x3000 | HUB_SET_DEPTH)
+#define GetPortErrorCount	(0x8000 | HUB_GET_PORT_ERR_COUNT)
+
 /*
  * Generic bandwidth allocation constants/support
  */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
new file mode 100644
index 0000000..3675e03
--- /dev/null
+++ b/include/linux/usb/msm_hsusb.h
@@ -0,0 +1,112 @@
+/* linux/include/asm-arm/arch-msm/hsusb.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_HSUSB_H
+#define __ASM_ARCH_MSM_HSUSB_H
+
+#include <linux/types.h>
+#include <linux/usb/otg.h>
+
+/**
+ * Supported USB modes
+ *
+ * USB_PERIPHERAL       Only peripheral mode is supported.
+ * USB_HOST             Only host mode is supported.
+ * USB_OTG              OTG mode is supported.
+ *
+ */
+enum usb_mode_type {
+	USB_NONE = 0,
+	USB_PERIPHERAL,
+	USB_HOST,
+	USB_OTG,
+};
+
+/**
+ * OTG control
+ *
+ * OTG_NO_CONTROL	Id/VBUS notifications not required. Useful in host
+ *                      only configuration.
+ * OTG_PHY_CONTROL	Id/VBUS notifications comes form USB PHY.
+ * OTG_PMIC_CONTROL	Id/VBUS notifications comes from PMIC hardware.
+ * OTG_USER_CONTROL	Id/VBUS notifcations comes from User via sysfs.
+ *
+ */
+enum otg_control_type {
+	OTG_NO_CONTROL = 0,
+	OTG_PHY_CONTROL,
+	OTG_PMIC_CONTROL,
+	OTG_USER_CONTROL,
+};
+
+/**
+ * struct msm_otg_platform_data - platform device data
+ *              for msm72k_otg driver.
+ * @phy_init_seq: PHY configuration sequence. val, reg pairs
+ *              terminated by -1.
+ * @vbus_power: VBUS power on/off routine.
+ * @power_budget: VBUS power budget in mA (0 will be treated as 500mA).
+ * @mode: Supported mode (OTG/peripheral/host).
+ * @otg_control: OTG switch controlled by user/Id pin
+ * @default_mode: Default operational mode. Applicable only if
+ *              OTG switch is controller by user.
+ *
+ */
+struct msm_otg_platform_data {
+	int *phy_init_seq;
+	void (*vbus_power)(bool on);
+	unsigned power_budget;
+	enum usb_mode_type mode;
+	enum otg_control_type otg_control;
+	enum usb_mode_type default_mode;
+	void (*setup_gpio)(enum usb_otg_state state);
+};
+
+/**
+ * struct msm_otg: OTG driver data. Shared by HCD and DCD.
+ * @otg: USB OTG Transceiver structure.
+ * @pdata: otg device platform data.
+ * @irq: IRQ number assigned for HSUSB controller.
+ * @clk: clock struct of usb_hs_clk.
+ * @pclk: clock struct of usb_hs_pclk.
+ * @phy_reset_clk: clock struct of usb_phy_clk.
+ * @core_clk: clock struct of usb_hs_core_clk.
+ * @regs: ioremapped register base address.
+ * @inputs: OTG state machine inputs(Id, SessValid etc).
+ * @sm_work: OTG state machine work.
+ * @in_lpm: indicates low power mode (LPM) state.
+ * @async_int: Async interrupt arrived.
+ *
+ */
+struct msm_otg {
+	struct otg_transceiver otg;
+	struct msm_otg_platform_data *pdata;
+	int irq;
+	struct clk *clk;
+	struct clk *pclk;
+	struct clk *phy_reset_clk;
+	struct clk *core_clk;
+	void __iomem *regs;
+#define ID		0
+#define B_SESS_VLD	1
+	unsigned long inputs;
+	struct work_struct sm_work;
+	atomic_t in_lpm;
+	int async_int;
+};
+
+#endif
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
new file mode 100644
index 0000000..b92e173
--- /dev/null
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LINUX_USB_GADGET_MSM72K_UDC_H__
+#define __LINUX_USB_GADGET_MSM72K_UDC_H__
+
+#ifdef CONFIG_ARCH_MSM7X00A
+#define USB_SBUSCFG          (MSM_USB_BASE + 0x0090)
+#else
+#define USB_AHBBURST         (MSM_USB_BASE + 0x0090)
+#define USB_AHBMODE          (MSM_USB_BASE + 0x0098)
+#endif
+#define USB_CAPLENGTH        (MSM_USB_BASE + 0x0100) /* 8 bit */
+
+#define USB_USBCMD           (MSM_USB_BASE + 0x0140)
+#define USB_PORTSC           (MSM_USB_BASE + 0x0184)
+#define USB_OTGSC            (MSM_USB_BASE + 0x01A4)
+#define USB_USBMODE          (MSM_USB_BASE + 0x01A8)
+
+#define USBCMD_RESET   2
+#define USB_USBINTR          (MSM_USB_BASE + 0x0148)
+
+#define PORTSC_PHCD            (1 << 23) /* phy suspend mode */
+#define PORTSC_PTS_MASK         (3 << 30)
+#define PORTSC_PTS_ULPI         (3 << 30)
+
+#define USB_ULPI_VIEWPORT    (MSM_USB_BASE + 0x0170)
+#define ULPI_RUN              (1 << 30)
+#define ULPI_WRITE            (1 << 29)
+#define ULPI_READ             (0 << 29)
+#define ULPI_ADDR(n)          (((n) & 255) << 16)
+#define ULPI_DATA(n)          ((n) & 255)
+#define ULPI_DATA_READ(n)     (((n) >> 8) & 255)
+
+#define ASYNC_INTR_CTRL         (1 << 29) /* Enable async interrupt */
+#define ULPI_STP_CTRL           (1 << 30) /* Block communication with PHY */
+
+/* OTG definitions */
+#define OTGSC_INTSTS_MASK	(0x7f << 16)
+#define OTGSC_ID		(1 << 8)
+#define OTGSC_BSV		(1 << 11)
+#define OTGSC_IDIS		(1 << 16)
+#define OTGSC_BSVIS		(1 << 19)
+#define OTGSC_IDIE		(1 << 24)
+#define OTGSC_BSVIE		(1 << 27)
+
+#endif /* __LINUX_USB_GADGET_MSM72K_UDC_H__ */
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index 2387f9f..eb50525 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -3,7 +3,7 @@
  * Inventra (Multidrop) Highspeed Dual-Role Controllers:  (M)HDRC.
  *
  * Board initialization should put one of these into dev->platform_data,
- * probably on some platform_device named "musb_hdrc".  It encapsulates
+ * probably on some platform_device named "musb-hdrc".  It encapsulates
  * key configuration differences between boards.
  */
 
@@ -120,14 +120,14 @@
 	/* Power the device on or off */
 	int		(*set_power)(int state);
 
-	/* Turn device clock on or off */
-	int		(*set_clock)(struct clk *clock, int is_on);
-
 	/* MUSB configuration-specific details */
 	struct musb_hdrc_config	*config;
 
 	/* Architecture specific board data	*/
 	void		*board_data;
+
+	/* Platform specific struct musb_ops pointer */
+	const void	*platform_ops;
 };
 
 
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 0a5b371..a1a1e7a 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -116,7 +116,7 @@
 /* for board-specific init logic */
 extern int otg_set_transceiver(struct otg_transceiver *);
 
-#if defined(CONFIG_NOP_USB_XCEIV) || defined(CONFIG_NOP_USB_XCEIV_MODULE)
+#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
 /* sometimes transceivers are accessed only through e.g. ULPI */
 extern void usb_nop_xceiv_register(void);
 extern void usb_nop_xceiv_unregister(void);
diff --git a/include/linux/via-core.h b/include/linux/via-core.h
index 38bffd8..9c21cdf 100644
--- a/include/linux/via-core.h
+++ b/include/linux/via-core.h
@@ -60,6 +60,21 @@
 };
 
 /*
+ * Allow subdevs to register suspend/resume hooks.
+ */
+#ifdef CONFIG_PM
+struct viafb_pm_hooks {
+	struct list_head list;
+	int (*suspend)(void *private);
+	int (*resume)(void *private);
+	void *private;
+};
+
+void viafb_pm_register(struct viafb_pm_hooks *hooks);
+void viafb_pm_unregister(struct viafb_pm_hooks *hooks);
+#endif /* CONFIG_PM */
+
+/*
  * This is the global viafb "device" containing stuff needed by
  * all subdevs.
  */
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
deleted file mode 100644
index b19eab1..0000000
--- a/include/linux/videodev.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- *	Video for Linux version 1 - OBSOLETE
- *
- *	Header file for v4l1 drivers and applications, for
- *	Linux kernels 2.2.x or 2.4.x.
- *
- *	Provides header for legacy drivers and applications
- *
- *	See http://linuxtv.org for more info
- *
- */
-#ifndef __LINUX_VIDEODEV_H
-#define __LINUX_VIDEODEV_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <linux/videodev2.h>
-
-#if defined(__MIN_V4L1) && defined (__KERNEL__)
-
-/*
- * Used by those V4L2 core functions that need a minimum V4L1 support,
- * in order to allow V4L1 Compatibilty code compilation.
- */
-
-struct video_mbuf
-{
-	int	size;		/* Total memory to map */
-	int	frames;		/* Frames */
-	int	offsets[VIDEO_MAX_FRAME];
-};
-
-#define VIDIOCGMBUF		_IOR('v',20, struct video_mbuf)		/* Memory map buffer info */
-
-#else
-#if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__)
-
-#define VID_TYPE_CAPTURE	1	/* Can capture */
-#define VID_TYPE_TUNER		2	/* Can tune */
-#define VID_TYPE_TELETEXT	4	/* Does teletext */
-#define VID_TYPE_OVERLAY	8	/* Overlay onto frame buffer */
-#define VID_TYPE_CHROMAKEY	16	/* Overlay by chromakey */
-#define VID_TYPE_CLIPPING	32	/* Can clip */
-#define VID_TYPE_FRAMERAM	64	/* Uses the frame buffer memory */
-#define VID_TYPE_SCALES		128	/* Scalable */
-#define VID_TYPE_MONOCHROME	256	/* Monochrome only */
-#define VID_TYPE_SUBCAPTURE	512	/* Can capture subareas of the image */
-#define VID_TYPE_MPEG_DECODER	1024	/* Can decode MPEG streams */
-#define VID_TYPE_MPEG_ENCODER	2048	/* Can encode MPEG streams */
-#define VID_TYPE_MJPEG_DECODER	4096	/* Can decode MJPEG streams */
-#define VID_TYPE_MJPEG_ENCODER	8192	/* Can encode MJPEG streams */
-
-struct video_capability
-{
-	char name[32];
-	int type;
-	int channels;	/* Num channels */
-	int audios;	/* Num audio devices */
-	int maxwidth;	/* Supported width */
-	int maxheight;	/* And height */
-	int minwidth;	/* Supported width */
-	int minheight;	/* And height */
-};
-
-
-struct video_channel
-{
-	int channel;
-	char name[32];
-	int tuners;
-	__u32  flags;
-#define VIDEO_VC_TUNER		1	/* Channel has a tuner */
-#define VIDEO_VC_AUDIO		2	/* Channel has audio */
-	__u16  type;
-#define VIDEO_TYPE_TV		1
-#define VIDEO_TYPE_CAMERA	2
-	__u16 norm;			/* Norm set by channel */
-};
-
-struct video_tuner
-{
-	int tuner;
-	char name[32];
-	unsigned long rangelow, rangehigh;	/* Tuner range */
-	__u32 flags;
-#define VIDEO_TUNER_PAL		1
-#define VIDEO_TUNER_NTSC	2
-#define VIDEO_TUNER_SECAM	4
-#define VIDEO_TUNER_LOW		8	/* Uses KHz not MHz */
-#define VIDEO_TUNER_NORM	16	/* Tuner can set norm */
-#define VIDEO_TUNER_STEREO_ON	128	/* Tuner is seeing stereo */
-#define VIDEO_TUNER_RDS_ON      256     /* Tuner is seeing an RDS datastream */
-#define VIDEO_TUNER_MBS_ON      512     /* Tuner is seeing an MBS datastream */
-	__u16 mode;			/* PAL/NTSC/SECAM/OTHER */
-#define VIDEO_MODE_PAL		0
-#define VIDEO_MODE_NTSC		1
-#define VIDEO_MODE_SECAM	2
-#define VIDEO_MODE_AUTO		3
-	__u16 signal;			/* Signal strength 16bit scale */
-};
-
-struct video_picture
-{
-	__u16	brightness;
-	__u16	hue;
-	__u16	colour;
-	__u16	contrast;
-	__u16	whiteness;	/* Black and white only */
-	__u16	depth;		/* Capture depth */
-	__u16   palette;	/* Palette in use */
-#define VIDEO_PALETTE_GREY	1	/* Linear greyscale */
-#define VIDEO_PALETTE_HI240	2	/* High 240 cube (BT848) */
-#define VIDEO_PALETTE_RGB565	3	/* 565 16 bit RGB */
-#define VIDEO_PALETTE_RGB24	4	/* 24bit RGB */
-#define VIDEO_PALETTE_RGB32	5	/* 32bit RGB */
-#define VIDEO_PALETTE_RGB555	6	/* 555 15bit RGB */
-#define VIDEO_PALETTE_YUV422	7	/* YUV422 capture */
-#define VIDEO_PALETTE_YUYV	8
-#define VIDEO_PALETTE_UYVY	9	/* The great thing about standards is ... */
-#define VIDEO_PALETTE_YUV420	10
-#define VIDEO_PALETTE_YUV411	11	/* YUV411 capture */
-#define VIDEO_PALETTE_RAW	12	/* RAW capture (BT848) */
-#define VIDEO_PALETTE_YUV422P	13	/* YUV 4:2:2 Planar */
-#define VIDEO_PALETTE_YUV411P	14	/* YUV 4:1:1 Planar */
-#define VIDEO_PALETTE_YUV420P	15	/* YUV 4:2:0 Planar */
-#define VIDEO_PALETTE_YUV410P	16	/* YUV 4:1:0 Planar */
-#define VIDEO_PALETTE_PLANAR	13	/* start of planar entries */
-#define VIDEO_PALETTE_COMPONENT 7	/* start of component entries */
-};
-
-struct video_audio
-{
-	int	audio;		/* Audio channel */
-	__u16	volume;		/* If settable */
-	__u16	bass, treble;
-	__u32	flags;
-#define VIDEO_AUDIO_MUTE	1
-#define VIDEO_AUDIO_MUTABLE	2
-#define VIDEO_AUDIO_VOLUME	4
-#define VIDEO_AUDIO_BASS	8
-#define VIDEO_AUDIO_TREBLE	16
-#define VIDEO_AUDIO_BALANCE	32
-	char    name[16];
-#define VIDEO_SOUND_MONO	1
-#define VIDEO_SOUND_STEREO	2
-#define VIDEO_SOUND_LANG1	4
-#define VIDEO_SOUND_LANG2	8
-	__u16   mode;
-	__u16	balance;	/* Stereo balance */
-	__u16	step;		/* Step actual volume uses */
-};
-
-struct video_clip
-{
-	__s32	x,y;
-	__s32	width, height;
-	struct	video_clip *next;	/* For user use/driver use only */
-};
-
-struct video_window
-{
-	__u32	x,y;			/* Position of window */
-	__u32	width,height;		/* Its size */
-	__u32	chromakey;
-	__u32	flags;
-	struct	video_clip __user *clips;	/* Set only */
-	int	clipcount;
-#define VIDEO_WINDOW_INTERLACE	1
-#define VIDEO_WINDOW_CHROMAKEY	16	/* Overlay by chromakey */
-#define VIDEO_CLIP_BITMAP	-1
-/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
-#define VIDEO_CLIPMAP_SIZE	(128 * 625)
-};
-
-struct video_capture
-{
-	__u32 	x,y;			/* Offsets into image */
-	__u32	width, height;		/* Area to capture */
-	__u16	decimation;		/* Decimation divider */
-	__u16	flags;			/* Flags for capture */
-#define VIDEO_CAPTURE_ODD		0	/* Temporal */
-#define VIDEO_CAPTURE_EVEN		1
-};
-
-struct video_buffer
-{
-	void	*base;
-	int	height,width;
-	int	depth;
-	int	bytesperline;
-};
-
-struct video_mmap
-{
-	unsigned	int frame;		/* Frame (0 - n) for double buffer */
-	int		height,width;
-	unsigned	int format;		/* should be VIDEO_PALETTE_* */
-};
-
-struct video_key
-{
-	__u8	key[8];
-	__u32	flags;
-};
-
-struct video_mbuf
-{
-	int	size;		/* Total memory to map */
-	int	frames;		/* Frames */
-	int	offsets[VIDEO_MAX_FRAME];
-};
-
-#define 	VIDEO_NO_UNIT	(-1)
-
-struct video_unit
-{
-	int 	video;		/* Video minor */
-	int	vbi;		/* VBI minor */
-	int	radio;		/* Radio minor */
-	int	audio;		/* Audio minor */
-	int	teletext;	/* Teletext minor */
-};
-
-struct vbi_format {
-	__u32	sampling_rate;	/* in Hz */
-	__u32	samples_per_line;
-	__u32	sample_format;	/* VIDEO_PALETTE_RAW only (1 byte) */
-	__s32	start[2];	/* starting line for each frame */
-	__u32	count[2];	/* count of lines for each frame */
-	__u32	flags;
-#define	VBI_UNSYNC	1	/* can distingues between top/bottom field */
-#define	VBI_INTERLACED	2	/* lines are interlaced */
-};
-
-/* video_info is biased towards hardware mpeg encode/decode */
-/* but it could apply generically to any hardware compressor/decompressor */
-struct video_info
-{
-	__u32	frame_count;	/* frames output since decode/encode began */
-	__u32	h_size;		/* current unscaled horizontal size */
-	__u32	v_size;		/* current unscaled veritcal size */
-	__u32	smpte_timecode;	/* current SMPTE timecode (for current GOP) */
-	__u32	picture_type;	/* current picture type */
-	__u32	temporal_reference;	/* current temporal reference */
-	__u8	user_data[256];	/* user data last found in compressed stream */
-	/* user_data[0] contains user data flags, user_data[1] has count */
-};
-
-/* generic structure for setting playback modes */
-struct video_play_mode
-{
-	int	mode;
-	int	p1;
-	int	p2;
-};
-
-/* for loading microcode / fpga programming */
-struct video_code
-{
-	char	loadwhat[16];	/* name or tag of file being passed */
-	int	datasize;
-	__u8	*data;
-};
-
-#define VIDIOCGCAP		_IOR('v',1,struct video_capability)	/* Get capabilities */
-#define VIDIOCGCHAN		_IOWR('v',2,struct video_channel)	/* Get channel info (sources) */
-#define VIDIOCSCHAN		_IOW('v',3,struct video_channel)	/* Set channel 	*/
-#define VIDIOCGTUNER		_IOWR('v',4,struct video_tuner)		/* Get tuner abilities */
-#define VIDIOCSTUNER		_IOW('v',5,struct video_tuner)		/* Tune the tuner for the current channel */
-#define VIDIOCGPICT		_IOR('v',6,struct video_picture)	/* Get picture properties */
-#define VIDIOCSPICT		_IOW('v',7,struct video_picture)	/* Set picture properties */
-#define VIDIOCCAPTURE		_IOW('v',8,int)				/* Start, end capture */
-#define VIDIOCGWIN		_IOR('v',9, struct video_window)	/* Get the video overlay window */
-#define VIDIOCSWIN		_IOW('v',10, struct video_window)	/* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
-#define VIDIOCGFBUF		_IOR('v',11, struct video_buffer)	/* Get frame buffer */
-#define VIDIOCSFBUF		_IOW('v',12, struct video_buffer)	/* Set frame buffer - root only */
-#define VIDIOCKEY		_IOR('v',13, struct video_key)		/* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
-#define VIDIOCGFREQ		_IOR('v',14, unsigned long)		/* Set tuner */
-#define VIDIOCSFREQ		_IOW('v',15, unsigned long)		/* Set tuner */
-#define VIDIOCGAUDIO		_IOR('v',16, struct video_audio)	/* Get audio info */
-#define VIDIOCSAUDIO		_IOW('v',17, struct video_audio)	/* Audio source, mute etc */
-#define VIDIOCSYNC		_IOW('v',18, int)			/* Sync with mmap grabbing */
-#define VIDIOCMCAPTURE		_IOW('v',19, struct video_mmap)		/* Grab frames */
-#define VIDIOCGMBUF		_IOR('v',20, struct video_mbuf)		/* Memory map buffer info */
-#define VIDIOCGUNIT		_IOR('v',21, struct video_unit)		/* Get attached units */
-#define VIDIOCGCAPTURE		_IOR('v',22, struct video_capture)	/* Get subcapture */
-#define VIDIOCSCAPTURE		_IOW('v',23, struct video_capture)	/* Set subcapture */
-#define VIDIOCSPLAYMODE		_IOW('v',24, struct video_play_mode)	/* Set output video mode/feature */
-#define VIDIOCSWRITEMODE	_IOW('v',25, int)			/* Set write mode */
-#define VIDIOCGPLAYINFO		_IOR('v',26, struct video_info)		/* Get current playback info from hardware */
-#define VIDIOCSMICROCODE	_IOW('v',27, struct video_code)		/* Load microcode into hardware */
-#define	VIDIOCGVBIFMT		_IOR('v',28, struct vbi_format)		/* Get VBI information */
-#define	VIDIOCSVBIFMT		_IOW('v',29, struct vbi_format)		/* Set VBI information */
-
-
-#define BASE_VIDIOCPRIVATE	192		/* 192-255 are private */
-
-/* VIDIOCSWRITEMODE */
-#define VID_WRITE_MPEG_AUD		0
-#define VID_WRITE_MPEG_VID		1
-#define VID_WRITE_OSD			2
-#define VID_WRITE_TTX			3
-#define VID_WRITE_CC			4
-#define VID_WRITE_MJPEG			5
-
-/* VIDIOCSPLAYMODE */
-#define VID_PLAY_VID_OUT_MODE		0
-	/* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
-#define VID_PLAY_GENLOCK		1
-	/* p1: 0 = OFF, 1 = ON */
-	/* p2: GENLOCK FINE DELAY value */
-#define VID_PLAY_NORMAL			2
-#define VID_PLAY_PAUSE			3
-#define VID_PLAY_SINGLE_FRAME		4
-#define VID_PLAY_FAST_FORWARD		5
-#define VID_PLAY_SLOW_MOTION		6
-#define VID_PLAY_IMMEDIATE_NORMAL	7
-#define VID_PLAY_SWITCH_CHANNELS	8
-#define VID_PLAY_FREEZE_FRAME		9
-#define VID_PLAY_STILL_MODE		10
-#define VID_PLAY_MASTER_MODE		11
-	/* p1: see below */
-#define		VID_PLAY_MASTER_NONE	1
-#define		VID_PLAY_MASTER_VIDEO	2
-#define		VID_PLAY_MASTER_AUDIO	3
-#define VID_PLAY_ACTIVE_SCANLINES	12
-	/* p1 = first active; p2 = last active */
-#define VID_PLAY_RESET			13
-#define VID_PLAY_END_MARK		14
-
-#endif /* CONFIG_VIDEO_V4L1_COMPAT */
-#endif /* __MIN_V4L1 */
-
-#endif /* __LINUX_VIDEODEV_H */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 0c0771f..1ac1158 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -127,12 +127,20 @@
 	.timer = TIMER_INITIALIZER(NULL, 0, 0),			\
 	}
 
+#define __DEFERRED_WORK_INITIALIZER(n, f) {			\
+	.work = __WORK_INITIALIZER((n).work, (f)),		\
+	.timer = TIMER_DEFERRED_INITIALIZER(NULL, 0, 0),	\
+	}
+
 #define DECLARE_WORK(n, f)					\
 	struct work_struct n = __WORK_INITIALIZER(n, f)
 
 #define DECLARE_DELAYED_WORK(n, f)				\
 	struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)
 
+#define DECLARE_DEFERRED_WORK(n, f)				\
+	struct delayed_work n = __DEFERRED_WORK_INITIALIZER(n, f)
+
 /*
  * initialize a work item's function pointer
  */
@@ -401,7 +409,7 @@
 }
 
 /* Obsolete. use cancel_delayed_work_sync() */
-static inline
+static inline __deprecated
 void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
 					struct delayed_work *work)
 {
@@ -409,7 +417,7 @@
 }
 
 /* Obsolete. use cancel_delayed_work_sync() */
-static inline
+static inline __deprecated
 void cancel_rearming_delayed_work(struct delayed_work *work)
 {
 	cancel_delayed_work_sync(work);
diff --git a/include/media/bt819.h b/include/media/bt819.h
index 38f666b..8025f4b 100644
--- a/include/media/bt819.h
+++ b/include/media/bt819.h
@@ -26,7 +26,10 @@
 /* v4l2_device notifications. */
 
 /* Needed to reset the FIFO buffer when changing the input
-   or the video standard. */
+   or the video standard.
+
+   Note: these ioctls that internal to the kernel and are never called
+   from userspace. */
 #define BT819_FIFO_RESET_LOW 	_IO('b', 0)
 #define BT819_FIFO_RESET_HIGH 	_IO('b', 1)
 
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
index 8d08ebf..9635eeb 100644
--- a/include/media/cx2341x.h
+++ b/include/media/cx2341x.h
@@ -95,7 +95,7 @@
 		const struct cx2341x_mpeg_params *new);
 int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
 		struct v4l2_queryctrl *qctrl);
-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);
 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
 		struct v4l2_ext_controls *ctrls, unsigned int cmd);
 void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p);
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
deleted file mode 100644
index 528050e..0000000
--- a/include/media/ir-common.h
+++ /dev/null
@@ -1,107 +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
- */
-
-#ifndef _IR_COMMON
-#define _IR_COMMON
-
-#include <linux/input.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <media/ir-core.h>
-
-#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)
-
-struct ir_input_state {
-	/* configuration */
-	u64      ir_type;
-
-	/* key info */
-	u32                ir_key;      /* ir scancode */
-	u32                keycode;     /* linux key code */
-	int                keypressed;  /* current state */
-};
-
-/* this was saa7134_ir and bttv_ir, moved here for
- * rc5 decoding. */
-struct card_ir {
-	struct input_dev        *dev;
-	struct ir_input_state   ir;
-	char                    name[32];
-	char                    phys[32];
-	int			users;
-
-	u32			running:1;
-	struct ir_dev_props	props;
-
-	/* 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_key_timeout;
-	int			rc5_remote_gap;
-	struct work_struct      work;
-	struct timer_list       timer;
-
-	/* RC5 gpio */
-	u32 rc5_gpio;
-	struct timer_list timer_end;	/* timer_end for code completion */
-	struct timer_list timer_keyup;	/* timer_end for key release */
-	u32 last_rc5;			/* last good rc5 code */
-	u32 last_bit;			/* last raw bit seen */
-	u32 code;			/* raw code under construction */
-	struct timeval base_time;	/* time of last seen code */
-	int active;			/* building raw code */
-
-	/* NEC decoding */
-	u32			nec_gpio;
-	struct tasklet_struct   tlet;
-
-	/* IR core raw decoding */
-	u32			raw_decode;
-};
-
-/* Routines from ir-functions.c */
-
-int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
-		   const u64 ir_type);
-void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir);
-void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
-		      u32 ir_key);
-u32  ir_extract_bits(u32 data, u32 mask);
-int  ir_dump_samples(u32 *samples, int count);
-int  ir_decode_biphase(u32 *samples, int count, int low, int high);
-int  ir_decode_pulsedistance(u32 *samples, int count, int low, int high);
-u32  ir_rc5_decode(unsigned int code);
-
-void ir_rc5_timer_end(unsigned long data);
-void ir_rc5_timer_keyup(unsigned long data);
-
-#endif
diff --git a/include/media/ir-core.h b/include/media/ir-core.h
deleted file mode 100644
index 6dc37fa..0000000
--- a/include/media/ir-core.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Remote Controller core header
- *
- * 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.
- */
-
-#ifndef _IR_CORE
-#define _IR_CORE
-
-#include <linux/spinlock.h>
-#include <linux/kfifo.h>
-#include <linux/time.h>
-#include <linux/timer.h>
-#include <media/rc-map.h>
-
-extern int ir_core_debug;
-#define IR_dprintk(level, fmt, arg...)	if (ir_core_debug >= level) \
-	printk(KERN_DEBUG "%s: " fmt , __func__, ## arg)
-
-enum rc_driver_type {
-	RC_DRIVER_SCANCODE = 0,	/* Driver or hardware generates a scancode */
-	RC_DRIVER_IR_RAW,	/* Needs a Infra-Red pulse/space decoder */
-};
-
-/**
- * struct ir_dev_props - Allow caller drivers to set special properties
- * @driver_type: specifies if the driver or hardware have already a decoder,
- *	or if it needs to use the IR raw event decoders to produce a scancode
- * @allowed_protos: bitmask with the supported IR_TYPE_* protocols
- * @scanmask: some hardware decoders are not capable of providing the full
- *	scancode to the application. As this is a hardware limit, we can't do
- *	anything with it. Yet, as the same keycode table can be used with other
- *	devices, a mask is provided to allow its usage. Drivers should generally
- *	leave this field in blank
- * @timeout: optional time after which device stops sending data
- * @min_timeout: minimum timeout supported by device
- * @max_timeout: maximum timeout supported by device
- * @rx_resolution : resolution (in ns) of input sampler
- * @tx_resolution: resolution (in ns) of output sampler
- * @priv: driver-specific data, to be used on the callbacks
- * @change_protocol: allow changing the protocol used on hardware decoders
- * @open: callback to allow drivers to enable polling/irq when IR input device
- *	is opened.
- * @close: callback to allow drivers to disable polling/irq when IR input device
- *	is opened.
- * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs)
- * @s_tx_carrier: set transmit carrier frequency
- * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%)
- * @s_rx_carrier: inform driver about carrier it is expected to handle
- * @tx_ir: transmit IR
- * @s_idle: optional: enable/disable hardware idle mode, upon which,
-	device doesn't interrupt host until it sees IR pulses
- * @s_learning_mode: enable wide band receiver used for learning
- * @s_carrier_report: enable carrier reports
- */
-struct ir_dev_props {
-	enum rc_driver_type	driver_type;
-	unsigned long		allowed_protos;
-	u32			scanmask;
-
-	u32			timeout;
-	u32			min_timeout;
-	u32			max_timeout;
-
-	u32			rx_resolution;
-	u32			tx_resolution;
-
-	void			*priv;
-	int			(*change_protocol)(void *priv, u64 ir_type);
-	int			(*open)(void *priv);
-	void			(*close)(void *priv);
-	int			(*s_tx_mask)(void *priv, u32 mask);
-	int			(*s_tx_carrier)(void *priv, u32 carrier);
-	int			(*s_tx_duty_cycle)(void *priv, u32 duty_cycle);
-	int			(*s_rx_carrier_range)(void *priv, u32 min, u32 max);
-	int			(*tx_ir)(void *priv, int *txbuf, u32 n);
-	void			(*s_idle)(void *priv, bool enable);
-	int			(*s_learning_mode)(void *priv, int enable);
-	int			(*s_carrier_report) (void *priv, int enable);
-};
-
-struct ir_input_dev {
-	struct device			dev;		/* device */
-	char				*driver_name;	/* Name of the driver module */
-	struct ir_scancode_table	rc_tab;		/* scan/key table */
-	unsigned long			devno;		/* device number */
-	struct ir_dev_props		*props;		/* Device properties */
-	struct ir_raw_event_ctrl	*raw;		/* for raw pulse/space events */
-	struct input_dev		*input_dev;	/* the input device associated with this device */
-	bool				idle;
-
-	/* key info - needed by IR keycode handlers */
-	spinlock_t			keylock;	/* protects the below members */
-	bool				keypressed;	/* current state */
-	unsigned long			keyup_jiffies;	/* when should the current keypress be released? */
-	struct timer_list		timer_keyup;	/* timer for releasing a keypress */
-	u32				last_keycode;	/* keycode of last command */
-	u32				last_scancode;	/* scancode of last command */
-	u8				last_toggle;	/* toggle of last command */
-};
-
-enum raw_event_type {
-	IR_SPACE        = (1 << 0),
-	IR_PULSE        = (1 << 1),
-	IR_START_EVENT  = (1 << 2),
-	IR_STOP_EVENT   = (1 << 3),
-};
-
-#define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr)
-
-/* From ir-keytable.c */
-int __ir_input_register(struct input_dev *dev,
-		      const struct ir_scancode_table *ir_codes,
-		      struct ir_dev_props *props,
-		      const char *driver_name);
-
-static inline int ir_input_register(struct input_dev *dev,
-		      const char *map_name,
-		      struct ir_dev_props *props,
-		      const char *driver_name) {
-	struct ir_scancode_table *ir_codes;
-	struct ir_input_dev *ir_dev;
-	int rc;
-
-	if (!map_name)
-		return -EINVAL;
-
-	ir_codes = get_rc_map(map_name);
-	if (!ir_codes) {
-		ir_codes = get_rc_map(RC_MAP_EMPTY);
-
-		if (!ir_codes)
-			return -EINVAL;
-	}
-
-	rc = __ir_input_register(dev, ir_codes, props, driver_name);
-	if (rc < 0)
-		return -EINVAL;
-
-	ir_dev = input_get_drvdata(dev);
-
-	if (!rc && ir_dev->props && ir_dev->props->change_protocol)
-		rc = ir_dev->props->change_protocol(ir_dev->props->priv,
-						    ir_codes->ir_type);
-
-	return rc;
-}
-
-void ir_input_unregister(struct input_dev *input_dev);
-
-void ir_repeat(struct input_dev *dev);
-void ir_keydown(struct input_dev *dev, int scancode, u8 toggle);
-void ir_keyup(struct ir_input_dev *ir);
-u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode);
-
-/* From ir-raw-event.c */
-
-struct ir_raw_event {
-	union {
-		u32             duration;
-
-		struct {
-			u32     carrier;
-			u8      duty_cycle;
-		};
-	};
-
-	unsigned                pulse:1;
-	unsigned                reset:1;
-	unsigned                timeout:1;
-	unsigned                carrier_report:1;
-};
-
-#define DEFINE_IR_RAW_EVENT(event) \
-	struct ir_raw_event event = { \
-		{ .duration = 0 } , \
-		.pulse = 0, \
-		.reset = 0, \
-		.timeout = 0, \
-		.carrier_report = 0 }
-
-static inline void init_ir_raw_event(struct ir_raw_event *ev)
-{
-	memset(ev, 0, sizeof(*ev));
-}
-
-#define IR_MAX_DURATION         0xFFFFFFFF      /* a bit more than 4 seconds */
-
-void ir_raw_event_handle(struct input_dev *input_dev);
-int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev);
-int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type);
-int ir_raw_event_store_with_filter(struct input_dev *input_dev,
-				struct ir_raw_event *ev);
-void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle);
-
-static inline void ir_raw_event_reset(struct input_dev *input_dev)
-{
-	DEFINE_IR_RAW_EVENT(ev);
-	ev.reset = true;
-
-	ir_raw_event_store(input_dev, &ev);
-	ir_raw_event_handle(input_dev);
-}
-
-#endif /* _IR_CORE */
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h
index 557c676..768aa77 100644
--- a/include/media/ir-kbd-i2c.h
+++ b/include/media/ir-kbd-i2c.h
@@ -1,7 +1,7 @@
 #ifndef _IR_I2C
 #define _IR_I2C
 
-#include <media/ir-common.h>
+#include <media/rc-core.h>
 
 #define DEFAULT_POLLING_INTERVAL	100	/* ms */
 
@@ -9,11 +9,9 @@
 
 struct IR_i2c {
 	char		       *ir_codes;
-
 	struct i2c_client      *c;
-	struct input_dev       *input;
-	struct ir_input_state  ir;
-	u64                    ir_type;
+	struct rc_dev          *rc;
+
 	/* Used to avoid fast repeating */
 	unsigned char          old;
 
@@ -39,13 +37,16 @@
 struct IR_i2c_init_data {
 	char			*ir_codes;
 	const char		*name;
-	u64			type; /* IR_TYPE_RC5, etc */
+	u64			type; /* RC_TYPE_RC5, etc */
 	u32			polling_interval; /* 0 means DEFAULT_POLLING_INTERVAL */
+
 	/*
 	 * Specify either a function pointer or a value indicating one of
 	 * ir_kbd_i2c's internal get_key functions
 	 */
 	int                    (*get_key)(struct IR_i2c*, u32*, u32*);
 	enum ir_kbd_get_key_fn internal_get_key_func;
+
+	struct rc_dev		*rc_dev;
 };
 #endif
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 54780a5..630e702 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -217,9 +217,9 @@
 int lirc_dev_fop_close(struct inode *inode, struct file *file);
 unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
 long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-ssize_t lirc_dev_fop_read(struct file *file, char *buffer, size_t length,
+ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length,
 			  loff_t *ppos);
-ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, size_t length,
-			   loff_t *ppos);
+ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
+			   size_t length, loff_t *ppos);
 
 #endif
diff --git a/include/media/ovcamchip.h b/include/media/ovcamchip.h
deleted file mode 100644
index 05b9569..0000000
--- a/include/media/ovcamchip.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* OmniVision* camera chip driver API
- *
- * Copyright (c) 1999-2004 Mark McClelland
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
- *
- * * OmniVision is a trademark of OmniVision Technologies, Inc. This driver
- * is not sponsored or developed by them.
- */
-
-#ifndef __LINUX_OVCAMCHIP_H
-#define __LINUX_OVCAMCHIP_H
-
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-
-/* --------------------------------- */
-/*           ENUMERATIONS            */
-/* --------------------------------- */
-
-/* Controls */
-enum {
-	OVCAMCHIP_CID_CONT,		/* Contrast */
-	OVCAMCHIP_CID_BRIGHT,		/* Brightness */
-	OVCAMCHIP_CID_SAT,		/* Saturation */
-	OVCAMCHIP_CID_HUE,		/* Hue */
-	OVCAMCHIP_CID_EXP,		/* Exposure */
-	OVCAMCHIP_CID_FREQ,		/* Light frequency */
-	OVCAMCHIP_CID_BANDFILT,		/* Banding filter */
-	OVCAMCHIP_CID_AUTOBRIGHT,	/* Auto brightness */
-	OVCAMCHIP_CID_AUTOEXP,		/* Auto exposure */
-	OVCAMCHIP_CID_BACKLIGHT,	/* Back light compensation */
-	OVCAMCHIP_CID_MIRROR,		/* Mirror horizontally */
-};
-
-/* Chip types */
-#define NUM_CC_TYPES	9
-enum {
-	CC_UNKNOWN,
-	CC_OV76BE,
-	CC_OV7610,
-	CC_OV7620,
-	CC_OV7620AE,
-	CC_OV6620,
-	CC_OV6630,
-	CC_OV6630AE,
-	CC_OV6630AF,
-};
-
-/* --------------------------------- */
-/*           I2C ADDRESSES           */
-/* --------------------------------- */
-
-#define OV7xx0_SID   (0x42 >> 1)
-#define OV6xx0_SID   (0xC0 >> 1)
-
-/* --------------------------------- */
-/*                API                */
-/* --------------------------------- */
-
-struct ovcamchip_control {
-	__u32 id;
-	__s32 value;
-};
-
-struct ovcamchip_window {
-	int x;
-	int y;
-	int width;
-	int height;
-	int format;
-	int quarter;		/* Scale width and height down 2x */
-
-	/* This stuff will be removed eventually */
-	int clockdiv;		/* Clock divisor setting */
-};
-
-/* Commands */
-#define OVCAMCHIP_CMD_Q_SUBTYPE     _IOR  (0x88, 0x00, int)
-#define OVCAMCHIP_CMD_INITIALIZE    _IOW  (0x88, 0x01, int)
-/* You must call OVCAMCHIP_CMD_INITIALIZE before any of commands below! */
-#define OVCAMCHIP_CMD_S_CTRL        _IOW  (0x88, 0x02, struct ovcamchip_control)
-#define OVCAMCHIP_CMD_G_CTRL        _IOWR (0x88, 0x03, struct ovcamchip_control)
-#define OVCAMCHIP_CMD_S_MODE        _IOW  (0x88, 0x04, struct ovcamchip_window)
-#define OVCAMCHIP_MAX_CMD           _IO   (0x88, 0x3f)
-
-#endif
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
new file mode 100644
index 0000000..a23c1fc
--- /dev/null
+++ b/include/media/rc-core.h
@@ -0,0 +1,220 @@
+/*
+ * Remote Controller core header
+ *
+ * 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.
+ */
+
+#ifndef _RC_CORE
+#define _RC_CORE
+
+#include <linux/spinlock.h>
+#include <linux/kfifo.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <media/rc-map.h>
+
+extern int rc_core_debug;
+#define IR_dprintk(level, fmt, arg...)	if (rc_core_debug >= level) \
+	printk(KERN_DEBUG "%s: " fmt , __func__, ## arg)
+
+enum rc_driver_type {
+	RC_DRIVER_SCANCODE = 0,	/* Driver or hardware generates a scancode */
+	RC_DRIVER_IR_RAW,	/* Needs a Infra-Red pulse/space decoder */
+};
+
+/**
+ * struct rc_dev - represents a remote control device
+ * @dev: driver model's view of this device
+ * @input_name: name of the input child device
+ * @input_phys: physical path to the input child device
+ * @input_id: id of the input child device (struct input_id)
+ * @driver_name: name of the hardware driver which registered this device
+ * @map_name: name of the default keymap
+ * @rc_map: current scan/key table
+ * @devno: unique remote control device number
+ * @raw: additional data for raw pulse/space devices
+ * @input_dev: the input child device used to communicate events to userspace
+ * @driver_type: specifies if protocol decoding is done in hardware or software 
+ * @idle: used to keep track of RX state
+ * @allowed_protos: bitmask with the supported RC_TYPE_* protocols
+ * @scanmask: some hardware decoders are not capable of providing the full
+ *	scancode to the application. As this is a hardware limit, we can't do
+ *	anything with it. Yet, as the same keycode table can be used with other
+ *	devices, a mask is provided to allow its usage. Drivers should generally
+ *	leave this field in blank
+ * @priv: driver-specific data
+ * @keylock: protects the remaining members of the struct
+ * @keypressed: whether a key is currently pressed
+ * @keyup_jiffies: time (in jiffies) when the current keypress should be released
+ * @timer_keyup: timer for releasing a keypress
+ * @last_keycode: keycode of last keypress
+ * @last_scancode: scancode of last keypress
+ * @last_toggle: toggle value of last command
+ * @timeout: optional time after which device stops sending data
+ * @min_timeout: minimum timeout supported by device
+ * @max_timeout: maximum timeout supported by device
+ * @rx_resolution : resolution (in ns) of input sampler
+ * @tx_resolution: resolution (in ns) of output sampler
+ * @change_protocol: allow changing the protocol used on hardware decoders
+ * @open: callback to allow drivers to enable polling/irq when IR input device
+ *	is opened.
+ * @close: callback to allow drivers to disable polling/irq when IR input device
+ *	is opened.
+ * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs)
+ * @s_tx_carrier: set transmit carrier frequency
+ * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%)
+ * @s_rx_carrier: inform driver about carrier it is expected to handle
+ * @tx_ir: transmit IR
+ * @s_idle: enable/disable hardware idle mode, upon which,
+ *	device doesn't interrupt host until it sees IR pulses
+ * @s_learning_mode: enable wide band receiver used for learning
+ * @s_carrier_report: enable carrier reports
+ */
+struct rc_dev {
+	struct device			dev;
+	const char			*input_name;
+	const char			*input_phys;
+	struct input_id			input_id;
+	char				*driver_name;
+	const char			*map_name;
+	struct rc_map	rc_map;
+	unsigned long			devno;
+	struct ir_raw_event_ctrl	*raw;
+	struct input_dev		*input_dev;
+	enum rc_driver_type		driver_type;
+	bool				idle;
+	u64				allowed_protos;
+	u32				scanmask;
+	void				*priv;
+	spinlock_t			keylock;
+	bool				keypressed;
+	unsigned long			keyup_jiffies;
+	struct timer_list		timer_keyup;
+	u32				last_keycode;
+	u32				last_scancode;
+	u8				last_toggle;
+	u32				timeout;
+	u32				min_timeout;
+	u32				max_timeout;
+	u32				rx_resolution;
+	u32				tx_resolution;
+	int				(*change_protocol)(struct rc_dev *dev, u64 rc_type);
+	int				(*open)(struct rc_dev *dev);
+	void				(*close)(struct rc_dev *dev);
+	int				(*s_tx_mask)(struct rc_dev *dev, u32 mask);
+	int				(*s_tx_carrier)(struct rc_dev *dev, u32 carrier);
+	int				(*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle);
+	int				(*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max);
+	int				(*tx_ir)(struct rc_dev *dev, int *txbuf, u32 n);
+	void				(*s_idle)(struct rc_dev *dev, bool enable);
+	int				(*s_learning_mode)(struct rc_dev *dev, int enable);
+	int				(*s_carrier_report) (struct rc_dev *dev, int enable);
+};
+
+#define to_rc_dev(d) container_of(d, struct rc_dev, dev)
+
+/*
+ * From rc-main.c
+ * Those functions can be used on any type of Remote Controller. They
+ * basically creates an input_dev and properly reports the device as a
+ * Remote Controller, at sys/class/rc.
+ */
+
+struct rc_dev *rc_allocate_device(void);
+void rc_free_device(struct rc_dev *dev);
+int rc_register_device(struct rc_dev *dev);
+void rc_unregister_device(struct rc_dev *dev);
+
+void rc_repeat(struct rc_dev *dev);
+void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle);
+void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle);
+void rc_keyup(struct rc_dev *dev);
+u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode);
+
+/*
+ * From rc-raw.c
+ * The Raw interface is specific to InfraRed. It may be a good idea to
+ * split it later into a separate header.
+ */
+
+enum raw_event_type {
+	IR_SPACE        = (1 << 0),
+	IR_PULSE        = (1 << 1),
+	IR_START_EVENT  = (1 << 2),
+	IR_STOP_EVENT   = (1 << 3),
+};
+
+struct ir_raw_event {
+	union {
+		u32             duration;
+
+		struct {
+			u32     carrier;
+			u8      duty_cycle;
+		};
+	};
+
+	unsigned                pulse:1;
+	unsigned                reset:1;
+	unsigned                timeout:1;
+	unsigned                carrier_report:1;
+};
+
+#define DEFINE_IR_RAW_EVENT(event) \
+	struct ir_raw_event event = { \
+		{ .duration = 0 } , \
+		.pulse = 0, \
+		.reset = 0, \
+		.timeout = 0, \
+		.carrier_report = 0 }
+
+static inline void init_ir_raw_event(struct ir_raw_event *ev)
+{
+	memset(ev, 0, sizeof(*ev));
+}
+
+#define IR_MAX_DURATION         0xFFFFFFFF      /* a bit more than 4 seconds */
+
+void ir_raw_event_handle(struct rc_dev *dev);
+int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev);
+int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type);
+int ir_raw_event_store_with_filter(struct rc_dev *dev,
+				struct ir_raw_event *ev);
+void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
+
+static inline void ir_raw_event_reset(struct rc_dev *dev)
+{
+	DEFINE_IR_RAW_EVENT(ev);
+	ev.reset = true;
+
+	ir_raw_event_store(dev, &ev);
+	ir_raw_event_handle(dev);
+}
+
+/* extract mask bits out of data and pack them into the result */
+static inline 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;
+}
+
+#endif /* _RC_CORE */
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index e0f17ed..ee9e2f74 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -11,45 +11,45 @@
 
 #include <linux/input.h>
 
-#define IR_TYPE_UNKNOWN	0
-#define IR_TYPE_RC5	(1  << 0)	/* Philips RC5 protocol */
-#define IR_TYPE_NEC	(1  << 1)
-#define IR_TYPE_RC6	(1  << 2)	/* Philips RC6 protocol */
-#define IR_TYPE_JVC	(1  << 3)	/* JVC protocol */
-#define IR_TYPE_SONY	(1  << 4)	/* Sony12/15/20 protocol */
-#define IR_TYPE_RC5_SZ	(1  << 5)	/* RC5 variant used by Streamzap */
-#define IR_TYPE_LIRC	(1  << 30)	/* Pass raw IR to lirc userspace */
-#define IR_TYPE_OTHER	(1u << 31)
+#define RC_TYPE_UNKNOWN	0
+#define RC_TYPE_RC5	(1  << 0)	/* Philips RC5 protocol */
+#define RC_TYPE_NEC	(1  << 1)
+#define RC_TYPE_RC6	(1  << 2)	/* Philips RC6 protocol */
+#define RC_TYPE_JVC	(1  << 3)	/* JVC protocol */
+#define RC_TYPE_SONY	(1  << 4)	/* Sony12/15/20 protocol */
+#define RC_TYPE_RC5_SZ	(1  << 5)	/* RC5 variant used by Streamzap */
+#define RC_TYPE_LIRC	(1  << 30)	/* Pass raw IR to lirc userspace */
+#define RC_TYPE_OTHER	(1u << 31)
 
-#define IR_TYPE_ALL (IR_TYPE_RC5 | IR_TYPE_NEC  | IR_TYPE_RC6  | \
-		     IR_TYPE_JVC | IR_TYPE_SONY | IR_TYPE_LIRC | \
-		     IR_TYPE_RC5_SZ | IR_TYPE_OTHER)
+#define RC_TYPE_ALL (RC_TYPE_RC5 | RC_TYPE_NEC  | RC_TYPE_RC6  | \
+		     RC_TYPE_JVC | RC_TYPE_SONY | RC_TYPE_LIRC | \
+		     RC_TYPE_RC5_SZ | RC_TYPE_OTHER)
 
-struct ir_scancode {
+struct rc_map_table {
 	u32	scancode;
 	u32	keycode;
 };
 
-struct ir_scancode_table {
-	struct ir_scancode	*scan;
+struct rc_map {
+	struct rc_map_table	*scan;
 	unsigned int		size;	/* Max number of entries */
 	unsigned int		len;	/* Used number of entries */
 	unsigned int		alloc;	/* Size of *scan in bytes */
-	u64			ir_type;
+	u64			rc_type;
 	const char		*name;
 	spinlock_t		lock;
 };
 
-struct rc_keymap {
+struct rc_map_list {
 	struct list_head	 list;
-	struct ir_scancode_table map;
+	struct rc_map map;
 };
 
 /* Routines from rc-map.c */
 
-int ir_register_map(struct rc_keymap *map);
-void ir_unregister_map(struct rc_keymap *map);
-struct ir_scancode_table *get_rc_map(const char *name);
+int rc_map_register(struct rc_map_list *map);
+void rc_map_unregister(struct rc_map_list *map);
+struct rc_map *rc_map_get(const char *name);
 void rc_map_init(void);
 
 /* Names of the several keytables defined in-kernel */
@@ -119,6 +119,7 @@
 #define RC_MAP_PINNACLE_PCTV_HD          "rc-pinnacle-pctv-hd"
 #define RC_MAP_PIXELVIEW_NEW             "rc-pixelview-new"
 #define RC_MAP_PIXELVIEW                 "rc-pixelview"
+#define RC_MAP_PIXELVIEW_002T		 "rc-pixelview-002t"
 #define RC_MAP_PIXELVIEW_MK12            "rc-pixelview-mk12"
 #define RC_MAP_POWERCOLOR_REAL_ANGEL     "rc-powercolor-real-angel"
 #define RC_MAP_PROTEUS_2309              "rc-proteus-2309"
@@ -137,6 +138,7 @@
 #define RC_MAP_TREKSTOR                  "rc-trekstor"
 #define RC_MAP_TT_1500                   "rc-tt-1500"
 #define RC_MAP_TWINHAN_VP1027_DVBS       "rc-twinhan1027"
+#define RC_MAP_VIDEOMATE_M1F             "rc-videomate-m1f"
 #define RC_MAP_VIDEOMATE_S350            "rc-videomate-s350"
 #define RC_MAP_VIDEOMATE_TV_PVR          "rc-videomate-tv-pvr"
 #define RC_MAP_WINFAST                   "rc-winfast"
diff --git a/include/media/rds.h b/include/media/rds.h
deleted file mode 100644
index a894266..0000000
--- a/include/media/rds.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-
-    Types and defines needed for RDS. This is included by
-    saa6588.c and every driver (e.g. bttv-driver.c) that wants
-    to use the saa6588 module.
-
-    Instead of having a separate rds.h, I'd prefer to include
-    this stuff in one of the already existing files like tuner.h
-
-    (c) 2005 by Hans J. Koch
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU 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 _RDS_H
-#define _RDS_H
-
-struct rds_command {
-	unsigned int  block_count;
-	int           result;
-	unsigned char __user *buffer;
-	struct file   *instance;
-	poll_table    *event_list;
-};
-
-#define RDS_CMD_OPEN	_IOW('R',1,int)
-#define RDS_CMD_CLOSE	_IOW('R',2,int)
-#define RDS_CMD_READ	_IOR('R',3,int)
-#define RDS_CMD_POLL	_IOR('R',4,int)
-
-#endif
diff --git a/include/media/saa6588.h b/include/media/saa6588.h
new file mode 100644
index 0000000..2c3c442
--- /dev/null
+++ b/include/media/saa6588.h
@@ -0,0 +1,42 @@
+/*
+
+    Types and defines needed for RDS. This is included by
+    saa6588.c and every driver (e.g. bttv-driver.c) that wants
+    to use the saa6588 module.
+
+    (c) 2005 by Hans J. Koch
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU 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 _SAA6588_H
+#define _SAA6588_H
+
+struct saa6588_command {
+	unsigned int  block_count;
+	int           result;
+	unsigned char __user *buffer;
+	struct file   *instance;
+	poll_table    *event_list;
+};
+
+/* These ioctls are internal to the kernel */
+#define SAA6588_CMD_OPEN	_IOW('R', 1, int)
+#define SAA6588_CMD_CLOSE	_IOW('R', 2, int)
+#define SAA6588_CMD_READ	_IOR('R', 3, int)
+#define SAA6588_CMD_POLL	_IOR('R', 4, int)
+
+#endif
diff --git a/include/media/si4713.h b/include/media/si4713.h
index 99850a5..ed7353e 100644
--- a/include/media/si4713.h
+++ b/include/media/si4713.h
@@ -23,8 +23,7 @@
  * Platform dependent definition
  */
 struct si4713_platform_data {
-	/* Set power state, zero is off, non-zero is on. */
-	int (*set_power)(int power);
+	int gpio_reset; /* < 0 if not used */
 };
 
 /*
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 86e3631..9386db8 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -97,6 +97,7 @@
 #define SOCAM_SENSOR_INVERT_DATA	(1 << 4)
 
 struct i2c_board_info;
+struct regulator_bulk_data;
 
 struct soc_camera_link {
 	/* Camera bus id, used to match a camera and a bus */
@@ -108,6 +109,10 @@
 	const char *module_name;
 	void *priv;
 
+	/* Optional regulators that have to be managed on power on/off events */
+	struct regulator_bulk_data *regulators;
+	int num_regulators;
+
 	/*
 	 * For non-I2C devices platform platform has to provide methods to
 	 * add a device to the system and to remove
diff --git a/include/media/timb_radio.h b/include/media/timb_radio.h
index fcd32a3..a59a848 100644
--- a/include/media/timb_radio.h
+++ b/include/media/timb_radio.h
@@ -24,7 +24,6 @@
 struct timb_radio_platform_data {
 	int i2c_adapter; /* I2C adapter where the tuner and dsp are attached */
 	struct {
-		const char *module_name;
 		struct i2c_board_info *info;
 	} tuner;
 	struct {
diff --git a/include/media/timb_video.h b/include/media/timb_video.h
new file mode 100644
index 0000000..70ae439
--- /dev/null
+++ b/include/media/timb_video.h
@@ -0,0 +1,33 @@
+/*
+ * timb_video.h Platform struct for the Timberdale video 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.
+ */
+
+#ifndef _TIMB_VIDEO_
+#define _TIMB_VIDEO_ 1
+
+#include <linux/i2c.h>
+
+struct timb_video_platform_data {
+	int dma_channel;
+	int i2c_adapter; /* The I2C adapter where the encoder is attached */
+	struct {
+		const char *module_name;
+		struct i2c_board_info *info;
+	} encoder;
+};
+
+#endif
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 51e89f2..44fe44e 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -74,6 +74,7 @@
 	V4L2_IDENT_SOI968 = 256,
 	V4L2_IDENT_OV9640 = 257,
 	V4L2_IDENT_OV6650 = 258,
+	V4L2_IDENT_OV2640 = 259,
 
 	/* module saa7146: reserved range 300-309 */
 	V4L2_IDENT_SAA7146 = 300,
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 239125a..2d65b35 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -98,12 +98,12 @@
 /* Control helper functions */
 
 int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
-		const char **menu_items);
+		const char * const *menu_items);
 const char *v4l2_ctrl_get_name(u32 id);
-const char **v4l2_ctrl_get_menu(u32 id);
+const char * const *v4l2_ctrl_get_menu(u32 id);
 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def);
 int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu,
-		struct v4l2_queryctrl *qctrl, const char **menu_items);
+		struct v4l2_queryctrl *qctrl, const char * const *menu_items);
 #define V4L2_CTRL_MENU_IDS_END (0xffffffff)
 int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids);
 
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 9b7bea9..d69ab4a 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -112,7 +112,7 @@
 		u32 step;
 		u32 menu_skip_mask;
 	};
-	const char **qmenu;
+	const char * const *qmenu;
 	unsigned long flags;
 	union {
 		s32 val;
@@ -202,7 +202,7 @@
 	s32 def;
 	u32 flags;
 	u32 menu_skip_mask;
-	const char **qmenu;
+	const char * const *qmenu;
 	unsigned int is_private:1;
 	unsigned int is_volatile:1;
 };
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 06daa6e..67df375 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -14,12 +14,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/compiler.h> /* need __user */
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-#define __MIN_V4L1
-#include <linux/videodev.h>
-#else
 #include <linux/videodev2.h>
-#endif
 
 struct v4l2_fh;
 
@@ -113,10 +108,6 @@
 
 
 	int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-			/* buffer type is struct vidio_mbuf * */
-	int (*vidiocgmbuf)  (struct file *file, void *fh, struct video_mbuf *p);
-#endif
 	int (*vidioc_g_fbuf)   (struct file *file, void *fh,
 				struct v4l2_framebuffer *a);
 	int (*vidioc_s_fbuf)   (struct file *file, void *fh,
@@ -300,22 +291,15 @@
 extern const char *v4l2_field_names[];
 extern const char *v4l2_type_names[];
 
-/*  Compatibility layer interface  --  v4l1-compat module */
-typedef long (*v4l2_kioctl)(struct file *file,
-			   unsigned int cmd, void *arg);
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-long v4l_compat_translate_ioctl(struct file *file,
-			       int cmd, void *arg, v4l2_kioctl driver_ioctl);
-#else
-#define v4l_compat_translate_ioctl(file, cmd, arg, ioctl) (-EINVAL)
-#endif
-
 #ifdef CONFIG_COMPAT
 /* 32 Bits compatibility layer for 64 bits processors */
 extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd,
 				unsigned long arg);
 #endif
 
+typedef long (*v4l2_kioctl)(struct file *file,
+		unsigned int cmd, void *arg);
+
 /* Include support for obsoleted stuff */
 extern long video_usercopy(struct file *file, unsigned int cmd,
 				unsigned long arg, v4l2_kioctl func);
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
index 1d3835f..90ed895 100644
--- a/include/media/videobuf-core.h
+++ b/include/media/videobuf-core.h
@@ -17,10 +17,6 @@
 #define _VIDEOBUF_CORE_H
 
 #include <linux/poll.h>
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-#define __MIN_V4L1
-#include <linux/videodev.h>
-#endif
 #include <linux/videodev2.h>
 
 #define UNSET (-1U)
@@ -212,10 +208,6 @@
 		  struct v4l2_buffer *b);
 int videobuf_dqbuf(struct videobuf_queue *q,
 		   struct v4l2_buffer *b, int nonblocking);
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-int videobuf_cgmbuf(struct videobuf_queue *q,
-		    struct video_mbuf *mbuf, int count);
-#endif
 int videobuf_streamon(struct videobuf_queue *q);
 int videobuf_streamoff(struct videobuf_queue *q);
 
diff --git a/include/media/wm8775.h b/include/media/wm8775.h
index a1c4d41..60739c5 100644
--- a/include/media/wm8775.h
+++ b/include/media/wm8775.h
@@ -32,7 +32,4 @@
 #define WM8775_AIN3 4
 #define WM8775_AIN4 8
 
-/* subdev group ID */
-#define WM8775_GID (1 << 0)
-
 #endif
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index a8631ac..c3e1cbc 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -263,6 +263,7 @@
 	ISCSI_ERR_INVALID_HOST		= ISCSI_ERR_BASE + 18,
 	ISCSI_ERR_XMIT_FAILED		= ISCSI_ERR_BASE + 19,
 	ISCSI_ERR_TCP_CONN_CLOSE	= ISCSI_ERR_BASE + 20,
+	ISCSI_ERR_SCSI_EH_SESSION_RST	= ISCSI_ERR_BASE + 21,
 };
 
 /*
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 5c4c167..f53c8e3 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -221,8 +221,8 @@
  * @InputRequests:         Number of input requests
  * @OutputRequests:        Number of output requests
  * @ControlRequests:       Number of control requests
- * @InputMegabytes:        Number of received megabytes
- * @OutputMegabytes:       Number of transmitted megabytes
+ * @InputBytes:            Number of received bytes
+ * @OutputBytes:           Number of transmitted bytes
  * @VLinkFailureCount:     Number of virtual link failures
  * @MissDiscAdvCount:      Number of missing FIP discovery advertisement
  */
@@ -241,8 +241,8 @@
 	u64		InputRequests;
 	u64		OutputRequests;
 	u64		ControlRequests;
-	u64		InputMegabytes;
-	u64		OutputMegabytes;
+	u64		InputBytes;
+	u64		OutputBytes;
 	u64		VLinkFailureCount;
 	u64		MissDiscAdvCount;
 };
@@ -263,7 +263,6 @@
  * struct fc_fcp_pkt - FCP request structure (one for each scsi_cmnd request)
  * @lp:              The associated local port
  * @state:           The state of the I/O
- * @tgt_flags:       Target's flags
  * @ref_cnt:         Reference count
  * @scsi_pkt_lock:   Lock to protect the SCSI packet (must be taken before the
  *                   host_lock if both are to be held at the same time)
@@ -298,7 +297,6 @@
 	/* Housekeeping information */
 	struct fc_lport   *lp;
 	u16		  state;
-	u16		  tgt_flags;
 	atomic_t	  ref_cnt;
 	spinlock_t	  scsi_pkt_lock;
 
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index 06f1b5a..feb6a94 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -92,10 +92,12 @@
  * @timer_work:	   &work_struct for doing keep-alives and resets.
  * @recv_work:	   &work_struct for receiving FIP frames.
  * @fip_recv_list: list of received FIP frames.
+ * @flogi_req:	   clone of FLOGI request sent
  * @rnd_state:	   state for pseudo-random number generator.
  * @port_id:	   proposed or selected local-port ID.
  * @user_mfs:	   configured maximum FC frame size, including FC header.
  * @flogi_oxid:    exchange ID of most recent fabric login.
+ * @flogi_req_send: send of FLOGI requested
  * @flogi_count:   number of FLOGI attempts in AUTO mode.
  * @map_dest:	   use the FC_MAP mode for destination MAC addresses.
  * @spma:	   supports SPMA server-provided MACs mode
@@ -106,6 +108,7 @@
  * @update_mac:    LLD-supplied function to handle changes to MAC addresses.
  * @get_src_addr:  LLD-supplied function to supply a source MAC address.
  * @ctlr_mutex:	   lock protecting this structure.
+ * @ctlr_lock:     spinlock covering flogi_req
  *
  * This structure is used by all FCoE drivers.  It contains information
  * needed by all FCoE low-level drivers (LLDs) as well as internal state
@@ -126,12 +129,14 @@
 	struct work_struct timer_work;
 	struct work_struct recv_work;
 	struct sk_buff_head fip_recv_list;
+	struct sk_buff *flogi_req;
 
 	struct rnd_state rnd_state;
 	u32 port_id;
 
 	u16 user_mfs;
 	u16 flogi_oxid;
+	u8 flogi_req_send;
 	u8 flogi_count;
 	u8 map_dest;
 	u8 spma;
@@ -143,6 +148,7 @@
 	void (*update_mac)(struct fc_lport *, u8 *addr);
 	u8 * (*get_src_addr)(struct fc_lport *);
 	struct mutex ctlr_mutex;
+	spinlock_t ctlr_lock;
 };
 
 /**
@@ -155,6 +161,7 @@
  * @fcf_mac:	 Ethernet address of the FCF
  * @vfid:	 virtual fabric ID
  * @pri:	 selection priority, smaller values are better
+ * @flogi_sent:	 current FLOGI sent to this FCF
  * @flags:	 flags received from advertisement
  * @fka_period:	 keep-alive period, in jiffies
  *
@@ -176,6 +183,7 @@
 	u8 fcf_mac[ETH_ALEN];
 
 	u8 pri;
+	u8 flogi_sent;
 	u16 flags;
 	u32 fka_period;
 	u8 fd_flags:1;
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index b81d969..748382b 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -89,6 +89,7 @@
 	ISCSI_TASK_RUNNING,
 	ISCSI_TASK_ABRT_TMF,		/* aborted due to TMF */
 	ISCSI_TASK_ABRT_SESS_RECOV,	/* aborted due to session recovery */
+	ISCSI_TASK_REQUEUE_SCSIQ,	/* qcmd requeueing to scsi-ml */
 };
 
 struct iscsi_r2t_info {
@@ -341,7 +342,7 @@
 extern int iscsi_eh_recover_target(struct scsi_cmnd *sc);
 extern int iscsi_eh_session_reset(struct scsi_cmnd *sc);
 extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
-extern int iscsi_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *sc);
+extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc);
 
 /*
  * iSCSI host helpers.
@@ -419,6 +420,7 @@
 extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);
 extern void iscsi_requeue_task(struct iscsi_task *task);
 extern void iscsi_put_task(struct iscsi_task *task);
+extern void __iscsi_put_task(struct iscsi_task *task);
 extern void __iscsi_get_task(struct iscsi_task *task);
 extern void iscsi_complete_scsi_task(struct iscsi_task *task,
 				     uint32_t exp_cmdsn, uint32_t max_cmdsn);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 90ce527..8f6bb9c 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -361,6 +361,8 @@
 	/* The class calls this to send a task for execution. */
 	int lldd_max_execute_num;
 	int lldd_queue_size;
+	int strict_wide_ports; /* both sas_addr and attached_sas_addr must match
+				* their siblings when forming wide ports */
 
 	/* LLDD calls these to notify the class of an event. */
 	void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event);
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 216af85..1651fef1 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -115,33 +115,61 @@
 #define PERSISTENT_RESERVE_OUT 0x5f
 #define VARIABLE_LENGTH_CMD   0x7f
 #define REPORT_LUNS           0xa0
+#define SECURITY_PROTOCOL_IN  0xa2
 #define MAINTENANCE_IN        0xa3
 #define MAINTENANCE_OUT       0xa4
 #define MOVE_MEDIUM           0xa5
 #define EXCHANGE_MEDIUM       0xa6
 #define READ_12               0xa8
 #define WRITE_12              0xaa
+#define READ_MEDIA_SERIAL_NUMBER 0xab
 #define WRITE_VERIFY_12       0xae
 #define VERIFY_12	      0xaf
 #define SEARCH_HIGH_12        0xb0
 #define SEARCH_EQUAL_12       0xb1
 #define SEARCH_LOW_12         0xb2
+#define SECURITY_PROTOCOL_OUT 0xb5
 #define READ_ELEMENT_STATUS   0xb8
 #define SEND_VOLUME_TAG       0xb6
 #define WRITE_LONG_2          0xea
+#define EXTENDED_COPY         0x83
+#define RECEIVE_COPY_RESULTS  0x84
+#define ACCESS_CONTROL_IN     0x86
+#define ACCESS_CONTROL_OUT    0x87
 #define READ_16               0x88
 #define WRITE_16              0x8a
+#define READ_ATTRIBUTE        0x8c
+#define WRITE_ATTRIBUTE	      0x8d
 #define VERIFY_16	      0x8f
 #define WRITE_SAME_16	      0x93
 #define SERVICE_ACTION_IN     0x9e
 /* values for service action in */
 #define	SAI_READ_CAPACITY_16  0x10
 #define SAI_GET_LBA_STATUS    0x12
+/* values for VARIABLE_LENGTH_CMD service action codes
+ * see spc4r17 Section D.3.5, table D.7 and D.8 */
+#define VLC_SA_RECEIVE_CREDENTIAL 0x1800
 /* values for maintenance in */
+#define MI_REPORT_IDENTIFYING_INFORMATION 0x05
 #define MI_REPORT_TARGET_PGS  0x0a
+#define MI_REPORT_ALIASES     0x0b
+#define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c
+#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d
+#define MI_REPORT_PRIORITY   0x0e
+#define MI_REPORT_TIMESTAMP  0x0f
+#define MI_MANAGEMENT_PROTOCOL_IN 0x10
 /* values for maintenance out */
+#define MO_SET_IDENTIFYING_INFORMATION 0x06
 #define MO_SET_TARGET_PGS     0x0a
+#define MO_CHANGE_ALIASES     0x0b
+#define MO_SET_PRIORITY       0x0e
+#define MO_SET_TIMESTAMP      0x0f
+#define MO_MANAGEMENT_PROTOCOL_OUT 0x10
 /* values for variable length command */
+#define XDREAD_32	      0x03
+#define XDWRITE_32	      0x04
+#define XPWRITE_32	      0x06
+#define XDWRITEREAD_32	      0x07
 #define READ_32		      0x09
 #define VERIFY_32	      0x0a
 #define WRITE_32	      0x0b
diff --git a/include/trace/define_trace.h b/include/trace/define_trace.h
index 1dfab54..b0b4eb2 100644
--- a/include/trace/define_trace.h
+++ b/include/trace/define_trace.h
@@ -26,6 +26,15 @@
 #define TRACE_EVENT(name, proto, args, tstruct, assign, print)	\
 	DEFINE_TRACE(name)
 
+#undef TRACE_EVENT_CONDITION
+#define TRACE_EVENT_CONDITION(name, proto, args, cond, tstruct, assign, print) \
+	TRACE_EVENT(name,						\
+		PARAMS(proto),						\
+		PARAMS(args),						\
+		PARAMS(tstruct),					\
+		PARAMS(assign),						\
+		PARAMS(print))
+
 #undef TRACE_EVENT_FN
 #define TRACE_EVENT_FN(name, proto, args, tstruct,		\
 		assign, print, reg, unreg)			\
@@ -39,6 +48,10 @@
 #define DEFINE_EVENT_PRINT(template, name, proto, args, print)	\
 	DEFINE_TRACE(name)
 
+#undef DEFINE_EVENT_CONDITION
+#define DEFINE_EVENT_CONDITION(template, name, proto, args, cond) \
+	DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
+
 #undef DECLARE_TRACE
 #define DECLARE_TRACE(name, proto, args)	\
 	DEFINE_TRACE(name)
@@ -75,9 +88,11 @@
 
 #undef TRACE_EVENT
 #undef TRACE_EVENT_FN
+#undef TRACE_EVENT_CONDITION
 #undef DECLARE_EVENT_CLASS
 #undef DEFINE_EVENT
 #undef DEFINE_EVENT_PRINT
+#undef DEFINE_EVENT_CONDITION
 #undef TRACE_HEADER_MULTI_READ
 #undef DECLARE_TRACE
 
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 286784d..1bcc2a8 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -7,16 +7,67 @@
 #include <linux/ktime.h>
 #include <linux/tracepoint.h>
 
-#ifndef _TRACE_POWER_ENUM_
-#define _TRACE_POWER_ENUM_
-enum {
-	POWER_NONE	= 0,
-	POWER_CSTATE	= 1,	/* C-State */
-	POWER_PSTATE	= 2,	/* Fequency change or DVFS */
-	POWER_SSTATE	= 3,	/* Suspend */
-};
+DECLARE_EVENT_CLASS(cpu,
+
+	TP_PROTO(unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(state, cpu_id),
+
+	TP_STRUCT__entry(
+		__field(	u32,		state		)
+		__field(	u32,		cpu_id		)
+	),
+
+	TP_fast_assign(
+		__entry->state = state;
+		__entry->cpu_id = cpu_id;
+	),
+
+	TP_printk("state=%lu cpu_id=%lu", (unsigned long)__entry->state,
+		  (unsigned long)__entry->cpu_id)
+);
+
+DEFINE_EVENT(cpu, cpu_idle,
+
+	TP_PROTO(unsigned int state, unsigned int cpu_id),
+
+	TP_ARGS(state, cpu_id)
+);
+
+/* This file can get included multiple times, TRACE_HEADER_MULTI_READ at top */
+#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING
+#define _PWR_EVENT_AVOID_DOUBLE_DEFINING
+
+#define PWR_EVENT_EXIT -1
 #endif
 
+DEFINE_EVENT(cpu, cpu_frequency,
+
+	TP_PROTO(unsigned int frequency, unsigned int cpu_id),
+
+	TP_ARGS(frequency, cpu_id)
+);
+
+TRACE_EVENT(machine_suspend,
+
+	TP_PROTO(unsigned int state),
+
+	TP_ARGS(state),
+
+	TP_STRUCT__entry(
+		__field(	u32,		state		)
+	),
+
+	TP_fast_assign(
+		__entry->state = state;
+	),
+
+	TP_printk("state=%lu", (unsigned long)__entry->state)
+);
+
+/* This code will be removed after deprecation time exceeded (2.6.41) */
+#ifdef CONFIG_EVENT_POWER_TRACING_DEPRECATED
+
 /*
  * The power events are used for cpuidle & suspend (power_start, power_end)
  *  and for cpufreq (power_frequency)
@@ -75,6 +126,36 @@
 
 );
 
+/* Deprecated dummy functions must be protected against multi-declartion */
+#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
+#define _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
+
+enum {
+	POWER_NONE = 0,
+	POWER_CSTATE = 1,
+	POWER_PSTATE = 2,
+};
+#endif /* _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED */
+
+#else /* CONFIG_EVENT_POWER_TRACING_DEPRECATED */
+
+#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
+#define _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
+enum {
+       POWER_NONE = 0,
+       POWER_CSTATE = 1,
+       POWER_PSTATE = 2,
+};
+
+/* These dummy declaration have to be ripped out when the deprecated
+   events get removed */
+static inline void trace_power_start(u64 type, u64 state, u64 cpuid) {};
+static inline void trace_power_end(u64 cpuid) {};
+static inline void trace_power_frequency(u64 type, u64 state, u64 cpuid) {};
+#endif /* _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED */
+
+#endif /* CONFIG_EVENT_POWER_TRACING_DEPRECATED */
+
 /*
  * The clock events are used for clock enable/disable and for
  *  clock rate change
@@ -153,7 +234,6 @@
 
 	TP_ARGS(name, state, cpu_id)
 );
-
 #endif /* _TRACE_POWER_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/syscalls.h b/include/trace/events/syscalls.h
index fb726ac..5a4c04a 100644
--- a/include/trace/events/syscalls.h
+++ b/include/trace/events/syscalls.h
@@ -40,6 +40,8 @@
 	syscall_regfunc, syscall_unregfunc
 );
 
+TRACE_EVENT_FLAGS(sys_enter, TRACE_EVENT_FL_CAP_ANY)
+
 TRACE_EVENT_FN(sys_exit,
 
 	TP_PROTO(struct pt_regs *regs, long ret),
@@ -62,6 +64,8 @@
 	syscall_regfunc, syscall_unregfunc
 );
 
+TRACE_EVENT_FLAGS(sys_exit, TRACE_EVENT_FL_CAP_ANY)
+
 #endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */
 
 #endif /* _TRACE_EVENTS_SYSCALLS_H */
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index a9377c0..e16610c 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -82,6 +82,10 @@
 	TRACE_EVENT(name, PARAMS(proto), PARAMS(args),			\
 		PARAMS(tstruct), PARAMS(assign), PARAMS(print))		\
 
+#undef TRACE_EVENT_FLAGS
+#define TRACE_EVENT_FLAGS(name, value)					\
+	__TRACE_EVENT_FLAGS(name, value)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 
@@ -129,6 +133,9 @@
 #define DEFINE_EVENT_PRINT(template, name, proto, args, print)	\
 	DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))
 
+#undef TRACE_EVENT_FLAGS
+#define TRACE_EVENT_FLAGS(event, flag)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 /*
@@ -289,13 +296,19 @@
 
 #undef __array
 #define __array(type, item, len)					\
-	BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);				\
-	ret = trace_define_field(event_call, #type "[" #len "]", #item,	\
+	do {								\
+		mutex_lock(&event_storage_mutex);			\
+		BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);			\
+		snprintf(event_storage, sizeof(event_storage),		\
+			 "%s[%d]", #type, len);				\
+		ret = trace_define_field(event_call, event_storage, #item, \
 				 offsetof(typeof(field), item),		\
 				 sizeof(field.item),			\
 				 is_signed_type(type), FILTER_OTHER);	\
-	if (ret)							\
-		return ret;
+		mutex_unlock(&event_storage_mutex);			\
+		if (ret)						\
+			return ret;					\
+	} while (0);
 
 #undef __dynamic_array
 #define __dynamic_array(type, item, len)				       \
diff --git a/include/video/s1d13xxxfb.h b/include/video/s1d13xxxfb.h
index f0736cff..55f5344 100644
--- a/include/video/s1d13xxxfb.h
+++ b/include/video/s1d13xxxfb.h
@@ -136,12 +136,6 @@
 #define S1DREG_DELAYOFF			0xFFFE
 #define S1DREG_DELAYON			0xFFFF
 
-#define BBLT_FIFO_EMPTY			0x00
-#define BBLT_FIFO_NOT_EMPTY		0x40
-#define BBLT_FIFO_NOT_FULL		0x30
-#define BBLT_FIFO_HALF_FULL		0x20
-#define BBLT_FIFO_FULL			0x10
-
 #define BBLT_SOLID_FILL			0x0c
 
 
diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h
index 18bca08..6cb95c9 100644
--- a/include/video/sh_mipi_dsi.h
+++ b/include/video/sh_mipi_dsi.h
@@ -27,9 +27,15 @@
 
 struct sh_mobile_lcdc_chan_cfg;
 
+#define SH_MIPI_DSI_HSABM	(1 << 0)
+#define SH_MIPI_DSI_HSPBM	(1 << 1)
+
 struct sh_mipi_dsi_info {
 	enum sh_mipi_dsi_data_fmt	data_format;
 	struct sh_mobile_lcdc_chan_cfg	*lcd_chan;
+	unsigned long			flags;
+	u32				clksrc;
+	unsigned int			vsynw_offset;
 };
 
 #endif
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
index 1e1aa54..b569329 100644
--- a/include/video/sh_mobile_hdmi.h
+++ b/include/video/sh_mobile_hdmi.h
@@ -13,6 +13,7 @@
 
 struct sh_mobile_lcdc_chan_cfg;
 struct device;
+struct clk;
 
 /*
  * flags format
@@ -33,6 +34,8 @@
 	struct sh_mobile_lcdc_chan_cfg	*lcd_chan;
 	struct device			*lcd_dev;
 	unsigned int			 flags;
+	long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
+				    unsigned long *parent_freq);
 };
 
 #endif
diff --git a/include/video/udlfb.h b/include/video/udlfb.h
new file mode 100644
index 0000000..69d485a
--- /dev/null
+++ b/include/video/udlfb.h
@@ -0,0 +1,95 @@
+#ifndef UDLFB_H
+#define UDLFB_H
+
+/*
+ * TODO: Propose standard fb.h ioctl for reporting damage,
+ * using _IOWR() and one of the existing area structs from fb.h
+ * Consider these ioctls deprecated, but they're still used by the
+ * DisplayLink X server as yet - need both to be modified in tandem
+ * when new ioctl(s) are ready.
+ */
+#define DLFB_IOCTL_RETURN_EDID	 0xAD
+#define DLFB_IOCTL_REPORT_DAMAGE 0xAA
+struct dloarea {
+	int x, y;
+	int w, h;
+	int x2, y2;
+};
+
+struct urb_node {
+	struct list_head entry;
+	struct dlfb_data *dev;
+	struct delayed_work release_urb_work;
+	struct urb *urb;
+};
+
+struct urb_list {
+	struct list_head list;
+	spinlock_t lock;
+	struct semaphore limit_sem;
+	int available;
+	int count;
+	size_t size;
+};
+
+struct dlfb_data {
+	struct usb_device *udev;
+	struct device *gdev; /* &udev->dev */
+	struct fb_info *info;
+	struct urb_list urbs;
+	struct kref kref;
+	char *backing_buffer;
+	int fb_count;
+	bool virtualized; /* true when physical usb device not present */
+	struct delayed_work free_framebuffer_work;
+	atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
+	atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
+	char *edid; /* null until we read edid from hw or get from sysfs */
+	size_t edid_size;
+	int sku_pixel_limit;
+	int base16;
+	int base8;
+	u32 pseudo_palette[256];
+	/* blit-only rendering path metrics, exposed through sysfs */
+	atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
+	atomic_t bytes_identical; /* saved effort with backbuffer comparison */
+	atomic_t bytes_sent; /* to usb, after compression including overhead */
+	atomic_t cpu_kcycles_used; /* transpired during pixel processing */
+};
+
+#define NR_USB_REQUEST_I2C_SUB_IO 0x02
+#define NR_USB_REQUEST_CHANNEL 0x12
+
+/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
+#define BULK_SIZE 512
+#define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
+#define WRITES_IN_FLIGHT (4)
+
+#define MAX_VENDOR_DESCRIPTOR_SIZE 256
+
+#define GET_URB_TIMEOUT	HZ
+#define FREE_URB_TIMEOUT (HZ*2)
+
+#define BPP                     2
+#define MAX_CMD_PIXELS		255
+
+#define RLX_HEADER_BYTES	7
+#define MIN_RLX_PIX_BYTES       4
+#define MIN_RLX_CMD_BYTES	(RLX_HEADER_BYTES + MIN_RLX_PIX_BYTES)
+
+#define RLE_HEADER_BYTES	6
+#define MIN_RLE_PIX_BYTES	3
+#define MIN_RLE_CMD_BYTES	(RLE_HEADER_BYTES + MIN_RLE_PIX_BYTES)
+
+#define RAW_HEADER_BYTES	6
+#define MIN_RAW_PIX_BYTES	2
+#define MIN_RAW_CMD_BYTES	(RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES)
+
+#define DL_DEFIO_WRITE_DELAY    5 /* fb_deferred_io.delay in jiffies */
+#define DL_DEFIO_WRITE_DISABLE  (HZ*60) /* "disable" with long delay */
+
+/* remove these once align.h patch is taken into kernel */
+#define DL_ALIGN_UP(x, a) ALIGN(x, a)
+#define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a)
+
+#endif
diff --git a/init/Kconfig b/init/Kconfig
index c972899..8dfd094 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -393,7 +393,6 @@
 
 config RCU_TRACE
 	bool "Enable tracing for RCU"
-	depends on TREE_RCU || TREE_PREEMPT_RCU
 	help
 	  This option provides tracing in RCU which presents stats
 	  in debugfs for debugging RCU implementation.
@@ -459,6 +458,60 @@
 	  TREE_PREEMPT_RCU implementations, permitting Makefile to
 	  trivially select kernel/rcutree_trace.c.
 
+config RCU_BOOST
+	bool "Enable RCU priority boosting"
+	depends on RT_MUTEXES && TINY_PREEMPT_RCU
+	default n
+	help
+	  This option boosts the priority of preempted RCU readers that
+	  block the current preemptible RCU grace period for too long.
+	  This option also prevents heavy loads from blocking RCU
+	  callback invocation for all flavors of RCU.
+
+	  Say Y here if you are working with real-time apps or heavy loads
+	  Say N here if you are unsure.
+
+config RCU_BOOST_PRIO
+	int "Real-time priority to boost RCU readers to"
+	range 1 99
+	depends on RCU_BOOST
+	default 1
+	help
+	  This option specifies the real-time priority to which preempted
+	  RCU readers are to be boosted.  If you are working with CPU-bound
+	  real-time applications, you should specify a priority higher then
+	  the highest-priority CPU-bound application.
+
+	  Specify the real-time priority, or take the default if unsure.
+
+config RCU_BOOST_DELAY
+	int "Milliseconds to delay boosting after RCU grace-period start"
+	range 0 3000
+	depends on RCU_BOOST
+	default 500
+	help
+	  This option specifies the time to wait after the beginning of
+	  a given grace period before priority-boosting preempted RCU
+	  readers blocking that grace period.  Note that any RCU reader
+	  blocking an expedited RCU grace period is boosted immediately.
+
+	  Accept the default if unsure.
+
+config SRCU_SYNCHRONIZE_DELAY
+	int "Microseconds to delay before waiting for readers"
+	range 0 20
+	default 10
+	help
+	  This option controls how long SRCU delays before entering its
+	  loop waiting on SRCU readers.  The purpose of this loop is
+	  to avoid the unconditional context-switch penalty that would
+	  otherwise be incurred if there was an active SRCU reader,
+	  in a manner similar to adaptive locking schemes.  This should
+	  be set to be a bit longer than the common-case SRCU read-side
+	  critical-section overhead.
+
+	  Accept the default if unsure.
+
 endmenu # "RCU Subsystem"
 
 config IKCONFIG
@@ -741,6 +794,19 @@
 
 endif # NAMESPACES
 
+config SCHED_AUTOGROUP
+	bool "Automatic process group scheduling"
+	select EVENTFD
+	select CGROUPS
+	select CGROUP_SCHED
+	select FAIR_GROUP_SCHED
+	help
+	  This option optimizes the scheduler for common desktop workloads by
+	  automatically creating and populating task groups.  This separation
+	  of workloads isolates aggressive CPU burners (like build jobs) from
+	  desktop applications.  Task group autogeneration is currently based
+	  upon task session.
+
 config MM_OWNER
 	bool
 
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 830aaec..2b54bef3 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -93,7 +93,7 @@
  *
  * Returns the matching dev_t on success or 0 on failure.
  */
-static dev_t __init devt_from_partuuid(char *uuid_str)
+static dev_t devt_from_partuuid(char *uuid_str)
 {
 	dev_t res = 0;
 	struct device *dev = NULL;
diff --git a/init/main.c b/init/main.c
index 8646401..00799c1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -67,6 +67,7 @@
 #include <linux/sfi.h>
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
+#include <linux/perf_event.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -603,6 +604,8 @@
 				"enabled *very* early, fixing it\n");
 		local_irq_disable();
 	}
+	idr_init_cache();
+	perf_event_init();
 	rcu_init();
 	radix_tree_init();
 	/* init some links before init_ISA_irqs() */
@@ -658,7 +661,6 @@
 	enable_debug_pagealloc();
 	kmemleak_init();
 	debug_objects_mem_init();
-	idr_init_cache();
 	setup_per_cpu_pageset();
 	numa_policy_init();
 	if (late_time_init)
@@ -775,9 +777,6 @@
 
 	for (fn = __early_initcall_end; fn < __initcall_end; fn++)
 		do_one_initcall(*fn);
-
-	/* Make sure there is no pending stuff from the initcall sequence */
-	flush_scheduled_work();
 }
 
 /*
@@ -882,6 +881,7 @@
 	smp_prepare_cpus(setup_max_cpus);
 
 	do_pre_smp_initcalls();
+	lockup_detector_init();
 
 	smp_init();
 	sched_init_smp();
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 035f439..14fb6d6 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -237,9 +237,16 @@
 	return &ei->vfs_inode;
 }
 
+static void mqueue_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(mqueue_inode_cachep, MQUEUE_I(inode));
+}
+
 static void mqueue_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(mqueue_inode_cachep, MQUEUE_I(inode));
+	call_rcu(&inode->i_rcu, mqueue_i_callback);
 }
 
 static void mqueue_evict_inode(struct inode *inode)
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 66a416b..51cddc1 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -763,6 +763,8 @@
  * -> cgroup_mkdir.
  */
 
+static struct dentry *cgroup_lookup(struct inode *dir,
+			struct dentry *dentry, struct nameidata *nd);
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 static int cgroup_populate_dir(struct cgroup *cgrp);
@@ -874,25 +876,29 @@
 	struct list_head *node;
 
 	BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
-	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
 	node = dentry->d_subdirs.next;
 	while (node != &dentry->d_subdirs) {
 		struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+
+		spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
 		list_del_init(node);
 		if (d->d_inode) {
 			/* This should never be called on a cgroup
 			 * directory with child cgroups */
 			BUG_ON(d->d_inode->i_mode & S_IFDIR);
-			d = dget_locked(d);
-			spin_unlock(&dcache_lock);
+			dget_dlock(d);
+			spin_unlock(&d->d_lock);
+			spin_unlock(&dentry->d_lock);
 			d_delete(d);
 			simple_unlink(dentry->d_inode, d);
 			dput(d);
-			spin_lock(&dcache_lock);
-		}
+			spin_lock(&dentry->d_lock);
+		} else
+			spin_unlock(&d->d_lock);
 		node = dentry->d_subdirs.next;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
 }
 
 /*
@@ -900,11 +906,16 @@
  */
 static void cgroup_d_remove_dir(struct dentry *dentry)
 {
+	struct dentry *parent;
+
 	cgroup_clear_directory(dentry);
 
-	spin_lock(&dcache_lock);
+	parent = dentry->d_parent;
+	spin_lock(&parent->d_lock);
+	spin_lock(&dentry->d_lock);
 	list_del_init(&dentry->d_u.d_child);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&parent->d_lock);
 	remove_dir(dentry);
 }
 
@@ -2180,7 +2191,7 @@
 };
 
 static const struct inode_operations cgroup_dir_inode_operations = {
-	.lookup = simple_lookup,
+	.lookup = cgroup_lookup,
 	.mkdir = cgroup_mkdir,
 	.rmdir = cgroup_rmdir,
 	.rename = cgroup_rename,
@@ -2196,13 +2207,29 @@
 	return __d_cft(file->f_dentry);
 }
 
-static int cgroup_create_file(struct dentry *dentry, mode_t mode,
-				struct super_block *sb)
+static int cgroup_delete_dentry(const struct dentry *dentry)
 {
-	static const struct dentry_operations cgroup_dops = {
+	return 1;
+}
+
+static struct dentry *cgroup_lookup(struct inode *dir,
+			struct dentry *dentry, struct nameidata *nd)
+{
+	static const struct dentry_operations cgroup_dentry_operations = {
+		.d_delete = cgroup_delete_dentry,
 		.d_iput = cgroup_diput,
 	};
 
+	if (dentry->d_name.len > NAME_MAX)
+		return ERR_PTR(-ENAMETOOLONG);
+	d_set_d_op(dentry, &cgroup_dentry_operations);
+	d_add(dentry, NULL);
+	return NULL;
+}
+
+static int cgroup_create_file(struct dentry *dentry, mode_t mode,
+				struct super_block *sb)
+{
 	struct inode *inode;
 
 	if (!dentry)
@@ -2228,7 +2255,6 @@
 		inode->i_size = 0;
 		inode->i_fop = &cgroup_file_operations;
 	}
-	dentry->d_op = &cgroup_dops;
 	d_instantiate(dentry, inode);
 	dget(dentry);	/* Extra count - pin the dentry in core */
 	return 0;
@@ -3638,9 +3664,7 @@
 	list_del(&cgrp->sibling);
 	cgroup_unlock_hierarchy(cgrp->root);
 
-	spin_lock(&cgrp->dentry->d_lock);
 	d = dget(cgrp->dentry);
-	spin_unlock(&d->d_lock);
 
 	cgroup_d_remove_dir(d);
 	dput(d);
diff --git a/kernel/cpu.c b/kernel/cpu.c
index f6e726f..156cc55 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -189,7 +189,6 @@
 }
 
 struct take_cpu_down_param {
-	struct task_struct *caller;
 	unsigned long mod;
 	void *hcpu;
 };
@@ -198,7 +197,6 @@
 static int __ref take_cpu_down(void *_param)
 {
 	struct take_cpu_down_param *param = _param;
-	unsigned int cpu = (unsigned long)param->hcpu;
 	int err;
 
 	/* Ensure this CPU doesn't handle any more interrupts. */
@@ -208,11 +206,6 @@
 
 	cpu_notify(CPU_DYING | param->mod, param->hcpu);
 
-	if (task_cpu(param->caller) == cpu)
-		move_task_off_dead_cpu(cpu, param->caller);
-	/* Force idle task to run as soon as we yield: it should
-	   immediately notice cpu is offline and die quickly. */
-	sched_idle_next();
 	return 0;
 }
 
@@ -223,7 +216,6 @@
 	void *hcpu = (void *)(long)cpu;
 	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
 	struct take_cpu_down_param tcd_param = {
-		.caller = current,
 		.mod = mod,
 		.hcpu = hcpu,
 	};
@@ -253,9 +245,15 @@
 	}
 	BUG_ON(cpu_online(cpu));
 
-	/* Wait for it to sleep (leaving idle task). */
+	/*
+	 * The migration_call() CPU_DYING callback will have removed all
+	 * runnable tasks from the cpu, there's only the idle task left now
+	 * that the migration thread is done doing the stop_machine thing.
+	 *
+	 * Wait for the stop thread to go away.
+	 */
 	while (!idle_cpu(cpu))
-		yield();
+		cpu_relax();
 
 	/* This actually kills the CPU. */
 	__cpu_die(cpu);
@@ -386,6 +384,14 @@
 #ifdef CONFIG_PM_SLEEP_SMP
 static cpumask_var_t frozen_cpus;
 
+void __weak arch_disable_nonboot_cpus_begin(void)
+{
+}
+
+void __weak arch_disable_nonboot_cpus_end(void)
+{
+}
+
 int disable_nonboot_cpus(void)
 {
 	int cpu, first_cpu, error = 0;
@@ -397,6 +403,7 @@
 	 * with the userspace trying to use the CPU hotplug at the same time
 	 */
 	cpumask_clear(frozen_cpus);
+	arch_disable_nonboot_cpus_begin();
 
 	printk("Disabling non-boot CPUs ...\n");
 	for_each_online_cpu(cpu) {
@@ -412,6 +419,8 @@
 		}
 	}
 
+	arch_disable_nonboot_cpus_end();
+
 	if (!error) {
 		BUG_ON(num_online_cpus() > 1);
 		/* Make sure the CPUs won't be enabled by someone else */
diff --git a/kernel/exit.c b/kernel/exit.c
index 676149a..89c7486 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -69,7 +69,7 @@
 
 		list_del_rcu(&p->tasks);
 		list_del_init(&p->sibling);
-		__get_cpu_var(process_counts)--;
+		__this_cpu_dec(process_counts);
 	}
 	list_del_rcu(&p->thread_group);
 }
diff --git a/kernel/fork.c b/kernel/fork.c
index 5447dc7..d9b44f2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -169,6 +169,7 @@
 static inline void free_signal_struct(struct signal_struct *sig)
 {
 	taskstats_tgid_free(sig);
+	sched_autogroup_exit(sig);
 	kmem_cache_free(signal_cachep, sig);
 }
 
@@ -905,6 +906,7 @@
 	posix_cpu_timers_init_group(sig);
 
 	tty_audit_fork(sig);
+	sched_autogroup_fork(sig);
 
 	sig->oom_adj = current->signal->oom_adj;
 	sig->oom_score_adj = current->signal->oom_score_adj;
@@ -1283,7 +1285,7 @@
 			attach_pid(p, PIDTYPE_SID, task_session(current));
 			list_add_tail(&p->sibling, &p->real_parent->children);
 			list_add_tail_rcu(&p->tasks, &init_task.tasks);
-			__get_cpu_var(process_counts)++;
+			__this_cpu_inc(process_counts);
 		}
 		attach_pid(p, PIDTYPE_PID, pid);
 		nr_threads++;
diff --git a/kernel/futex.c b/kernel/futex.c
index 40a8777..3019b92 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -69,6 +69,14 @@
 #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
 /*
+ * Futex flags used to encode options to functions and preserve them across
+ * restarts.
+ */
+#define FLAGS_SHARED		0x01
+#define FLAGS_CLOCKRT		0x02
+#define FLAGS_HAS_TIMEOUT	0x04
+
+/*
  * Priority Inheritance state:
  */
 struct futex_pi_state {
@@ -123,6 +131,12 @@
 	u32 bitset;
 };
 
+static const struct futex_q futex_q_init = {
+	/* list gets initialized in queue_me()*/
+	.key = FUTEX_KEY_INIT,
+	.bitset = FUTEX_BITSET_MATCH_ANY
+};
+
 /*
  * Hash buckets are shared by all the futex_keys that hash to the same
  * location.  Each key may have multiple futex_q structures, one for each task
@@ -283,8 +297,7 @@
 	return 0;
 }
 
-static inline
-void put_futex_key(int fshared, union futex_key *key)
+static inline void put_futex_key(union futex_key *key)
 {
 	drop_futex_key_refs(key);
 }
@@ -870,7 +883,8 @@
 /*
  * Wake up waiters matching bitset queued on this futex (uaddr).
  */
-static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)
+static int
+futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
 {
 	struct futex_hash_bucket *hb;
 	struct futex_q *this, *next;
@@ -881,7 +895,7 @@
 	if (!bitset)
 		return -EINVAL;
 
-	ret = get_futex_key(uaddr, fshared, &key);
+	ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -907,7 +921,7 @@
 	}
 
 	spin_unlock(&hb->lock);
-	put_futex_key(fshared, &key);
+	put_futex_key(&key);
 out:
 	return ret;
 }
@@ -917,7 +931,7 @@
  * to this virtual address:
  */
 static int
-futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
+futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
 	      int nr_wake, int nr_wake2, int op)
 {
 	union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
@@ -927,10 +941,10 @@
 	int ret, op_ret;
 
 retry:
-	ret = get_futex_key(uaddr1, fshared, &key1);
+	ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1);
 	if (unlikely(ret != 0))
 		goto out;
-	ret = get_futex_key(uaddr2, fshared, &key2);
+	ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
 	if (unlikely(ret != 0))
 		goto out_put_key1;
 
@@ -962,11 +976,11 @@
 		if (ret)
 			goto out_put_keys;
 
-		if (!fshared)
+		if (!(flags & FLAGS_SHARED))
 			goto retry_private;
 
-		put_futex_key(fshared, &key2);
-		put_futex_key(fshared, &key1);
+		put_futex_key(&key2);
+		put_futex_key(&key1);
 		goto retry;
 	}
 
@@ -996,9 +1010,9 @@
 
 	double_unlock_hb(hb1, hb2);
 out_put_keys:
-	put_futex_key(fshared, &key2);
+	put_futex_key(&key2);
 out_put_key1:
-	put_futex_key(fshared, &key1);
+	put_futex_key(&key1);
 out:
 	return ret;
 }
@@ -1133,13 +1147,13 @@
 /**
  * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
  * @uaddr1:	source futex user address
- * @fshared:	0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
+ * @flags:	futex flags (FLAGS_SHARED, etc.)
  * @uaddr2:	target futex user address
  * @nr_wake:	number of waiters to wake (must be 1 for requeue_pi)
  * @nr_requeue:	number of waiters to requeue (0-INT_MAX)
  * @cmpval:	@uaddr1 expected value (or %NULL)
  * @requeue_pi:	if we are attempting to requeue from a non-pi futex to a
- * 		pi futex (pi to pi requeue is not supported)
+ *		pi futex (pi to pi requeue is not supported)
  *
  * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
  * uaddr2 atomically on behalf of the top waiter.
@@ -1148,9 +1162,9 @@
  * >=0 - on success, the number of tasks requeued or woken
  *  <0 - on error
  */
-static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
-			 int nr_wake, int nr_requeue, u32 *cmpval,
-			 int requeue_pi)
+static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
+			 u32 __user *uaddr2, int nr_wake, int nr_requeue,
+			 u32 *cmpval, int requeue_pi)
 {
 	union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
 	int drop_count = 0, task_count = 0, ret;
@@ -1191,10 +1205,10 @@
 		pi_state = NULL;
 	}
 
-	ret = get_futex_key(uaddr1, fshared, &key1);
+	ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1);
 	if (unlikely(ret != 0))
 		goto out;
-	ret = get_futex_key(uaddr2, fshared, &key2);
+	ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
 	if (unlikely(ret != 0))
 		goto out_put_key1;
 
@@ -1216,11 +1230,11 @@
 			if (ret)
 				goto out_put_keys;
 
-			if (!fshared)
+			if (!(flags & FLAGS_SHARED))
 				goto retry_private;
 
-			put_futex_key(fshared, &key2);
-			put_futex_key(fshared, &key1);
+			put_futex_key(&key2);
+			put_futex_key(&key1);
 			goto retry;
 		}
 		if (curval != *cmpval) {
@@ -1260,8 +1274,8 @@
 			break;
 		case -EFAULT:
 			double_unlock_hb(hb1, hb2);
-			put_futex_key(fshared, &key2);
-			put_futex_key(fshared, &key1);
+			put_futex_key(&key2);
+			put_futex_key(&key1);
 			ret = fault_in_user_writeable(uaddr2);
 			if (!ret)
 				goto retry;
@@ -1269,8 +1283,8 @@
 		case -EAGAIN:
 			/* The owner was exiting, try again. */
 			double_unlock_hb(hb1, hb2);
-			put_futex_key(fshared, &key2);
-			put_futex_key(fshared, &key1);
+			put_futex_key(&key2);
+			put_futex_key(&key1);
 			cond_resched();
 			goto retry;
 		default:
@@ -1352,9 +1366,9 @@
 		drop_futex_key_refs(&key1);
 
 out_put_keys:
-	put_futex_key(fshared, &key2);
+	put_futex_key(&key2);
 out_put_key1:
-	put_futex_key(fshared, &key1);
+	put_futex_key(&key1);
 out:
 	if (pi_state != NULL)
 		free_pi_state(pi_state);
@@ -1494,7 +1508,7 @@
  * private futexes.
  */
 static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
-				struct task_struct *newowner, int fshared)
+				struct task_struct *newowner)
 {
 	u32 newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
 	struct futex_pi_state *pi_state = q->pi_state;
@@ -1587,20 +1601,11 @@
 	goto retry;
 }
 
-/*
- * In case we must use restart_block to restart a futex_wait,
- * we encode in the 'flags' shared capability
- */
-#define FLAGS_SHARED		0x01
-#define FLAGS_CLOCKRT		0x02
-#define FLAGS_HAS_TIMEOUT	0x04
-
 static long futex_wait_restart(struct restart_block *restart);
 
 /**
  * fixup_owner() - Post lock pi_state and corner case management
  * @uaddr:	user address of the futex
- * @fshared:	whether the futex is shared (1) or not (0)
  * @q:		futex_q (contains pi_state and access to the rt_mutex)
  * @locked:	if the attempt to take the rt_mutex succeeded (1) or not (0)
  *
@@ -1613,8 +1618,7 @@
  *  0 - success, lock not taken
  * <0 - on error (-EFAULT)
  */
-static int fixup_owner(u32 __user *uaddr, int fshared, struct futex_q *q,
-		       int locked)
+static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
 {
 	struct task_struct *owner;
 	int ret = 0;
@@ -1625,7 +1629,7 @@
 		 * did a lock-steal - fix up the PI-state in that case:
 		 */
 		if (q->pi_state->owner != current)
-			ret = fixup_pi_state_owner(uaddr, q, current, fshared);
+			ret = fixup_pi_state_owner(uaddr, q, current);
 		goto out;
 	}
 
@@ -1652,7 +1656,7 @@
 		 * lock. Fix the state up.
 		 */
 		owner = rt_mutex_owner(&q->pi_state->pi_mutex);
-		ret = fixup_pi_state_owner(uaddr, q, owner, fshared);
+		ret = fixup_pi_state_owner(uaddr, q, owner);
 		goto out;
 	}
 
@@ -1715,7 +1719,7 @@
  * futex_wait_setup() - Prepare to wait on a futex
  * @uaddr:	the futex userspace address
  * @val:	the expected value
- * @fshared:	whether the futex is shared (1) or not (0)
+ * @flags:	futex flags (FLAGS_SHARED, etc.)
  * @q:		the associated futex_q
  * @hb:		storage for hash_bucket pointer to be returned to caller
  *
@@ -1728,7 +1732,7 @@
  *  0 - uaddr contains val and hb has been locked
  * <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlcoked
  */
-static int futex_wait_setup(u32 __user *uaddr, u32 val, int fshared,
+static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
 			   struct futex_q *q, struct futex_hash_bucket **hb)
 {
 	u32 uval;
@@ -1752,8 +1756,7 @@
 	 * rare, but normal.
 	 */
 retry:
-	q->key = FUTEX_KEY_INIT;
-	ret = get_futex_key(uaddr, fshared, &q->key);
+	ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key);
 	if (unlikely(ret != 0))
 		return ret;
 
@@ -1769,10 +1772,10 @@
 		if (ret)
 			goto out;
 
-		if (!fshared)
+		if (!(flags & FLAGS_SHARED))
 			goto retry_private;
 
-		put_futex_key(fshared, &q->key);
+		put_futex_key(&q->key);
 		goto retry;
 	}
 
@@ -1783,32 +1786,29 @@
 
 out:
 	if (ret)
-		put_futex_key(fshared, &q->key);
+		put_futex_key(&q->key);
 	return ret;
 }
 
-static int futex_wait(u32 __user *uaddr, int fshared,
-		      u32 val, ktime_t *abs_time, u32 bitset, int clockrt)
+static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
+		      ktime_t *abs_time, u32 bitset)
 {
 	struct hrtimer_sleeper timeout, *to = NULL;
 	struct restart_block *restart;
 	struct futex_hash_bucket *hb;
-	struct futex_q q;
+	struct futex_q q = futex_q_init;
 	int ret;
 
 	if (!bitset)
 		return -EINVAL;
-
-	q.pi_state = NULL;
 	q.bitset = bitset;
-	q.rt_waiter = NULL;
-	q.requeue_pi_key = NULL;
 
 	if (abs_time) {
 		to = &timeout;
 
-		hrtimer_init_on_stack(&to->timer, clockrt ? CLOCK_REALTIME :
-				      CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+		hrtimer_init_on_stack(&to->timer, (flags & FLAGS_CLOCKRT) ?
+				      CLOCK_REALTIME : CLOCK_MONOTONIC,
+				      HRTIMER_MODE_ABS);
 		hrtimer_init_sleeper(to, current);
 		hrtimer_set_expires_range_ns(&to->timer, *abs_time,
 					     current->timer_slack_ns);
@@ -1819,7 +1819,7 @@
 	 * Prepare to wait on uaddr. On success, holds hb lock and increments
 	 * q.key refs.
 	 */
-	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
+	ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
 	if (ret)
 		goto out;
 
@@ -1852,12 +1852,7 @@
 	restart->futex.val = val;
 	restart->futex.time = abs_time->tv64;
 	restart->futex.bitset = bitset;
-	restart->futex.flags = FLAGS_HAS_TIMEOUT;
-
-	if (fshared)
-		restart->futex.flags |= FLAGS_SHARED;
-	if (clockrt)
-		restart->futex.flags |= FLAGS_CLOCKRT;
+	restart->futex.flags = flags;
 
 	ret = -ERESTART_RESTARTBLOCK;
 
@@ -1873,7 +1868,6 @@
 static long futex_wait_restart(struct restart_block *restart)
 {
 	u32 __user *uaddr = restart->futex.uaddr;
-	int fshared = 0;
 	ktime_t t, *tp = NULL;
 
 	if (restart->futex.flags & FLAGS_HAS_TIMEOUT) {
@@ -1881,11 +1875,9 @@
 		tp = &t;
 	}
 	restart->fn = do_no_restart_syscall;
-	if (restart->futex.flags & FLAGS_SHARED)
-		fshared = 1;
-	return (long)futex_wait(uaddr, fshared, restart->futex.val, tp,
-				restart->futex.bitset,
-				restart->futex.flags & FLAGS_CLOCKRT);
+
+	return (long)futex_wait(uaddr, restart->futex.flags,
+				restart->futex.val, tp, restart->futex.bitset);
 }
 
 
@@ -1895,12 +1887,12 @@
  * if there are waiters then it will block, it does PI, etc. (Due to
  * races the kernel might see a 0 value of the futex too.)
  */
-static int futex_lock_pi(u32 __user *uaddr, int fshared,
-			 int detect, ktime_t *time, int trylock)
+static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, int detect,
+			 ktime_t *time, int trylock)
 {
 	struct hrtimer_sleeper timeout, *to = NULL;
 	struct futex_hash_bucket *hb;
-	struct futex_q q;
+	struct futex_q q = futex_q_init;
 	int res, ret;
 
 	if (refill_pi_state_cache())
@@ -1914,12 +1906,8 @@
 		hrtimer_set_expires(&to->timer, *time);
 	}
 
-	q.pi_state = NULL;
-	q.rt_waiter = NULL;
-	q.requeue_pi_key = NULL;
 retry:
-	q.key = FUTEX_KEY_INIT;
-	ret = get_futex_key(uaddr, fshared, &q.key);
+	ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -1941,7 +1929,7 @@
 			 * exit to complete.
 			 */
 			queue_unlock(&q, hb);
-			put_futex_key(fshared, &q.key);
+			put_futex_key(&q.key);
 			cond_resched();
 			goto retry;
 		default:
@@ -1971,7 +1959,7 @@
 	 * Fixup the pi_state owner and possibly acquire the lock if we
 	 * haven't already.
 	 */
-	res = fixup_owner(uaddr, fshared, &q, !ret);
+	res = fixup_owner(uaddr, &q, !ret);
 	/*
 	 * If fixup_owner() returned an error, proprogate that.  If it acquired
 	 * the lock, clear our -ETIMEDOUT or -EINTR.
@@ -1995,7 +1983,7 @@
 	queue_unlock(&q, hb);
 
 out_put_key:
-	put_futex_key(fshared, &q.key);
+	put_futex_key(&q.key);
 out:
 	if (to)
 		destroy_hrtimer_on_stack(&to->timer);
@@ -2008,10 +1996,10 @@
 	if (ret)
 		goto out_put_key;
 
-	if (!fshared)
+	if (!(flags & FLAGS_SHARED))
 		goto retry_private;
 
-	put_futex_key(fshared, &q.key);
+	put_futex_key(&q.key);
 	goto retry;
 }
 
@@ -2020,7 +2008,7 @@
  * This is the in-kernel slowpath: we look up the PI state (if any),
  * and do the rt-mutex unlock.
  */
-static int futex_unlock_pi(u32 __user *uaddr, int fshared)
+static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
 {
 	struct futex_hash_bucket *hb;
 	struct futex_q *this, *next;
@@ -2038,7 +2026,7 @@
 	if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current))
 		return -EPERM;
 
-	ret = get_futex_key(uaddr, fshared, &key);
+	ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -2093,14 +2081,14 @@
 
 out_unlock:
 	spin_unlock(&hb->lock);
-	put_futex_key(fshared, &key);
+	put_futex_key(&key);
 
 out:
 	return ret;
 
 pi_faulted:
 	spin_unlock(&hb->lock);
-	put_futex_key(fshared, &key);
+	put_futex_key(&key);
 
 	ret = fault_in_user_writeable(uaddr);
 	if (!ret)
@@ -2160,7 +2148,7 @@
 /**
  * futex_wait_requeue_pi() - Wait on uaddr and take uaddr2
  * @uaddr:	the futex we initially wait on (non-pi)
- * @fshared:	whether the futexes are shared (1) or not (0).  They must be
+ * @flags:	futex flags (FLAGS_SHARED, FLAGS_CLOCKRT, etc.), they must be
  * 		the same type, no requeueing from private to shared, etc.
  * @val:	the expected value of uaddr
  * @abs_time:	absolute timeout
@@ -2198,16 +2186,16 @@
  *  0 - On success
  * <0 - On error
  */
-static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
+static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
 				 u32 val, ktime_t *abs_time, u32 bitset,
-				 int clockrt, u32 __user *uaddr2)
+				 u32 __user *uaddr2)
 {
 	struct hrtimer_sleeper timeout, *to = NULL;
 	struct rt_mutex_waiter rt_waiter;
 	struct rt_mutex *pi_mutex = NULL;
 	struct futex_hash_bucket *hb;
-	union futex_key key2;
-	struct futex_q q;
+	union futex_key key2 = FUTEX_KEY_INIT;
+	struct futex_q q = futex_q_init;
 	int res, ret;
 
 	if (!bitset)
@@ -2215,8 +2203,9 @@
 
 	if (abs_time) {
 		to = &timeout;
-		hrtimer_init_on_stack(&to->timer, clockrt ? CLOCK_REALTIME :
-				      CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+		hrtimer_init_on_stack(&to->timer, (flags & FLAGS_CLOCKRT) ?
+				      CLOCK_REALTIME : CLOCK_MONOTONIC,
+				      HRTIMER_MODE_ABS);
 		hrtimer_init_sleeper(to, current);
 		hrtimer_set_expires_range_ns(&to->timer, *abs_time,
 					     current->timer_slack_ns);
@@ -2229,12 +2218,10 @@
 	debug_rt_mutex_init_waiter(&rt_waiter);
 	rt_waiter.task = NULL;
 
-	key2 = FUTEX_KEY_INIT;
-	ret = get_futex_key(uaddr2, fshared, &key2);
+	ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
 	if (unlikely(ret != 0))
 		goto out;
 
-	q.pi_state = NULL;
 	q.bitset = bitset;
 	q.rt_waiter = &rt_waiter;
 	q.requeue_pi_key = &key2;
@@ -2243,7 +2230,7 @@
 	 * Prepare to wait on uaddr. On success, increments q.key (key1) ref
 	 * count.
 	 */
-	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
+	ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
 	if (ret)
 		goto out_key2;
 
@@ -2273,8 +2260,7 @@
 		 */
 		if (q.pi_state && (q.pi_state->owner != current)) {
 			spin_lock(q.lock_ptr);
-			ret = fixup_pi_state_owner(uaddr2, &q, current,
-						   fshared);
+			ret = fixup_pi_state_owner(uaddr2, &q, current);
 			spin_unlock(q.lock_ptr);
 		}
 	} else {
@@ -2293,7 +2279,7 @@
 		 * Fixup the pi_state owner and possibly acquire the lock if we
 		 * haven't already.
 		 */
-		res = fixup_owner(uaddr2, fshared, &q, !ret);
+		res = fixup_owner(uaddr2, &q, !ret);
 		/*
 		 * If fixup_owner() returned an error, proprogate that.  If it
 		 * acquired the lock, clear -ETIMEDOUT or -EINTR.
@@ -2324,9 +2310,9 @@
 	}
 
 out_put_keys:
-	put_futex_key(fshared, &q.key);
+	put_futex_key(&q.key);
 out_key2:
-	put_futex_key(fshared, &key2);
+	put_futex_key(&key2);
 
 out:
 	if (to) {
@@ -2551,58 +2537,57 @@
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 		u32 __user *uaddr2, u32 val2, u32 val3)
 {
-	int clockrt, ret = -ENOSYS;
-	int cmd = op & FUTEX_CMD_MASK;
-	int fshared = 0;
+	int ret = -ENOSYS, cmd = op & FUTEX_CMD_MASK;
+	unsigned int flags = 0;
 
 	if (!(op & FUTEX_PRIVATE_FLAG))
-		fshared = 1;
+		flags |= FLAGS_SHARED;
 
-	clockrt = op & FUTEX_CLOCK_REALTIME;
-	if (clockrt && cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI)
-		return -ENOSYS;
+	if (op & FUTEX_CLOCK_REALTIME) {
+		flags |= FLAGS_CLOCKRT;
+		if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI)
+			return -ENOSYS;
+	}
 
 	switch (cmd) {
 	case FUTEX_WAIT:
 		val3 = FUTEX_BITSET_MATCH_ANY;
 	case FUTEX_WAIT_BITSET:
-		ret = futex_wait(uaddr, fshared, val, timeout, val3, clockrt);
+		ret = futex_wait(uaddr, flags, val, timeout, val3);
 		break;
 	case FUTEX_WAKE:
 		val3 = FUTEX_BITSET_MATCH_ANY;
 	case FUTEX_WAKE_BITSET:
-		ret = futex_wake(uaddr, fshared, val, val3);
+		ret = futex_wake(uaddr, flags, val, val3);
 		break;
 	case FUTEX_REQUEUE:
-		ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, NULL, 0);
+		ret = futex_requeue(uaddr, flags, uaddr2, val, val2, NULL, 0);
 		break;
 	case FUTEX_CMP_REQUEUE:
-		ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, &val3,
-				    0);
+		ret = futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 0);
 		break;
 	case FUTEX_WAKE_OP:
-		ret = futex_wake_op(uaddr, fshared, uaddr2, val, val2, val3);
+		ret = futex_wake_op(uaddr, flags, uaddr2, val, val2, val3);
 		break;
 	case FUTEX_LOCK_PI:
 		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, fshared, val, timeout, 0);
+			ret = futex_lock_pi(uaddr, flags, val, timeout, 0);
 		break;
 	case FUTEX_UNLOCK_PI:
 		if (futex_cmpxchg_enabled)
-			ret = futex_unlock_pi(uaddr, fshared);
+			ret = futex_unlock_pi(uaddr, flags);
 		break;
 	case FUTEX_TRYLOCK_PI:
 		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
+			ret = futex_lock_pi(uaddr, flags, 0, timeout, 1);
 		break;
 	case FUTEX_WAIT_REQUEUE_PI:
 		val3 = FUTEX_BITSET_MATCH_ANY;
-		ret = futex_wait_requeue_pi(uaddr, fshared, val, timeout, val3,
-					    clockrt, uaddr2);
+		ret = futex_wait_requeue_pi(uaddr, flags, val, timeout, val3,
+					    uaddr2);
 		break;
 	case FUTEX_CMP_REQUEUE_PI:
-		ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, &val3,
-				    1);
+		ret = futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 1);
 		break;
 	default:
 		ret = -ENOSYS;
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 72206cf..45da2b6 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -497,7 +497,7 @@
  */
 static inline int hrtimer_hres_active(void)
 {
-	return __get_cpu_var(hrtimer_bases).hres_active;
+	return __this_cpu_read(hrtimer_bases.hres_active);
 }
 
 /*
@@ -516,10 +516,13 @@
 
 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
 		struct hrtimer *timer;
+		struct timerqueue_node *next;
 
-		if (!base->first)
+		next = timerqueue_getnext(&base->active);
+		if (!next)
 			continue;
-		timer = rb_entry(base->first, struct hrtimer, node);
+		timer = container_of(next, struct hrtimer, node);
+
 		expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
 		/*
 		 * clock_was_set() has changed base->offset so the
@@ -840,48 +843,17 @@
 static int enqueue_hrtimer(struct hrtimer *timer,
 			   struct hrtimer_clock_base *base)
 {
-	struct rb_node **link = &base->active.rb_node;
-	struct rb_node *parent = NULL;
-	struct hrtimer *entry;
-	int leftmost = 1;
-
 	debug_activate(timer);
 
-	/*
-	 * Find the right place in the rbtree:
-	 */
-	while (*link) {
-		parent = *link;
-		entry = rb_entry(parent, struct hrtimer, node);
-		/*
-		 * We dont care about collisions. Nodes with
-		 * the same expiry time stay together.
-		 */
-		if (hrtimer_get_expires_tv64(timer) <
-				hrtimer_get_expires_tv64(entry)) {
-			link = &(*link)->rb_left;
-		} else {
-			link = &(*link)->rb_right;
-			leftmost = 0;
-		}
-	}
+	timerqueue_add(&base->active, &timer->node);
 
 	/*
-	 * Insert the timer to the rbtree and check whether it
-	 * replaces the first pending timer
-	 */
-	if (leftmost)
-		base->first = &timer->node;
-
-	rb_link_node(&timer->node, parent, link);
-	rb_insert_color(&timer->node, &base->active);
-	/*
 	 * HRTIMER_STATE_ENQUEUED is or'ed to the current state to preserve the
 	 * state of a possibly running callback.
 	 */
 	timer->state |= HRTIMER_STATE_ENQUEUED;
 
-	return leftmost;
+	return (&timer->node == base->active.next);
 }
 
 /*
@@ -901,12 +873,7 @@
 	if (!(timer->state & HRTIMER_STATE_ENQUEUED))
 		goto out;
 
-	/*
-	 * Remove the timer from the rbtree and replace the first
-	 * entry pointer if necessary.
-	 */
-	if (base->first == &timer->node) {
-		base->first = rb_next(&timer->node);
+	if (&timer->node == timerqueue_getnext(&base->active)) {
 #ifdef CONFIG_HIGH_RES_TIMERS
 		/* Reprogram the clock event device. if enabled */
 		if (reprogram && hrtimer_hres_active()) {
@@ -919,7 +886,7 @@
 		}
 #endif
 	}
-	rb_erase(&timer->node, &base->active);
+	timerqueue_del(&base->active, &timer->node);
 out:
 	timer->state = newstate;
 }
@@ -1128,11 +1095,13 @@
 	if (!hrtimer_hres_active()) {
 		for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
 			struct hrtimer *timer;
+			struct timerqueue_node *next;
 
-			if (!base->first)
+			next = timerqueue_getnext(&base->active);
+			if (!next)
 				continue;
 
-			timer = rb_entry(base->first, struct hrtimer, node);
+			timer = container_of(next, struct hrtimer, node);
 			delta.tv64 = hrtimer_get_expires_tv64(timer);
 			delta = ktime_sub(delta, base->get_time());
 			if (delta.tv64 < mindelta.tv64)
@@ -1162,6 +1131,7 @@
 
 	timer->base = &cpu_base->clock_base[clock_id];
 	hrtimer_init_timer_hres(timer);
+	timerqueue_init(&timer->node);
 
 #ifdef CONFIG_TIMER_STATS
 	timer->start_site = NULL;
@@ -1278,14 +1248,14 @@
 
 	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
 		ktime_t basenow;
-		struct rb_node *node;
+		struct timerqueue_node *node;
 
 		basenow = ktime_add(now, base->offset);
 
-		while ((node = base->first)) {
+		while ((node = timerqueue_getnext(&base->active))) {
 			struct hrtimer *timer;
 
-			timer = rb_entry(node, struct hrtimer, node);
+			timer = container_of(node, struct hrtimer, node);
 
 			/*
 			 * The immediate goal for using the softexpires is
@@ -1441,7 +1411,7 @@
  */
 void hrtimer_run_queues(void)
 {
-	struct rb_node *node;
+	struct timerqueue_node *node;
 	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
 	struct hrtimer_clock_base *base;
 	int index, gettime = 1;
@@ -1451,8 +1421,7 @@
 
 	for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
 		base = &cpu_base->clock_base[index];
-
-		if (!base->first)
+		if (!timerqueue_getnext(&base->active))
 			continue;
 
 		if (gettime) {
@@ -1462,10 +1431,10 @@
 
 		raw_spin_lock(&cpu_base->lock);
 
-		while ((node = base->first)) {
+		while ((node = timerqueue_getnext(&base->active))) {
 			struct hrtimer *timer;
 
-			timer = rb_entry(node, struct hrtimer, node);
+			timer = container_of(node, struct hrtimer, node);
 			if (base->softirq_time.tv64 <=
 					hrtimer_get_expires_tv64(timer))
 				break;
@@ -1630,8 +1599,10 @@
 
 	raw_spin_lock_init(&cpu_base->lock);
 
-	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
 		cpu_base->clock_base[i].cpu_base = cpu_base;
+		timerqueue_init_head(&cpu_base->clock_base[i].active);
+	}
 
 	hrtimer_init_hres(cpu_base);
 }
@@ -1642,10 +1613,10 @@
 				struct hrtimer_clock_base *new_base)
 {
 	struct hrtimer *timer;
-	struct rb_node *node;
+	struct timerqueue_node *node;
 
-	while ((node = rb_first(&old_base->active))) {
-		timer = rb_entry(node, struct hrtimer, node);
+	while ((node = timerqueue_getnext(&old_base->active))) {
+		timer = container_of(node, struct hrtimer, node);
 		BUG_ON(hrtimer_callback_running(timer));
 		debug_deactivate(timer);
 
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index e532582..086adf2 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -641,7 +641,7 @@
 
 	constraints_initialized = 1;
 
-	perf_pmu_register(&perf_breakpoint);
+	perf_pmu_register(&perf_breakpoint, "breakpoint", PERF_TYPE_BREAKPOINT);
 
 	return register_die_notifier(&hw_breakpoint_exceptions_nb);
 
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 5f92acc5..0caa59f 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -577,7 +577,9 @@
  */
 static int irq_thread(void *data)
 {
-	struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, };
+	static const struct sched_param param = {
+		.sched_priority = MAX_USER_RT_PRIO/2,
+	};
 	struct irqaction *action = data;
 	struct irq_desc *desc = irq_to_desc(action->irq);
 	int wake, oneshot = desc->status & IRQ_ONESHOT;
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index 90f8819..c58fa7d 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -77,21 +77,21 @@
  */
 static void __irq_work_queue(struct irq_work *entry)
 {
-	struct irq_work **head, *next;
+	struct irq_work *next;
 
-	head = &get_cpu_var(irq_work_list);
+	preempt_disable();
 
 	do {
-		next = *head;
+		next = __this_cpu_read(irq_work_list);
 		/* Can assign non-atomic because we keep the flags set. */
 		entry->next = next_flags(next, IRQ_WORK_FLAGS);
-	} while (cmpxchg(head, next, entry) != next);
+	} while (this_cpu_cmpxchg(irq_work_list, next, entry) != next);
 
 	/* The list was empty, raise self-interrupt to start processing. */
 	if (!irq_work_next(entry))
 		arch_irq_work_raise();
 
-	put_cpu_var(irq_work_list);
+	preempt_enable();
 }
 
 /*
@@ -120,16 +120,16 @@
  */
 void irq_work_run(void)
 {
-	struct irq_work *list, **head;
+	struct irq_work *list;
 
-	head = &__get_cpu_var(irq_work_list);
-	if (*head == NULL)
+	if (this_cpu_read(irq_work_list) == NULL)
 		return;
 
 	BUG_ON(!in_irq());
 	BUG_ON(!irqs_disabled());
 
-	list = xchg(head, NULL);
+	list = this_cpu_xchg(irq_work_list, NULL);
+
 	while (list != NULL) {
 		struct irq_work *entry = list;
 
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 9737a76..7798181 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -317,12 +317,12 @@
 /* We have preemption disabled.. so it is safe to use __ versions */
 static inline void set_kprobe_instance(struct kprobe *kp)
 {
-	__get_cpu_var(kprobe_instance) = kp;
+	__this_cpu_write(kprobe_instance, kp);
 }
 
 static inline void reset_kprobe_instance(void)
 {
-	__get_cpu_var(kprobe_instance) = NULL;
+	__this_cpu_write(kprobe_instance, NULL);
 }
 
 /*
@@ -354,13 +354,20 @@
 	return p->pre_handler == aggr_pre_handler;
 }
 
+/* Return true(!0) if the kprobe is unused */
+static inline int kprobe_unused(struct kprobe *p)
+{
+	return kprobe_aggrprobe(p) && kprobe_disabled(p) &&
+	       list_empty(&p->list);
+}
+
 /*
  * Keep all fields in the kprobe consistent
  */
-static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
+static inline void copy_kprobe(struct kprobe *ap, struct kprobe *p)
 {
-	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
-	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
+	memcpy(&p->opcode, &ap->opcode, sizeof(kprobe_opcode_t));
+	memcpy(&p->ainsn, &ap->ainsn, sizeof(struct arch_specific_insn));
 }
 
 #ifdef CONFIG_OPTPROBES
@@ -384,6 +391,17 @@
 	}
 }
 
+/* Free optimized instructions and optimized_kprobe */
+static __kprobes void free_aggr_kprobe(struct kprobe *p)
+{
+	struct optimized_kprobe *op;
+
+	op = container_of(p, struct optimized_kprobe, kp);
+	arch_remove_optimized_kprobe(op);
+	arch_remove_kprobe(p);
+	kfree(op);
+}
+
 /* Return true(!0) if the kprobe is ready for optimization. */
 static inline int kprobe_optready(struct kprobe *p)
 {
@@ -397,6 +415,33 @@
 	return 0;
 }
 
+/* Return true(!0) if the kprobe is disarmed. Note: p must be on hash list */
+static inline int kprobe_disarmed(struct kprobe *p)
+{
+	struct optimized_kprobe *op;
+
+	/* If kprobe is not aggr/opt probe, just return kprobe is disabled */
+	if (!kprobe_aggrprobe(p))
+		return kprobe_disabled(p);
+
+	op = container_of(p, struct optimized_kprobe, kp);
+
+	return kprobe_disabled(p) && list_empty(&op->list);
+}
+
+/* Return true(!0) if the probe is queued on (un)optimizing lists */
+static int __kprobes kprobe_queued(struct kprobe *p)
+{
+	struct optimized_kprobe *op;
+
+	if (kprobe_aggrprobe(p)) {
+		op = container_of(p, struct optimized_kprobe, kp);
+		if (!list_empty(&op->list))
+			return 1;
+	}
+	return 0;
+}
+
 /*
  * Return an optimized kprobe whose optimizing code replaces
  * instructions including addr (exclude breakpoint).
@@ -422,30 +467,23 @@
 
 /* Optimization staging list, protected by kprobe_mutex */
 static LIST_HEAD(optimizing_list);
+static LIST_HEAD(unoptimizing_list);
 
 static void kprobe_optimizer(struct work_struct *work);
 static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer);
+static DECLARE_COMPLETION(optimizer_comp);
 #define OPTIMIZE_DELAY 5
 
-/* Kprobe jump optimizer */
-static __kprobes void kprobe_optimizer(struct work_struct *work)
+/*
+ * Optimize (replace a breakpoint with a jump) kprobes listed on
+ * optimizing_list.
+ */
+static __kprobes void do_optimize_kprobes(void)
 {
-	struct optimized_kprobe *op, *tmp;
-
-	/* Lock modules while optimizing kprobes */
-	mutex_lock(&module_mutex);
-	mutex_lock(&kprobe_mutex);
-	if (kprobes_all_disarmed || !kprobes_allow_optimization)
-		goto end;
-
-	/*
-	 * Wait for quiesence period to ensure all running interrupts
-	 * are done. Because optprobe may modify multiple instructions
-	 * there is a chance that Nth instruction is interrupted. In that
-	 * case, running interrupt can return to 2nd-Nth byte of jump
-	 * instruction. This wait is for avoiding it.
-	 */
-	synchronize_sched();
+	/* Optimization never be done when disarmed */
+	if (kprobes_all_disarmed || !kprobes_allow_optimization ||
+	    list_empty(&optimizing_list))
+		return;
 
 	/*
 	 * The optimization/unoptimization refers online_cpus via
@@ -459,17 +497,111 @@
 	 */
 	get_online_cpus();
 	mutex_lock(&text_mutex);
-	list_for_each_entry_safe(op, tmp, &optimizing_list, list) {
-		WARN_ON(kprobe_disabled(&op->kp));
-		if (arch_optimize_kprobe(op) < 0)
-			op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
-		list_del_init(&op->list);
+	arch_optimize_kprobes(&optimizing_list);
+	mutex_unlock(&text_mutex);
+	put_online_cpus();
+}
+
+/*
+ * Unoptimize (replace a jump with a breakpoint and remove the breakpoint
+ * if need) kprobes listed on unoptimizing_list.
+ */
+static __kprobes void do_unoptimize_kprobes(struct list_head *free_list)
+{
+	struct optimized_kprobe *op, *tmp;
+
+	/* Unoptimization must be done anytime */
+	if (list_empty(&unoptimizing_list))
+		return;
+
+	/* Ditto to do_optimize_kprobes */
+	get_online_cpus();
+	mutex_lock(&text_mutex);
+	arch_unoptimize_kprobes(&unoptimizing_list, free_list);
+	/* Loop free_list for disarming */
+	list_for_each_entry_safe(op, tmp, free_list, list) {
+		/* Disarm probes if marked disabled */
+		if (kprobe_disabled(&op->kp))
+			arch_disarm_kprobe(&op->kp);
+		if (kprobe_unused(&op->kp)) {
+			/*
+			 * Remove unused probes from hash list. After waiting
+			 * for synchronization, these probes are reclaimed.
+			 * (reclaiming is done by do_free_cleaned_kprobes.)
+			 */
+			hlist_del_rcu(&op->kp.hlist);
+		} else
+			list_del_init(&op->list);
 	}
 	mutex_unlock(&text_mutex);
 	put_online_cpus();
-end:
+}
+
+/* Reclaim all kprobes on the free_list */
+static __kprobes void do_free_cleaned_kprobes(struct list_head *free_list)
+{
+	struct optimized_kprobe *op, *tmp;
+
+	list_for_each_entry_safe(op, tmp, free_list, list) {
+		BUG_ON(!kprobe_unused(&op->kp));
+		list_del_init(&op->list);
+		free_aggr_kprobe(&op->kp);
+	}
+}
+
+/* Start optimizer after OPTIMIZE_DELAY passed */
+static __kprobes void kick_kprobe_optimizer(void)
+{
+	if (!delayed_work_pending(&optimizing_work))
+		schedule_delayed_work(&optimizing_work, OPTIMIZE_DELAY);
+}
+
+/* Kprobe jump optimizer */
+static __kprobes void kprobe_optimizer(struct work_struct *work)
+{
+	LIST_HEAD(free_list);
+
+	/* Lock modules while optimizing kprobes */
+	mutex_lock(&module_mutex);
+	mutex_lock(&kprobe_mutex);
+
+	/*
+	 * Step 1: Unoptimize kprobes and collect cleaned (unused and disarmed)
+	 * kprobes before waiting for quiesence period.
+	 */
+	do_unoptimize_kprobes(&free_list);
+
+	/*
+	 * Step 2: Wait for quiesence period to ensure all running interrupts
+	 * are done. Because optprobe may modify multiple instructions
+	 * there is a chance that Nth instruction is interrupted. In that
+	 * case, running interrupt can return to 2nd-Nth byte of jump
+	 * instruction. This wait is for avoiding it.
+	 */
+	synchronize_sched();
+
+	/* Step 3: Optimize kprobes after quiesence period */
+	do_optimize_kprobes();
+
+	/* Step 4: Free cleaned kprobes after quiesence period */
+	do_free_cleaned_kprobes(&free_list);
+
 	mutex_unlock(&kprobe_mutex);
 	mutex_unlock(&module_mutex);
+
+	/* Step 5: Kick optimizer again if needed */
+	if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list))
+		kick_kprobe_optimizer();
+	else
+		/* Wake up all waiters */
+		complete_all(&optimizer_comp);
+}
+
+/* Wait for completing optimization and unoptimization */
+static __kprobes void wait_for_kprobe_optimizer(void)
+{
+	if (delayed_work_pending(&optimizing_work))
+		wait_for_completion(&optimizer_comp);
 }
 
 /* Optimize kprobe if p is ready to be optimized */
@@ -495,28 +627,85 @@
 	/* Check if it is already optimized. */
 	if (op->kp.flags & KPROBE_FLAG_OPTIMIZED)
 		return;
-
 	op->kp.flags |= KPROBE_FLAG_OPTIMIZED;
-	list_add(&op->list, &optimizing_list);
-	if (!delayed_work_pending(&optimizing_work))
-		schedule_delayed_work(&optimizing_work, OPTIMIZE_DELAY);
+
+	if (!list_empty(&op->list))
+		/* This is under unoptimizing. Just dequeue the probe */
+		list_del_init(&op->list);
+	else {
+		list_add(&op->list, &optimizing_list);
+		kick_kprobe_optimizer();
+	}
+}
+
+/* Short cut to direct unoptimizing */
+static __kprobes void force_unoptimize_kprobe(struct optimized_kprobe *op)
+{
+	get_online_cpus();
+	arch_unoptimize_kprobe(op);
+	put_online_cpus();
+	if (kprobe_disabled(&op->kp))
+		arch_disarm_kprobe(&op->kp);
 }
 
 /* Unoptimize a kprobe if p is optimized */
-static __kprobes void unoptimize_kprobe(struct kprobe *p)
+static __kprobes void unoptimize_kprobe(struct kprobe *p, bool force)
 {
 	struct optimized_kprobe *op;
 
-	if ((p->flags & KPROBE_FLAG_OPTIMIZED) && kprobe_aggrprobe(p)) {
-		op = container_of(p, struct optimized_kprobe, kp);
-		if (!list_empty(&op->list))
-			/* Dequeue from the optimization queue */
+	if (!kprobe_aggrprobe(p) || kprobe_disarmed(p))
+		return; /* This is not an optprobe nor optimized */
+
+	op = container_of(p, struct optimized_kprobe, kp);
+	if (!kprobe_optimized(p)) {
+		/* Unoptimized or unoptimizing case */
+		if (force && !list_empty(&op->list)) {
+			/*
+			 * Only if this is unoptimizing kprobe and forced,
+			 * forcibly unoptimize it. (No need to unoptimize
+			 * unoptimized kprobe again :)
+			 */
 			list_del_init(&op->list);
-		else
-			/* Replace jump with break */
-			arch_unoptimize_kprobe(op);
-		op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
+			force_unoptimize_kprobe(op);
+		}
+		return;
 	}
+
+	op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
+	if (!list_empty(&op->list)) {
+		/* Dequeue from the optimization queue */
+		list_del_init(&op->list);
+		return;
+	}
+	/* Optimized kprobe case */
+	if (force)
+		/* Forcibly update the code: this is a special case */
+		force_unoptimize_kprobe(op);
+	else {
+		list_add(&op->list, &unoptimizing_list);
+		kick_kprobe_optimizer();
+	}
+}
+
+/* Cancel unoptimizing for reusing */
+static void reuse_unused_kprobe(struct kprobe *ap)
+{
+	struct optimized_kprobe *op;
+
+	BUG_ON(!kprobe_unused(ap));
+	/*
+	 * Unused kprobe MUST be on the way of delayed unoptimizing (means
+	 * there is still a relative jump) and disabled.
+	 */
+	op = container_of(ap, struct optimized_kprobe, kp);
+	if (unlikely(list_empty(&op->list)))
+		printk(KERN_WARNING "Warning: found a stray unused "
+			"aggrprobe@%p\n", ap->addr);
+	/* Enable the probe again */
+	ap->flags &= ~KPROBE_FLAG_DISABLED;
+	/* Optimize it again (remove from op->list) */
+	BUG_ON(!kprobe_optready(ap));
+	optimize_kprobe(ap);
 }
 
 /* Remove optimized instructions */
@@ -525,12 +714,12 @@
 	struct optimized_kprobe *op;
 
 	op = container_of(p, struct optimized_kprobe, kp);
-	if (!list_empty(&op->list)) {
-		/* Dequeue from the optimization queue */
+	if (!list_empty(&op->list))
+		/* Dequeue from the (un)optimization queue */
 		list_del_init(&op->list);
-		op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
-	}
-	/* Don't unoptimize, because the target code will be freed. */
+
+	op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
+	/* Don't touch the code, because it is already freed. */
 	arch_remove_optimized_kprobe(op);
 }
 
@@ -543,16 +732,6 @@
 	arch_prepare_optimized_kprobe(op);
 }
 
-/* Free optimized instructions and optimized_kprobe */
-static __kprobes void free_aggr_kprobe(struct kprobe *p)
-{
-	struct optimized_kprobe *op;
-
-	op = container_of(p, struct optimized_kprobe, kp);
-	arch_remove_optimized_kprobe(op);
-	kfree(op);
-}
-
 /* Allocate new optimized_kprobe and try to prepare optimized instructions */
 static __kprobes struct kprobe *alloc_aggr_kprobe(struct kprobe *p)
 {
@@ -587,7 +766,8 @@
 	op = container_of(ap, struct optimized_kprobe, kp);
 	if (!arch_prepared_optinsn(&op->optinsn)) {
 		/* If failed to setup optimizing, fallback to kprobe */
-		free_aggr_kprobe(ap);
+		arch_remove_optimized_kprobe(op);
+		kfree(op);
 		return;
 	}
 
@@ -631,21 +811,16 @@
 		return;
 
 	kprobes_allow_optimization = false;
-	printk(KERN_INFO "Kprobes globally unoptimized\n");
-	get_online_cpus();	/* For avoiding text_mutex deadlock */
-	mutex_lock(&text_mutex);
 	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
 		head = &kprobe_table[i];
 		hlist_for_each_entry_rcu(p, node, head, hlist) {
 			if (!kprobe_disabled(p))
-				unoptimize_kprobe(p);
+				unoptimize_kprobe(p, false);
 		}
 	}
-
-	mutex_unlock(&text_mutex);
-	put_online_cpus();
-	/* Allow all currently running kprobes to complete */
-	synchronize_sched();
+	/* Wait for unoptimizing completion */
+	wait_for_kprobe_optimizer();
+	printk(KERN_INFO "Kprobes globally unoptimized\n");
 }
 
 int sysctl_kprobes_optimization;
@@ -669,44 +844,60 @@
 }
 #endif /* CONFIG_SYSCTL */
 
+/* Put a breakpoint for a probe. Must be called with text_mutex locked */
 static void __kprobes __arm_kprobe(struct kprobe *p)
 {
-	struct kprobe *old_p;
+	struct kprobe *_p;
 
 	/* Check collision with other optimized kprobes */
-	old_p = get_optimized_kprobe((unsigned long)p->addr);
-	if (unlikely(old_p))
-		unoptimize_kprobe(old_p); /* Fallback to unoptimized kprobe */
+	_p = get_optimized_kprobe((unsigned long)p->addr);
+	if (unlikely(_p))
+		/* Fallback to unoptimized kprobe */
+		unoptimize_kprobe(_p, true);
 
 	arch_arm_kprobe(p);
 	optimize_kprobe(p);	/* Try to optimize (add kprobe to a list) */
 }
 
-static void __kprobes __disarm_kprobe(struct kprobe *p)
+/* Remove the breakpoint of a probe. Must be called with text_mutex locked */
+static void __kprobes __disarm_kprobe(struct kprobe *p, bool reopt)
 {
-	struct kprobe *old_p;
+	struct kprobe *_p;
 
-	unoptimize_kprobe(p);	/* Try to unoptimize */
-	arch_disarm_kprobe(p);
+	unoptimize_kprobe(p, false);	/* Try to unoptimize */
 
-	/* If another kprobe was blocked, optimize it. */
-	old_p = get_optimized_kprobe((unsigned long)p->addr);
-	if (unlikely(old_p))
-		optimize_kprobe(old_p);
+	if (!kprobe_queued(p)) {
+		arch_disarm_kprobe(p);
+		/* If another kprobe was blocked, optimize it. */
+		_p = get_optimized_kprobe((unsigned long)p->addr);
+		if (unlikely(_p) && reopt)
+			optimize_kprobe(_p);
+	}
+	/* TODO: reoptimize others after unoptimized this probe */
 }
 
 #else /* !CONFIG_OPTPROBES */
 
 #define optimize_kprobe(p)			do {} while (0)
-#define unoptimize_kprobe(p)			do {} while (0)
+#define unoptimize_kprobe(p, f)			do {} while (0)
 #define kill_optimized_kprobe(p)		do {} while (0)
 #define prepare_optimized_kprobe(p)		do {} while (0)
 #define try_to_optimize_kprobe(p)		do {} while (0)
 #define __arm_kprobe(p)				arch_arm_kprobe(p)
-#define __disarm_kprobe(p)			arch_disarm_kprobe(p)
+#define __disarm_kprobe(p, o)			arch_disarm_kprobe(p)
+#define kprobe_disarmed(p)			kprobe_disabled(p)
+#define wait_for_kprobe_optimizer()		do {} while (0)
+
+/* There should be no unused kprobes can be reused without optimization */
+static void reuse_unused_kprobe(struct kprobe *ap)
+{
+	printk(KERN_ERR "Error: There should be no unused kprobe here.\n");
+	BUG_ON(kprobe_unused(ap));
+}
 
 static __kprobes void free_aggr_kprobe(struct kprobe *p)
 {
+	arch_remove_kprobe(p);
 	kfree(p);
 }
 
@@ -732,11 +923,10 @@
 /* Disarm a kprobe with text_mutex */
 static void __kprobes disarm_kprobe(struct kprobe *kp)
 {
-	get_online_cpus();	/* For avoiding text_mutex deadlock */
+	/* Ditto */
 	mutex_lock(&text_mutex);
-	__disarm_kprobe(kp);
+	__disarm_kprobe(kp, true);
 	mutex_unlock(&text_mutex);
-	put_online_cpus();
 }
 
 /*
@@ -775,7 +965,7 @@
 static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
 					int trapnr)
 {
-	struct kprobe *cur = __get_cpu_var(kprobe_instance);
+	struct kprobe *cur = __this_cpu_read(kprobe_instance);
 
 	/*
 	 * if we faulted "during" the execution of a user specified
@@ -790,7 +980,7 @@
 
 static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
-	struct kprobe *cur = __get_cpu_var(kprobe_instance);
+	struct kprobe *cur = __this_cpu_read(kprobe_instance);
 	int ret = 0;
 
 	if (cur && cur->break_handler) {
@@ -942,7 +1132,7 @@
 	BUG_ON(kprobe_gone(ap) || kprobe_gone(p));
 
 	if (p->break_handler || p->post_handler)
-		unoptimize_kprobe(ap);	/* Fall back to normal kprobe */
+		unoptimize_kprobe(ap, true);	/* Fall back to normal kprobe */
 
 	if (p->break_handler) {
 		if (ap->break_handler)
@@ -993,19 +1183,21 @@
  * This is the second or subsequent kprobe at the address - handle
  * the intricacies
  */
-static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
+static int __kprobes register_aggr_kprobe(struct kprobe *orig_p,
 					  struct kprobe *p)
 {
 	int ret = 0;
-	struct kprobe *ap = old_p;
+	struct kprobe *ap = orig_p;
 
-	if (!kprobe_aggrprobe(old_p)) {
-		/* If old_p is not an aggr_kprobe, create new aggr_kprobe. */
-		ap = alloc_aggr_kprobe(old_p);
+	if (!kprobe_aggrprobe(orig_p)) {
+		/* If orig_p is not an aggr_kprobe, create new aggr_kprobe. */
+		ap = alloc_aggr_kprobe(orig_p);
 		if (!ap)
 			return -ENOMEM;
-		init_aggr_kprobe(ap, old_p);
-	}
+		init_aggr_kprobe(ap, orig_p);
+	} else if (kprobe_unused(ap))
+		/* This probe is going to die. Rescue it */
+		reuse_unused_kprobe(ap);
 
 	if (kprobe_gone(ap)) {
 		/*
@@ -1039,23 +1231,6 @@
 	return add_new_kprobe(ap, p);
 }
 
-/* Try to disable aggr_kprobe, and return 1 if succeeded.*/
-static int __kprobes try_to_disable_aggr_kprobe(struct kprobe *p)
-{
-	struct kprobe *kp;
-
-	list_for_each_entry_rcu(kp, &p->list, list) {
-		if (!kprobe_disabled(kp))
-			/*
-			 * There is an active probe on the list.
-			 * We can't disable aggr_kprobe.
-			 */
-			return 0;
-	}
-	p->flags |= KPROBE_FLAG_DISABLED;
-	return 1;
-}
-
 static int __kprobes in_kprobes_functions(unsigned long addr)
 {
 	struct kprobe_blackpoint *kb;
@@ -1098,34 +1273,33 @@
 /* Check passed kprobe is valid and return kprobe in kprobe_table. */
 static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
 {
-	struct kprobe *old_p, *list_p;
+	struct kprobe *ap, *list_p;
 
-	old_p = get_kprobe(p->addr);
-	if (unlikely(!old_p))
+	ap = get_kprobe(p->addr);
+	if (unlikely(!ap))
 		return NULL;
 
-	if (p != old_p) {
-		list_for_each_entry_rcu(list_p, &old_p->list, list)
+	if (p != ap) {
+		list_for_each_entry_rcu(list_p, &ap->list, list)
 			if (list_p == p)
 			/* kprobe p is a valid probe */
 				goto valid;
 		return NULL;
 	}
 valid:
-	return old_p;
+	return ap;
 }
 
 /* Return error if the kprobe is being re-registered */
 static inline int check_kprobe_rereg(struct kprobe *p)
 {
 	int ret = 0;
-	struct kprobe *old_p;
 
 	mutex_lock(&kprobe_mutex);
-	old_p = __get_valid_kprobe(p);
-	if (old_p)
+	if (__get_valid_kprobe(p))
 		ret = -EINVAL;
 	mutex_unlock(&kprobe_mutex);
+
 	return ret;
 }
 
@@ -1229,67 +1403,121 @@
 }
 EXPORT_SYMBOL_GPL(register_kprobe);
 
+/* Check if all probes on the aggrprobe are disabled */
+static int __kprobes aggr_kprobe_disabled(struct kprobe *ap)
+{
+	struct kprobe *kp;
+
+	list_for_each_entry_rcu(kp, &ap->list, list)
+		if (!kprobe_disabled(kp))
+			/*
+			 * There is an active probe on the list.
+			 * We can't disable this ap.
+			 */
+			return 0;
+
+	return 1;
+}
+
+/* Disable one kprobe: Make sure called under kprobe_mutex is locked */
+static struct kprobe *__kprobes __disable_kprobe(struct kprobe *p)
+{
+	struct kprobe *orig_p;
+
+	/* Get an original kprobe for return */
+	orig_p = __get_valid_kprobe(p);
+	if (unlikely(orig_p == NULL))
+		return NULL;
+
+	if (!kprobe_disabled(p)) {
+		/* Disable probe if it is a child probe */
+		if (p != orig_p)
+			p->flags |= KPROBE_FLAG_DISABLED;
+
+		/* Try to disarm and disable this/parent probe */
+		if (p == orig_p || aggr_kprobe_disabled(orig_p)) {
+			disarm_kprobe(orig_p);
+			orig_p->flags |= KPROBE_FLAG_DISABLED;
+		}
+	}
+
+	return orig_p;
+}
+
 /*
  * Unregister a kprobe without a scheduler synchronization.
  */
 static int __kprobes __unregister_kprobe_top(struct kprobe *p)
 {
-	struct kprobe *old_p, *list_p;
+	struct kprobe *ap, *list_p;
 
-	old_p = __get_valid_kprobe(p);
-	if (old_p == NULL)
+	/* Disable kprobe. This will disarm it if needed. */
+	ap = __disable_kprobe(p);
+	if (ap == NULL)
 		return -EINVAL;
 
-	if (old_p == p ||
-	    (kprobe_aggrprobe(old_p) &&
-	     list_is_singular(&old_p->list))) {
+	if (ap == p)
 		/*
-		 * Only probe on the hash list. Disarm only if kprobes are
-		 * enabled and not gone - otherwise, the breakpoint would
-		 * already have been removed. We save on flushing icache.
+		 * This probe is an independent(and non-optimized) kprobe
+		 * (not an aggrprobe). Remove from the hash list.
 		 */
-		if (!kprobes_all_disarmed && !kprobe_disabled(old_p))
-			disarm_kprobe(old_p);
-		hlist_del_rcu(&old_p->hlist);
-	} else {
+		goto disarmed;
+
+	/* Following process expects this probe is an aggrprobe */
+	WARN_ON(!kprobe_aggrprobe(ap));
+
+	if (list_is_singular(&ap->list) && kprobe_disarmed(ap))
+		/*
+		 * !disarmed could be happen if the probe is under delayed
+		 * unoptimizing.
+		 */
+		goto disarmed;
+	else {
+		/* If disabling probe has special handlers, update aggrprobe */
 		if (p->break_handler && !kprobe_gone(p))
-			old_p->break_handler = NULL;
+			ap->break_handler = NULL;
 		if (p->post_handler && !kprobe_gone(p)) {
-			list_for_each_entry_rcu(list_p, &old_p->list, list) {
+			list_for_each_entry_rcu(list_p, &ap->list, list) {
 				if ((list_p != p) && (list_p->post_handler))
 					goto noclean;
 			}
-			old_p->post_handler = NULL;
+			ap->post_handler = NULL;
 		}
 noclean:
+		/*
+		 * Remove from the aggrprobe: this path will do nothing in
+		 * __unregister_kprobe_bottom().
+		 */
 		list_del_rcu(&p->list);
-		if (!kprobe_disabled(old_p)) {
-			try_to_disable_aggr_kprobe(old_p);
-			if (!kprobes_all_disarmed) {
-				if (kprobe_disabled(old_p))
-					disarm_kprobe(old_p);
-				else
-					/* Try to optimize this probe again */
-					optimize_kprobe(old_p);
-			}
-		}
+		if (!kprobe_disabled(ap) && !kprobes_all_disarmed)
+			/*
+			 * Try to optimize this probe again, because post
+			 * handler may have been changed.
+			 */
+			optimize_kprobe(ap);
 	}
 	return 0;
+
+disarmed:
+	BUG_ON(!kprobe_disarmed(ap));
+	hlist_del_rcu(&ap->hlist);
+	return 0;
 }
 
 static void __kprobes __unregister_kprobe_bottom(struct kprobe *p)
 {
-	struct kprobe *old_p;
+	struct kprobe *ap;
 
 	if (list_empty(&p->list))
+		/* This is an independent kprobe */
 		arch_remove_kprobe(p);
 	else if (list_is_singular(&p->list)) {
-		/* "p" is the last child of an aggr_kprobe */
-		old_p = list_entry(p->list.next, struct kprobe, list);
+		/* This is the last child of an aggrprobe */
+		ap = list_entry(p->list.next, struct kprobe, list);
 		list_del(&p->list);
-		arch_remove_kprobe(old_p);
-		free_aggr_kprobe(old_p);
+		free_aggr_kprobe(ap);
 	}
+	/* Otherwise, do nothing. */
 }
 
 int __kprobes register_kprobes(struct kprobe **kps, int num)
@@ -1607,29 +1835,13 @@
 int __kprobes disable_kprobe(struct kprobe *kp)
 {
 	int ret = 0;
-	struct kprobe *p;
 
 	mutex_lock(&kprobe_mutex);
 
-	/* Check whether specified probe is valid. */
-	p = __get_valid_kprobe(kp);
-	if (unlikely(p == NULL)) {
+	/* Disable this kprobe */
+	if (__disable_kprobe(kp) == NULL)
 		ret = -EINVAL;
-		goto out;
-	}
 
-	/* If the probe is already disabled (or gone), just return */
-	if (kprobe_disabled(kp))
-		goto out;
-
-	kp->flags |= KPROBE_FLAG_DISABLED;
-	if (p != kp)
-		/* When kp != p, p is always enabled. */
-		try_to_disable_aggr_kprobe(p);
-
-	if (!kprobes_all_disarmed && kprobe_disabled(p))
-		disarm_kprobe(p);
-out:
 	mutex_unlock(&kprobe_mutex);
 	return ret;
 }
@@ -1927,36 +2139,27 @@
 	mutex_lock(&kprobe_mutex);
 
 	/* If kprobes are already disarmed, just return */
-	if (kprobes_all_disarmed)
-		goto already_disabled;
+	if (kprobes_all_disarmed) {
+		mutex_unlock(&kprobe_mutex);
+		return;
+	}
 
 	kprobes_all_disarmed = true;
 	printk(KERN_INFO "Kprobes globally disabled\n");
 
-	/*
-	 * Here we call get_online_cpus() for avoiding text_mutex deadlock,
-	 * because disarming may also unoptimize kprobes.
-	 */
-	get_online_cpus();
 	mutex_lock(&text_mutex);
 	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
 		head = &kprobe_table[i];
 		hlist_for_each_entry_rcu(p, node, head, hlist) {
 			if (!arch_trampoline_kprobe(p) && !kprobe_disabled(p))
-				__disarm_kprobe(p);
+				__disarm_kprobe(p, false);
 		}
 	}
-
 	mutex_unlock(&text_mutex);
-	put_online_cpus();
 	mutex_unlock(&kprobe_mutex);
-	/* Allow all currently running kprobes to complete */
-	synchronize_sched();
-	return;
 
-already_disabled:
-	mutex_unlock(&kprobe_mutex);
-	return;
+	/* Wait for disarming all kprobes by optimizer */
+	wait_for_kprobe_optimizer();
 }
 
 /*
diff --git a/kernel/kthread.c b/kernel/kthread.c
index ca61bbd..c55afba 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -148,7 +148,7 @@
 	wait_for_completion(&create.done);
 
 	if (!IS_ERR(create.result)) {
-		struct sched_param param = { .sched_priority = 0 };
+		static const struct sched_param param = { .sched_priority = 0 };
 		va_list args;
 
 		va_start(args, namefmt);
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index 59b76c8..1969d2f 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -494,7 +494,6 @@
 		namelen += 2;
 
 	for (i = 0; i < LOCKSTAT_POINTS; i++) {
-		char sym[KSYM_SYMBOL_LEN];
 		char ip[32];
 
 		if (class->contention_point[i] == 0)
@@ -503,15 +502,13 @@
 		if (!i)
 			seq_line(m, '-', 40-namelen, namelen);
 
-		sprint_symbol(sym, class->contention_point[i]);
 		snprintf(ip, sizeof(ip), "[<%p>]",
 				(void *)class->contention_point[i]);
-		seq_printf(m, "%40s %14lu %29s %s\n", name,
-				stats->contention_point[i],
-				ip, sym);
+		seq_printf(m, "%40s %14lu %29s %pS\n",
+			   name, stats->contention_point[i],
+			   ip, (void *)class->contention_point[i]);
 	}
 	for (i = 0; i < LOCKSTAT_POINTS; i++) {
-		char sym[KSYM_SYMBOL_LEN];
 		char ip[32];
 
 		if (class->contending_point[i] == 0)
@@ -520,12 +517,11 @@
 		if (!i)
 			seq_line(m, '-', 40-namelen, namelen);
 
-		sprint_symbol(sym, class->contending_point[i]);
 		snprintf(ip, sizeof(ip), "[<%p>]",
 				(void *)class->contending_point[i]);
-		seq_printf(m, "%40s %14lu %29s %s\n", name,
-				stats->contending_point[i],
-				ip, sym);
+		seq_printf(m, "%40s %14lu %29s %pS\n",
+			   name, stats->contending_point[i],
+			   ip, (void *)class->contending_point[i]);
 	}
 	if (i) {
 		seq_puts(m, "\n");
diff --git a/kernel/module.c b/kernel/module.c
index d190664..34e00b7 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -56,6 +56,7 @@
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
 #include <linux/jump_label.h>
+#include <linux/pfn.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -70,6 +71,26 @@
 #define ARCH_SHF_SMALL 0
 #endif
 
+/*
+ * Modules' sections will be aligned on page boundaries
+ * to ensure complete separation of code and data, but
+ * only when CONFIG_DEBUG_SET_MODULE_RONX=y
+ */
+#ifdef CONFIG_DEBUG_SET_MODULE_RONX
+# define debug_align(X) ALIGN(X, PAGE_SIZE)
+#else
+# define debug_align(X) (X)
+#endif
+
+/*
+ * Given BASE and SIZE this macro calculates the number of pages the
+ * memory regions occupies
+ */
+#define MOD_NUMBER_OF_PAGES(BASE, SIZE) (((SIZE) > 0) ?		\
+		(PFN_DOWN((unsigned long)(BASE) + (SIZE) - 1) -	\
+			 PFN_DOWN((unsigned long)BASE) + 1)	\
+		: (0UL))
+
 /* If this is set, the section belongs in the init part of the module */
 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
 
@@ -1542,6 +1563,115 @@
 	return 0;
 }
 
+#ifdef CONFIG_DEBUG_SET_MODULE_RONX
+/*
+ * LKM RO/NX protection: protect module's text/ro-data
+ * from modification and any data from execution.
+ */
+void set_page_attributes(void *start, void *end, int (*set)(unsigned long start, int num_pages))
+{
+	unsigned long begin_pfn = PFN_DOWN((unsigned long)start);
+	unsigned long end_pfn = PFN_DOWN((unsigned long)end);
+
+	if (end_pfn > begin_pfn)
+		set(begin_pfn << PAGE_SHIFT, end_pfn - begin_pfn);
+}
+
+static void set_section_ro_nx(void *base,
+			unsigned long text_size,
+			unsigned long ro_size,
+			unsigned long total_size)
+{
+	/* begin and end PFNs of the current subsection */
+	unsigned long begin_pfn;
+	unsigned long end_pfn;
+
+	/*
+	 * Set RO for module text and RO-data:
+	 * - Always protect first page.
+	 * - Do not protect last partial page.
+	 */
+	if (ro_size > 0)
+		set_page_attributes(base, base + ro_size, set_memory_ro);
+
+	/*
+	 * Set NX permissions for module data:
+	 * - Do not protect first partial page.
+	 * - Always protect last page.
+	 */
+	if (total_size > text_size) {
+		begin_pfn = PFN_UP((unsigned long)base + text_size);
+		end_pfn = PFN_UP((unsigned long)base + total_size);
+		if (end_pfn > begin_pfn)
+			set_memory_nx(begin_pfn << PAGE_SHIFT, end_pfn - begin_pfn);
+	}
+}
+
+/* Setting memory back to RW+NX before releasing it */
+void unset_section_ro_nx(struct module *mod, void *module_region)
+{
+	unsigned long total_pages;
+
+	if (mod->module_core == module_region) {
+		/* Set core as NX+RW */
+		total_pages = MOD_NUMBER_OF_PAGES(mod->module_core, mod->core_size);
+		set_memory_nx((unsigned long)mod->module_core, total_pages);
+		set_memory_rw((unsigned long)mod->module_core, total_pages);
+
+	} else if (mod->module_init == module_region) {
+		/* Set init as NX+RW */
+		total_pages = MOD_NUMBER_OF_PAGES(mod->module_init, mod->init_size);
+		set_memory_nx((unsigned long)mod->module_init, total_pages);
+		set_memory_rw((unsigned long)mod->module_init, total_pages);
+	}
+}
+
+/* Iterate through all modules and set each module's text as RW */
+void set_all_modules_text_rw()
+{
+	struct module *mod;
+
+	mutex_lock(&module_mutex);
+	list_for_each_entry_rcu(mod, &modules, list) {
+		if ((mod->module_core) && (mod->core_text_size)) {
+			set_page_attributes(mod->module_core,
+						mod->module_core + mod->core_text_size,
+						set_memory_rw);
+		}
+		if ((mod->module_init) && (mod->init_text_size)) {
+			set_page_attributes(mod->module_init,
+						mod->module_init + mod->init_text_size,
+						set_memory_rw);
+		}
+	}
+	mutex_unlock(&module_mutex);
+}
+
+/* Iterate through all modules and set each module's text as RO */
+void set_all_modules_text_ro()
+{
+	struct module *mod;
+
+	mutex_lock(&module_mutex);
+	list_for_each_entry_rcu(mod, &modules, list) {
+		if ((mod->module_core) && (mod->core_text_size)) {
+			set_page_attributes(mod->module_core,
+						mod->module_core + mod->core_text_size,
+						set_memory_ro);
+		}
+		if ((mod->module_init) && (mod->init_text_size)) {
+			set_page_attributes(mod->module_init,
+						mod->module_init + mod->init_text_size,
+						set_memory_ro);
+		}
+	}
+	mutex_unlock(&module_mutex);
+}
+#else
+static inline void set_section_ro_nx(void *base, unsigned long text_size, unsigned long ro_size, unsigned long total_size) { }
+static inline void unset_section_ro_nx(struct module *mod, void *module_region) { }
+#endif
+
 /* Free a module, remove from lists, etc. */
 static void free_module(struct module *mod)
 {
@@ -1566,6 +1696,7 @@
 	destroy_params(mod->kp, mod->num_kp);
 
 	/* This may be NULL, but that's OK */
+	unset_section_ro_nx(mod, mod->module_init);
 	module_free(mod, mod->module_init);
 	kfree(mod->args);
 	percpu_modfree(mod);
@@ -1574,6 +1705,7 @@
 	lockdep_free_key_range(mod->module_core, mod->core_size);
 
 	/* Finally, free the core (containing the module structure) */
+	unset_section_ro_nx(mod, mod->module_core);
 	module_free(mod, mod->module_core);
 
 #ifdef CONFIG_MPU
@@ -1777,8 +1909,19 @@
 			s->sh_entsize = get_offset(mod, &mod->core_size, s, i);
 			DEBUGP("\t%s\n", name);
 		}
-		if (m == 0)
+		switch (m) {
+		case 0: /* executable */
+			mod->core_size = debug_align(mod->core_size);
 			mod->core_text_size = mod->core_size;
+			break;
+		case 1: /* RO: text and ro-data */
+			mod->core_size = debug_align(mod->core_size);
+			mod->core_ro_size = mod->core_size;
+			break;
+		case 3: /* whole core */
+			mod->core_size = debug_align(mod->core_size);
+			break;
+		}
 	}
 
 	DEBUGP("Init section allocation order:\n");
@@ -1796,8 +1939,19 @@
 					 | INIT_OFFSET_MASK);
 			DEBUGP("\t%s\n", sname);
 		}
-		if (m == 0)
+		switch (m) {
+		case 0: /* executable */
+			mod->init_size = debug_align(mod->init_size);
 			mod->init_text_size = mod->init_size;
+			break;
+		case 1: /* RO: text and ro-data */
+			mod->init_size = debug_align(mod->init_size);
+			mod->init_ro_size = mod->init_size;
+			break;
+		case 3: /* whole init */
+			mod->init_size = debug_align(mod->init_size);
+			break;
+		}
 	}
 }
 
@@ -2722,6 +2876,18 @@
 	blocking_notifier_call_chain(&module_notify_list,
 			MODULE_STATE_COMING, mod);
 
+	/* Set RO and NX regions for core */
+	set_section_ro_nx(mod->module_core,
+				mod->core_text_size,
+				mod->core_ro_size,
+				mod->core_size);
+
+	/* Set RO and NX regions for init */
+	set_section_ro_nx(mod->module_init,
+				mod->init_text_size,
+				mod->init_ro_size,
+				mod->init_size);
+
 	do_mod_ctors(mod);
 	/* Start the module */
 	if (mod->init != NULL)
@@ -2765,6 +2931,7 @@
 	mod->symtab = mod->core_symtab;
 	mod->strtab = mod->core_strtab;
 #endif
+	unset_section_ro_nx(mod, mod->module_init);
 	module_free(mod, mod->module_init);
 	mod->module_init = NULL;
 	mod->init_size = 0;
diff --git a/kernel/mutex.c b/kernel/mutex.c
index 200407c..a5889fb 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -199,7 +199,7 @@
 		 * memory barriers as we'll eventually observe the right
 		 * values at the cost of a few extra spins.
 		 */
-		cpu_relax();
+		arch_mutex_cpu_relax();
 	}
 #endif
 	spin_lock_mutex(&lock->wait_lock, flags);
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 2870fee..11847bf 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
+#include <linux/idr.h>
 #include <linux/file.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -21,7 +22,9 @@
 #include <linux/dcache.h>
 #include <linux/percpu.h>
 #include <linux/ptrace.h>
+#include <linux/reboot.h>
 #include <linux/vmstat.h>
+#include <linux/device.h>
 #include <linux/vmalloc.h>
 #include <linux/hardirq.h>
 #include <linux/rculist.h>
@@ -133,6 +136,28 @@
 	}
 }
 
+static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
+{
+	/*
+	 * only top level events have the pid namespace they were created in
+	 */
+	if (event->parent)
+		event = event->parent;
+
+	return task_tgid_nr_ns(p, event->ns);
+}
+
+static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
+{
+	/*
+	 * only top level events have the pid namespace they were created in
+	 */
+	if (event->parent)
+		event = event->parent;
+
+	return task_pid_nr_ns(p, event->ns);
+}
+
 /*
  * If we inherit events we want to return the parent event id
  * to userspace.
@@ -312,9 +337,84 @@
 		ctx->nr_stat++;
 }
 
+/*
+ * Called at perf_event creation and when events are attached/detached from a
+ * group.
+ */
+static void perf_event__read_size(struct perf_event *event)
+{
+	int entry = sizeof(u64); /* value */
+	int size = 0;
+	int nr = 1;
+
+	if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
+		size += sizeof(u64);
+
+	if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+		size += sizeof(u64);
+
+	if (event->attr.read_format & PERF_FORMAT_ID)
+		entry += sizeof(u64);
+
+	if (event->attr.read_format & PERF_FORMAT_GROUP) {
+		nr += event->group_leader->nr_siblings;
+		size += sizeof(u64);
+	}
+
+	size += entry * nr;
+	event->read_size = size;
+}
+
+static void perf_event__header_size(struct perf_event *event)
+{
+	struct perf_sample_data *data;
+	u64 sample_type = event->attr.sample_type;
+	u16 size = 0;
+
+	perf_event__read_size(event);
+
+	if (sample_type & PERF_SAMPLE_IP)
+		size += sizeof(data->ip);
+
+	if (sample_type & PERF_SAMPLE_ADDR)
+		size += sizeof(data->addr);
+
+	if (sample_type & PERF_SAMPLE_PERIOD)
+		size += sizeof(data->period);
+
+	if (sample_type & PERF_SAMPLE_READ)
+		size += event->read_size;
+
+	event->header_size = size;
+}
+
+static void perf_event__id_header_size(struct perf_event *event)
+{
+	struct perf_sample_data *data;
+	u64 sample_type = event->attr.sample_type;
+	u16 size = 0;
+
+	if (sample_type & PERF_SAMPLE_TID)
+		size += sizeof(data->tid_entry);
+
+	if (sample_type & PERF_SAMPLE_TIME)
+		size += sizeof(data->time);
+
+	if (sample_type & PERF_SAMPLE_ID)
+		size += sizeof(data->id);
+
+	if (sample_type & PERF_SAMPLE_STREAM_ID)
+		size += sizeof(data->stream_id);
+
+	if (sample_type & PERF_SAMPLE_CPU)
+		size += sizeof(data->cpu_entry);
+
+	event->id_header_size = size;
+}
+
 static void perf_group_attach(struct perf_event *event)
 {
-	struct perf_event *group_leader = event->group_leader;
+	struct perf_event *group_leader = event->group_leader, *pos;
 
 	/*
 	 * We can have double attach due to group movement in perf_event_open.
@@ -333,6 +433,11 @@
 
 	list_add_tail(&event->group_entry, &group_leader->sibling_list);
 	group_leader->nr_siblings++;
+
+	perf_event__header_size(group_leader);
+
+	list_for_each_entry(pos, &group_leader->sibling_list, group_entry)
+		perf_event__header_size(pos);
 }
 
 /*
@@ -391,7 +496,7 @@
 	if (event->group_leader != event) {
 		list_del_init(&event->group_entry);
 		event->group_leader->nr_siblings--;
-		return;
+		goto out;
 	}
 
 	if (!list_empty(&event->group_entry))
@@ -410,6 +515,12 @@
 		/* Inherit group flags from the previous leader */
 		sibling->group_flags = event->group_flags;
 	}
+
+out:
+	perf_event__header_size(event->group_leader);
+
+	list_for_each_entry(tmp, &event->group_leader->sibling_list, group_entry)
+		perf_event__header_size(tmp);
 }
 
 static inline int
@@ -1073,7 +1184,7 @@
 	/*
 	 * not supported on inherited events
 	 */
-	if (event->attr.inherit)
+	if (event->attr.inherit || !is_sampling_event(event))
 		return -EINVAL;
 
 	atomic_add(refresh, &event->event_limit);
@@ -2289,31 +2400,6 @@
 	return perf_event_release_kernel(event);
 }
 
-static int perf_event_read_size(struct perf_event *event)
-{
-	int entry = sizeof(u64); /* value */
-	int size = 0;
-	int nr = 1;
-
-	if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
-		size += sizeof(u64);
-
-	if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
-		size += sizeof(u64);
-
-	if (event->attr.read_format & PERF_FORMAT_ID)
-		entry += sizeof(u64);
-
-	if (event->attr.read_format & PERF_FORMAT_GROUP) {
-		nr += event->group_leader->nr_siblings;
-		size += sizeof(u64);
-	}
-
-	size += entry * nr;
-
-	return size;
-}
-
 u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
 {
 	struct perf_event *child;
@@ -2428,7 +2514,7 @@
 	if (event->state == PERF_EVENT_STATE_ERROR)
 		return 0;
 
-	if (count < perf_event_read_size(event))
+	if (count < event->read_size)
 		return -ENOSPC;
 
 	WARN_ON_ONCE(event->ctx->parent_ctx);
@@ -2514,7 +2600,7 @@
 	int ret = 0;
 	u64 value;
 
-	if (!event->attr.sample_period)
+	if (!is_sampling_event(event))
 		return -EINVAL;
 
 	if (copy_from_user(&value, arg, sizeof(value)))
@@ -3305,6 +3391,73 @@
 	} while (len);
 }
 
+static void __perf_event_header__init_id(struct perf_event_header *header,
+					 struct perf_sample_data *data,
+					 struct perf_event *event)
+{
+	u64 sample_type = event->attr.sample_type;
+
+	data->type = sample_type;
+	header->size += event->id_header_size;
+
+	if (sample_type & PERF_SAMPLE_TID) {
+		/* namespace issues */
+		data->tid_entry.pid = perf_event_pid(event, current);
+		data->tid_entry.tid = perf_event_tid(event, current);
+	}
+
+	if (sample_type & PERF_SAMPLE_TIME)
+		data->time = perf_clock();
+
+	if (sample_type & PERF_SAMPLE_ID)
+		data->id = primary_event_id(event);
+
+	if (sample_type & PERF_SAMPLE_STREAM_ID)
+		data->stream_id = event->id;
+
+	if (sample_type & PERF_SAMPLE_CPU) {
+		data->cpu_entry.cpu	 = raw_smp_processor_id();
+		data->cpu_entry.reserved = 0;
+	}
+}
+
+static void perf_event_header__init_id(struct perf_event_header *header,
+				       struct perf_sample_data *data,
+				       struct perf_event *event)
+{
+	if (event->attr.sample_id_all)
+		__perf_event_header__init_id(header, data, event);
+}
+
+static void __perf_event__output_id_sample(struct perf_output_handle *handle,
+					   struct perf_sample_data *data)
+{
+	u64 sample_type = data->type;
+
+	if (sample_type & PERF_SAMPLE_TID)
+		perf_output_put(handle, data->tid_entry);
+
+	if (sample_type & PERF_SAMPLE_TIME)
+		perf_output_put(handle, data->time);
+
+	if (sample_type & PERF_SAMPLE_ID)
+		perf_output_put(handle, data->id);
+
+	if (sample_type & PERF_SAMPLE_STREAM_ID)
+		perf_output_put(handle, data->stream_id);
+
+	if (sample_type & PERF_SAMPLE_CPU)
+		perf_output_put(handle, data->cpu_entry);
+}
+
+static void perf_event__output_id_sample(struct perf_event *event,
+					 struct perf_output_handle *handle,
+					 struct perf_sample_data *sample)
+{
+	if (event->attr.sample_id_all)
+		__perf_event__output_id_sample(handle, sample);
+}
+
 int perf_output_begin(struct perf_output_handle *handle,
 		      struct perf_event *event, unsigned int size,
 		      int nmi, int sample)
@@ -3312,6 +3465,7 @@
 	struct perf_buffer *buffer;
 	unsigned long tail, offset, head;
 	int have_lost;
+	struct perf_sample_data sample_data;
 	struct {
 		struct perf_event_header header;
 		u64			 id;
@@ -3338,8 +3492,12 @@
 		goto out;
 
 	have_lost = local_read(&buffer->lost);
-	if (have_lost)
-		size += sizeof(lost_event);
+	if (have_lost) {
+		lost_event.header.size = sizeof(lost_event);
+		perf_event_header__init_id(&lost_event.header, &sample_data,
+					   event);
+		size += lost_event.header.size;
+	}
 
 	perf_output_get_handle(handle);
 
@@ -3370,11 +3528,11 @@
 	if (have_lost) {
 		lost_event.header.type = PERF_RECORD_LOST;
 		lost_event.header.misc = 0;
-		lost_event.header.size = sizeof(lost_event);
 		lost_event.id          = event->id;
 		lost_event.lost        = local_xchg(&buffer->lost, 0);
 
 		perf_output_put(handle, lost_event);
+		perf_event__output_id_sample(event, handle, &sample_data);
 	}
 
 	return 0;
@@ -3407,28 +3565,6 @@
 	rcu_read_unlock();
 }
 
-static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
-{
-	/*
-	 * only top level events have the pid namespace they were created in
-	 */
-	if (event->parent)
-		event = event->parent;
-
-	return task_tgid_nr_ns(p, event->ns);
-}
-
-static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
-{
-	/*
-	 * only top level events have the pid namespace they were created in
-	 */
-	if (event->parent)
-		event = event->parent;
-
-	return task_pid_nr_ns(p, event->ns);
-}
-
 static void perf_output_read_one(struct perf_output_handle *handle,
 				 struct perf_event *event,
 				 u64 enabled, u64 running)
@@ -3603,62 +3739,17 @@
 {
 	u64 sample_type = event->attr.sample_type;
 
-	data->type = sample_type;
-
 	header->type = PERF_RECORD_SAMPLE;
-	header->size = sizeof(*header);
+	header->size = sizeof(*header) + event->header_size;
 
 	header->misc = 0;
 	header->misc |= perf_misc_flags(regs);
 
-	if (sample_type & PERF_SAMPLE_IP) {
+	__perf_event_header__init_id(header, data, event);
+
+	if (sample_type & PERF_SAMPLE_IP)
 		data->ip = perf_instruction_pointer(regs);
 
-		header->size += sizeof(data->ip);
-	}
-
-	if (sample_type & PERF_SAMPLE_TID) {
-		/* namespace issues */
-		data->tid_entry.pid = perf_event_pid(event, current);
-		data->tid_entry.tid = perf_event_tid(event, current);
-
-		header->size += sizeof(data->tid_entry);
-	}
-
-	if (sample_type & PERF_SAMPLE_TIME) {
-		data->time = perf_clock();
-
-		header->size += sizeof(data->time);
-	}
-
-	if (sample_type & PERF_SAMPLE_ADDR)
-		header->size += sizeof(data->addr);
-
-	if (sample_type & PERF_SAMPLE_ID) {
-		data->id = primary_event_id(event);
-
-		header->size += sizeof(data->id);
-	}
-
-	if (sample_type & PERF_SAMPLE_STREAM_ID) {
-		data->stream_id = event->id;
-
-		header->size += sizeof(data->stream_id);
-	}
-
-	if (sample_type & PERF_SAMPLE_CPU) {
-		data->cpu_entry.cpu		= raw_smp_processor_id();
-		data->cpu_entry.reserved	= 0;
-
-		header->size += sizeof(data->cpu_entry);
-	}
-
-	if (sample_type & PERF_SAMPLE_PERIOD)
-		header->size += sizeof(data->period);
-
-	if (sample_type & PERF_SAMPLE_READ)
-		header->size += perf_event_read_size(event);
-
 	if (sample_type & PERF_SAMPLE_CALLCHAIN) {
 		int size = 1;
 
@@ -3722,23 +3813,26 @@
 			struct task_struct *task)
 {
 	struct perf_output_handle handle;
+	struct perf_sample_data sample;
 	struct perf_read_event read_event = {
 		.header = {
 			.type = PERF_RECORD_READ,
 			.misc = 0,
-			.size = sizeof(read_event) + perf_event_read_size(event),
+			.size = sizeof(read_event) + event->read_size,
 		},
 		.pid = perf_event_pid(event, task),
 		.tid = perf_event_tid(event, task),
 	};
 	int ret;
 
+	perf_event_header__init_id(&read_event.header, &sample, event);
 	ret = perf_output_begin(&handle, event, read_event.header.size, 0, 0);
 	if (ret)
 		return;
 
 	perf_output_put(&handle, read_event);
 	perf_output_read(&handle, event);
+	perf_event__output_id_sample(event, &handle, &sample);
 
 	perf_output_end(&handle);
 }
@@ -3768,14 +3862,16 @@
 				     struct perf_task_event *task_event)
 {
 	struct perf_output_handle handle;
+	struct perf_sample_data	sample;
 	struct task_struct *task = task_event->task;
-	int size, ret;
+	int ret, size = task_event->event_id.header.size;
 
-	size  = task_event->event_id.header.size;
-	ret = perf_output_begin(&handle, event, size, 0, 0);
+	perf_event_header__init_id(&task_event->event_id.header, &sample, event);
 
+	ret = perf_output_begin(&handle, event,
+				task_event->event_id.header.size, 0, 0);
 	if (ret)
-		return;
+		goto out;
 
 	task_event->event_id.pid = perf_event_pid(event, task);
 	task_event->event_id.ppid = perf_event_pid(event, current);
@@ -3785,7 +3881,11 @@
 
 	perf_output_put(&handle, task_event->event_id);
 
+	perf_event__output_id_sample(event, &handle, &sample);
+
 	perf_output_end(&handle);
+out:
+	task_event->event_id.header.size = size;
 }
 
 static int perf_event_task_match(struct perf_event *event)
@@ -3900,11 +4000,16 @@
 				     struct perf_comm_event *comm_event)
 {
 	struct perf_output_handle handle;
+	struct perf_sample_data sample;
 	int size = comm_event->event_id.header.size;
-	int ret = perf_output_begin(&handle, event, size, 0, 0);
+	int ret;
+
+	perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
+	ret = perf_output_begin(&handle, event,
+				comm_event->event_id.header.size, 0, 0);
 
 	if (ret)
-		return;
+		goto out;
 
 	comm_event->event_id.pid = perf_event_pid(event, comm_event->task);
 	comm_event->event_id.tid = perf_event_tid(event, comm_event->task);
@@ -3912,7 +4017,12 @@
 	perf_output_put(&handle, comm_event->event_id);
 	perf_output_copy(&handle, comm_event->comm,
 				   comm_event->comm_size);
+
+	perf_event__output_id_sample(event, &handle, &sample);
+
 	perf_output_end(&handle);
+out:
+	comm_event->event_id.header.size = size;
 }
 
 static int perf_event_comm_match(struct perf_event *event)
@@ -3957,7 +4067,6 @@
 	comm_event->comm_size = size;
 
 	comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
-
 	rcu_read_lock();
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
 		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
@@ -4038,11 +4147,15 @@
 				     struct perf_mmap_event *mmap_event)
 {
 	struct perf_output_handle handle;
+	struct perf_sample_data sample;
 	int size = mmap_event->event_id.header.size;
-	int ret = perf_output_begin(&handle, event, size, 0, 0);
+	int ret;
 
+	perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
+	ret = perf_output_begin(&handle, event,
+				mmap_event->event_id.header.size, 0, 0);
 	if (ret)
-		return;
+		goto out;
 
 	mmap_event->event_id.pid = perf_event_pid(event, current);
 	mmap_event->event_id.tid = perf_event_tid(event, current);
@@ -4050,7 +4163,12 @@
 	perf_output_put(&handle, mmap_event->event_id);
 	perf_output_copy(&handle, mmap_event->file_name,
 				   mmap_event->file_size);
+
+	perf_event__output_id_sample(event, &handle, &sample);
+
 	perf_output_end(&handle);
+out:
+	mmap_event->event_id.header.size = size;
 }
 
 static int perf_event_mmap_match(struct perf_event *event,
@@ -4205,6 +4323,7 @@
 static void perf_log_throttle(struct perf_event *event, int enable)
 {
 	struct perf_output_handle handle;
+	struct perf_sample_data sample;
 	int ret;
 
 	struct {
@@ -4226,11 +4345,15 @@
 	if (enable)
 		throttle_event.header.type = PERF_RECORD_UNTHROTTLE;
 
-	ret = perf_output_begin(&handle, event, sizeof(throttle_event), 1, 0);
+	perf_event_header__init_id(&throttle_event.header, &sample, event);
+
+	ret = perf_output_begin(&handle, event,
+				throttle_event.header.size, 1, 0);
 	if (ret)
 		return;
 
 	perf_output_put(&handle, throttle_event);
+	perf_event__output_id_sample(event, &handle, &sample);
 	perf_output_end(&handle);
 }
 
@@ -4246,6 +4369,13 @@
 	struct hw_perf_event *hwc = &event->hw;
 	int ret = 0;
 
+	/*
+	 * Non-sampling counters might still use the PMI to fold short
+	 * hardware counters, ignore those.
+	 */
+	if (unlikely(!is_sampling_event(event)))
+		return 0;
+
 	if (!throttle) {
 		hwc->interrupts++;
 	} else {
@@ -4391,7 +4521,7 @@
 	if (!regs)
 		return;
 
-	if (!hwc->sample_period)
+	if (!is_sampling_event(event))
 		return;
 
 	if (nr == 1 && hwc->sample_period == 1 && !event->attr.freq)
@@ -4554,7 +4684,7 @@
 	struct hw_perf_event *hwc = &event->hw;
 	struct hlist_head *head;
 
-	if (hwc->sample_period) {
+	if (is_sampling_event(event)) {
 		hwc->last_period = hwc->sample_period;
 		perf_swevent_set_period(event);
 	}
@@ -4811,15 +4941,6 @@
 	if (event->attr.type != PERF_TYPE_TRACEPOINT)
 		return -ENOENT;
 
-	/*
-	 * Raw tracepoint data is a severe data leak, only allow root to
-	 * have these.
-	 */
-	if ((event->attr.sample_type & PERF_SAMPLE_RAW) &&
-			perf_paranoid_tracepoint_raw() &&
-			!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	err = perf_trace_init(event);
 	if (err)
 		return err;
@@ -4842,7 +4963,7 @@
 
 static inline void perf_tp_register(void)
 {
-	perf_pmu_register(&perf_tracepoint);
+	perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
 }
 
 static int perf_event_set_filter(struct perf_event *event, void __user *arg)
@@ -4932,31 +5053,33 @@
 static void perf_swevent_start_hrtimer(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
+	s64 period;
+
+	if (!is_sampling_event(event))
+		return;
 
 	hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	hwc->hrtimer.function = perf_swevent_hrtimer;
-	if (hwc->sample_period) {
-		s64 period = local64_read(&hwc->period_left);
 
-		if (period) {
-			if (period < 0)
-				period = 10000;
+	period = local64_read(&hwc->period_left);
+	if (period) {
+		if (period < 0)
+			period = 10000;
 
-			local64_set(&hwc->period_left, 0);
-		} else {
-			period = max_t(u64, 10000, hwc->sample_period);
-		}
-		__hrtimer_start_range_ns(&hwc->hrtimer,
+		local64_set(&hwc->period_left, 0);
+	} else {
+		period = max_t(u64, 10000, hwc->sample_period);
+	}
+	__hrtimer_start_range_ns(&hwc->hrtimer,
 				ns_to_ktime(period), 0,
 				HRTIMER_MODE_REL_PINNED, 0);
-	}
 }
 
 static void perf_swevent_cancel_hrtimer(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
 
-	if (hwc->sample_period) {
+	if (is_sampling_event(event)) {
 		ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
 		local64_set(&hwc->period_left, ktime_to_ns(remaining));
 
@@ -5184,8 +5307,61 @@
 out:
 	mutex_unlock(&pmus_lock);
 }
+static struct idr pmu_idr;
 
-int perf_pmu_register(struct pmu *pmu)
+static ssize_t
+type_show(struct device *dev, struct device_attribute *attr, char *page)
+{
+	struct pmu *pmu = dev_get_drvdata(dev);
+
+	return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
+}
+
+static struct device_attribute pmu_dev_attrs[] = {
+       __ATTR_RO(type),
+       __ATTR_NULL,
+};
+
+static int pmu_bus_running;
+static struct bus_type pmu_bus = {
+	.name		= "event_source",
+	.dev_attrs	= pmu_dev_attrs,
+};
+
+static void pmu_dev_release(struct device *dev)
+{
+	kfree(dev);
+}
+
+static int pmu_dev_alloc(struct pmu *pmu)
+{
+	int ret = -ENOMEM;
+
+	pmu->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+	if (!pmu->dev)
+		goto out;
+
+	device_initialize(pmu->dev);
+	ret = dev_set_name(pmu->dev, "%s", pmu->name);
+	if (ret)
+		goto free_dev;
+
+	dev_set_drvdata(pmu->dev, pmu);
+	pmu->dev->bus = &pmu_bus;
+	pmu->dev->release = pmu_dev_release;
+	ret = device_add(pmu->dev);
+	if (ret)
+		goto free_dev;
+
+out:
+	return ret;
+
+free_dev:
+	put_device(pmu->dev);
+	goto out;
+}
+
+int perf_pmu_register(struct pmu *pmu, char *name, int type)
 {
 	int cpu, ret;
 
@@ -5195,13 +5371,38 @@
 	if (!pmu->pmu_disable_count)
 		goto unlock;
 
+	pmu->type = -1;
+	if (!name)
+		goto skip_type;
+	pmu->name = name;
+
+	if (type < 0) {
+		int err = idr_pre_get(&pmu_idr, GFP_KERNEL);
+		if (!err)
+			goto free_pdc;
+
+		err = idr_get_new_above(&pmu_idr, pmu, PERF_TYPE_MAX, &type);
+		if (err) {
+			ret = err;
+			goto free_pdc;
+		}
+	}
+	pmu->type = type;
+
+	if (pmu_bus_running) {
+		ret = pmu_dev_alloc(pmu);
+		if (ret)
+			goto free_idr;
+	}
+
+skip_type:
 	pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
 	if (pmu->pmu_cpu_context)
 		goto got_cpu_context;
 
 	pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
 	if (!pmu->pmu_cpu_context)
-		goto free_pdc;
+		goto free_dev;
 
 	for_each_possible_cpu(cpu) {
 		struct perf_cpu_context *cpuctx;
@@ -5245,6 +5446,14 @@
 
 	return ret;
 
+free_dev:
+	device_del(pmu->dev);
+	put_device(pmu->dev);
+
+free_idr:
+	if (pmu->type >= PERF_TYPE_MAX)
+		idr_remove(&pmu_idr, pmu->type);
+
 free_pdc:
 	free_percpu(pmu->pmu_disable_count);
 	goto unlock;
@@ -5264,6 +5473,10 @@
 	synchronize_rcu();
 
 	free_percpu(pmu->pmu_disable_count);
+	if (pmu->type >= PERF_TYPE_MAX)
+		idr_remove(&pmu_idr, pmu->type);
+	device_del(pmu->dev);
+	put_device(pmu->dev);
 	free_pmu_context(pmu);
 }
 
@@ -5273,6 +5486,13 @@
 	int idx;
 
 	idx = srcu_read_lock(&pmus_srcu);
+
+	rcu_read_lock();
+	pmu = idr_find(&pmu_idr, event->attr.type);
+	rcu_read_unlock();
+	if (pmu)
+		goto unlock;
+
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
 		int ret = pmu->event_init(event);
 		if (!ret)
@@ -5738,6 +5958,12 @@
 	mutex_unlock(&current->perf_event_mutex);
 
 	/*
+	 * Precalculate sample_data sizes
+	 */
+	perf_event__header_size(event);
+	perf_event__id_header_size(event);
+
+	/*
 	 * Drop the reference on the group_event after placing the
 	 * new event on the sibling_list. This ensures destruction
 	 * of the group leader will find the pointer to itself in
@@ -6090,6 +6316,12 @@
 	child_event->overflow_handler = parent_event->overflow_handler;
 
 	/*
+	 * Precalculate sample_data sizes
+	 */
+	perf_event__header_size(child_event);
+	perf_event__id_header_size(child_event);
+
+	/*
 	 * Link it up in the child's context:
 	 */
 	raw_spin_lock_irqsave(&child_ctx->lock, flags);
@@ -6320,7 +6552,7 @@
 	mutex_unlock(&swhash->hlist_mutex);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC
 static void perf_pmu_rotate_stop(struct pmu *pmu)
 {
 	struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
@@ -6374,6 +6606,26 @@
 static inline void perf_event_exit_cpu(int cpu) { }
 #endif
 
+static int
+perf_reboot(struct notifier_block *notifier, unsigned long val, void *v)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		perf_event_exit_cpu(cpu);
+
+	return NOTIFY_OK;
+}
+
+/*
+ * Run the perf reboot notifier at the very last possible moment so that
+ * the generic watchdog code runs as long as possible.
+ */
+static struct notifier_block perf_reboot_notifier = {
+	.notifier_call = perf_reboot,
+	.priority = INT_MIN,
+};
+
 static int __cpuinit
 perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
 {
@@ -6402,14 +6654,45 @@
 {
 	int ret;
 
+	idr_init(&pmu_idr);
+
 	perf_event_init_all_cpus();
 	init_srcu_struct(&pmus_srcu);
-	perf_pmu_register(&perf_swevent);
-	perf_pmu_register(&perf_cpu_clock);
-	perf_pmu_register(&perf_task_clock);
+	perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE);
+	perf_pmu_register(&perf_cpu_clock, NULL, -1);
+	perf_pmu_register(&perf_task_clock, NULL, -1);
 	perf_tp_register();
 	perf_cpu_notifier(perf_cpu_notify);
+	register_reboot_notifier(&perf_reboot_notifier);
 
 	ret = init_hw_breakpoint();
 	WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
 }
+
+static int __init perf_event_sysfs_init(void)
+{
+	struct pmu *pmu;
+	int ret;
+
+	mutex_lock(&pmus_lock);
+
+	ret = bus_register(&pmu_bus);
+	if (ret)
+		goto unlock;
+
+	list_for_each_entry(pmu, &pmus, entry) {
+		if (!pmu->name || pmu->type < 0)
+			continue;
+
+		ret = pmu_dev_alloc(pmu);
+		WARN(ret, "Failed to register pmu: %s, reason %d\n", pmu->name, ret);
+	}
+	pmu_bus_running = 1;
+	ret = 0;
+
+unlock:
+	mutex_unlock(&pmus_lock);
+
+	return ret;
+}
+device_initcall(perf_event_sysfs_init);
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 9ca4973..93bd2eb 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -145,7 +145,13 @@
 
 static enum hrtimer_restart posix_timer_fn(struct hrtimer *data);
 
-static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
+static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags);
+
+#define lock_timer(tid, flags)						   \
+({	struct k_itimer *__timr;					   \
+	__cond_lock(&__timr->it_lock, __timr = __lock_timer(tid, flags));  \
+	__timr;								   \
+})
 
 static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
 {
@@ -619,7 +625,7 @@
  * the find to the timer lock.  To avoid a dead lock, the timer id MUST
  * be release with out holding the timer lock.
  */
-static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags)
+static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)
 {
 	struct k_itimer *timr;
 	/*
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index ecf7705..031d5e3 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <trace/events/power.h>
 
 #include "power.h"
 
@@ -201,6 +202,7 @@
 	if (!suspend_ops)
 		return -ENOSYS;
 
+	trace_machine_suspend(state);
 	if (suspend_ops->begin) {
 		error = suspend_ops->begin(state);
 		if (error)
@@ -229,6 +231,7 @@
  Close:
 	if (suspend_ops->end)
 		suspend_ops->end();
+	trace_machine_suspend(PWR_EVENT_EXIT);
 	return error;
 
  Recover_platform:
diff --git a/kernel/printk.c b/kernel/printk.c
index a23315d..4642a5c 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -43,12 +43,6 @@
 #include <asm/uaccess.h>
 
 /*
- * for_each_console() allows you to iterate on each console
- */
-#define for_each_console(con) \
-	for (con = console_drivers; con != NULL; con = con->next)
-
-/*
  * Architectures can override it:
  */
 void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
@@ -1074,17 +1068,17 @@
 
 void printk_tick(void)
 {
-	if (__get_cpu_var(printk_pending)) {
-		__get_cpu_var(printk_pending) = 0;
+	if (__this_cpu_read(printk_pending)) {
+		__this_cpu_write(printk_pending, 0);
 		wake_up_interruptible(&log_wait);
 	}
 }
 
 int printk_needs_cpu(int cpu)
 {
-	if (unlikely(cpu_is_offline(cpu)))
+	if (cpu_is_offline(cpu))
 		printk_tick();
-	return per_cpu(printk_pending, cpu);
+	return __this_cpu_read(printk_pending);
 }
 
 void wake_up_klogd(void)
@@ -1359,6 +1353,7 @@
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 	}
 	release_console_sem();
+	console_sysfs_notify();
 
 	/*
 	 * By unregistering the bootconsoles after we enable the real console
@@ -1417,6 +1412,7 @@
 		console_drivers->flags |= CON_CONSDEV;
 
 	release_console_sem();
+	console_sysfs_notify();
 	return res;
 }
 EXPORT_SYMBOL(unregister_console);
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index d806735..0344937 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -36,31 +36,16 @@
 #include <linux/time.h>
 #include <linux/cpu.h>
 
-/* Global control variables for rcupdate callback mechanism. */
-struct rcu_ctrlblk {
-	struct rcu_head *rcucblist;	/* List of pending callbacks (CBs). */
-	struct rcu_head **donetail;	/* ->next pointer of last "done" CB. */
-	struct rcu_head **curtail;	/* ->next pointer of last CB. */
-};
-
-/* Definition for rcupdate control block. */
-static struct rcu_ctrlblk rcu_sched_ctrlblk = {
-	.donetail	= &rcu_sched_ctrlblk.rcucblist,
-	.curtail	= &rcu_sched_ctrlblk.rcucblist,
-};
-
-static struct rcu_ctrlblk rcu_bh_ctrlblk = {
-	.donetail	= &rcu_bh_ctrlblk.rcucblist,
-	.curtail	= &rcu_bh_ctrlblk.rcucblist,
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-int rcu_scheduler_active __read_mostly;
-EXPORT_SYMBOL_GPL(rcu_scheduler_active);
-#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+/* Controls for rcu_kthread() kthread, replacing RCU_SOFTIRQ used previously. */
+static struct task_struct *rcu_kthread_task;
+static DECLARE_WAIT_QUEUE_HEAD(rcu_kthread_wq);
+static unsigned long have_rcu_kthread_work;
+static void invoke_rcu_kthread(void);
 
 /* Forward declarations for rcutiny_plugin.h. */
-static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp);
+struct rcu_ctrlblk;
+static void rcu_process_callbacks(struct rcu_ctrlblk *rcp);
+static int rcu_kthread(void *arg);
 static void __call_rcu(struct rcu_head *head,
 		       void (*func)(struct rcu_head *rcu),
 		       struct rcu_ctrlblk *rcp);
@@ -123,7 +108,7 @@
 {
 	if (rcu_qsctr_help(&rcu_sched_ctrlblk) +
 	    rcu_qsctr_help(&rcu_bh_ctrlblk))
-		raise_softirq(RCU_SOFTIRQ);
+		invoke_rcu_kthread();
 }
 
 /*
@@ -132,7 +117,7 @@
 void rcu_bh_qs(int cpu)
 {
 	if (rcu_qsctr_help(&rcu_bh_ctrlblk))
-		raise_softirq(RCU_SOFTIRQ);
+		invoke_rcu_kthread();
 }
 
 /*
@@ -152,13 +137,14 @@
 }
 
 /*
- * Helper function for rcu_process_callbacks() that operates on the
- * specified rcu_ctrlkblk structure.
+ * Invoke the RCU callbacks on the specified rcu_ctrlkblk structure
+ * whose grace period has elapsed.
  */
-static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
+static void rcu_process_callbacks(struct rcu_ctrlblk *rcp)
 {
 	struct rcu_head *next, *list;
 	unsigned long flags;
+	RCU_TRACE(int cb_count = 0);
 
 	/* If no RCU callbacks ready to invoke, just return. */
 	if (&rcp->rcucblist == rcp->donetail)
@@ -180,19 +166,58 @@
 		next = list->next;
 		prefetch(next);
 		debug_rcu_head_unqueue(list);
+		local_bh_disable();
 		list->func(list);
+		local_bh_enable();
 		list = next;
+		RCU_TRACE(cb_count++);
 	}
+	RCU_TRACE(rcu_trace_sub_qlen(rcp, cb_count));
 }
 
 /*
- * Invoke any callbacks whose grace period has completed.
+ * This kthread invokes RCU callbacks whose grace periods have
+ * elapsed.  It is awakened as needed, and takes the place of the
+ * RCU_SOFTIRQ that was used previously for this purpose.
+ * This is a kthread, but it is never stopped, at least not until
+ * the system goes down.
  */
-static void rcu_process_callbacks(struct softirq_action *unused)
+static int rcu_kthread(void *arg)
 {
-	__rcu_process_callbacks(&rcu_sched_ctrlblk);
-	__rcu_process_callbacks(&rcu_bh_ctrlblk);
-	rcu_preempt_process_callbacks();
+	unsigned long work;
+	unsigned long morework;
+	unsigned long flags;
+
+	for (;;) {
+		wait_event(rcu_kthread_wq, have_rcu_kthread_work != 0);
+		morework = rcu_boost();
+		local_irq_save(flags);
+		work = have_rcu_kthread_work;
+		have_rcu_kthread_work = morework;
+		local_irq_restore(flags);
+		if (work) {
+			rcu_process_callbacks(&rcu_sched_ctrlblk);
+			rcu_process_callbacks(&rcu_bh_ctrlblk);
+			rcu_preempt_process_callbacks();
+		}
+		schedule_timeout_interruptible(1); /* Leave CPU for others. */
+	}
+
+	return 0;  /* Not reached, but needed to shut gcc up. */
+}
+
+/*
+ * Wake up rcu_kthread() to process callbacks now eligible for invocation
+ * or to boost readers.
+ */
+static void invoke_rcu_kthread(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	have_rcu_kthread_work = 1;
+	wake_up(&rcu_kthread_wq);
+	local_irq_restore(flags);
 }
 
 /*
@@ -230,6 +255,7 @@
 	local_irq_save(flags);
 	*rcp->curtail = head;
 	rcp->curtail = &head->next;
+	RCU_TRACE(rcp->qlen++);
 	local_irq_restore(flags);
 }
 
@@ -282,7 +308,16 @@
 }
 EXPORT_SYMBOL_GPL(rcu_barrier_sched);
 
-void __init rcu_init(void)
+/*
+ * Spawn the kthread that invokes RCU callbacks.
+ */
+static int __init rcu_spawn_kthreads(void)
 {
-	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
+	struct sched_param sp;
+
+	rcu_kthread_task = kthread_run(rcu_kthread, NULL, "rcu_kthread");
+	sp.sched_priority = RCU_BOOST_PRIO;
+	sched_setscheduler_nocheck(rcu_kthread_task, SCHED_FIFO, &sp);
+	return 0;
 }
+early_initcall(rcu_spawn_kthreads);
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 6ceca4f..015abae 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -22,6 +22,40 @@
  * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
  */
 
+#include <linux/kthread.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#ifdef CONFIG_RCU_TRACE
+#define RCU_TRACE(stmt)	stmt
+#else /* #ifdef CONFIG_RCU_TRACE */
+#define RCU_TRACE(stmt)
+#endif /* #else #ifdef CONFIG_RCU_TRACE */
+
+/* Global control variables for rcupdate callback mechanism. */
+struct rcu_ctrlblk {
+	struct rcu_head *rcucblist;	/* List of pending callbacks (CBs). */
+	struct rcu_head **donetail;	/* ->next pointer of last "done" CB. */
+	struct rcu_head **curtail;	/* ->next pointer of last CB. */
+	RCU_TRACE(long qlen);		/* Number of pending CBs. */
+};
+
+/* Definition for rcupdate control block. */
+static struct rcu_ctrlblk rcu_sched_ctrlblk = {
+	.donetail	= &rcu_sched_ctrlblk.rcucblist,
+	.curtail	= &rcu_sched_ctrlblk.rcucblist,
+};
+
+static struct rcu_ctrlblk rcu_bh_ctrlblk = {
+	.donetail	= &rcu_bh_ctrlblk.rcucblist,
+	.curtail	= &rcu_bh_ctrlblk.rcucblist,
+};
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+int rcu_scheduler_active __read_mostly;
+EXPORT_SYMBOL_GPL(rcu_scheduler_active);
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
 #ifdef CONFIG_TINY_PREEMPT_RCU
 
 #include <linux/delay.h>
@@ -46,17 +80,45 @@
 	struct list_head *gp_tasks;
 				/* Pointer to the first task blocking the */
 				/*  current grace period, or NULL if there */
-				/*  is not such task. */
+				/*  is no such task. */
 	struct list_head *exp_tasks;
 				/* Pointer to first task blocking the */
 				/*  current expedited grace period, or NULL */
 				/*  if there is no such task.  If there */
 				/*  is no current expedited grace period, */
 				/*  then there cannot be any such task. */
+#ifdef CONFIG_RCU_BOOST
+	struct list_head *boost_tasks;
+				/* Pointer to first task that needs to be */
+				/*  priority-boosted, or NULL if no priority */
+				/*  boosting is needed.  If there is no */
+				/*  current or expedited grace period, there */
+				/*  can be no such task. */
+#endif /* #ifdef CONFIG_RCU_BOOST */
 	u8 gpnum;		/* Current grace period. */
 	u8 gpcpu;		/* Last grace period blocked by the CPU. */
 	u8 completed;		/* Last grace period completed. */
 				/*  If all three are equal, RCU is idle. */
+#ifdef CONFIG_RCU_BOOST
+	s8 boosted_this_gp;	/* Has boosting already happened? */
+	unsigned long boost_time; /* When to start boosting (jiffies) */
+#endif /* #ifdef CONFIG_RCU_BOOST */
+#ifdef CONFIG_RCU_TRACE
+	unsigned long n_grace_periods;
+#ifdef CONFIG_RCU_BOOST
+	unsigned long n_tasks_boosted;
+	unsigned long n_exp_boosts;
+	unsigned long n_normal_boosts;
+	unsigned long n_normal_balk_blkd_tasks;
+	unsigned long n_normal_balk_gp_tasks;
+	unsigned long n_normal_balk_boost_tasks;
+	unsigned long n_normal_balk_boosted;
+	unsigned long n_normal_balk_notyet;
+	unsigned long n_normal_balk_nos;
+	unsigned long n_exp_balk_blkd_tasks;
+	unsigned long n_exp_balk_nos;
+#endif /* #ifdef CONFIG_RCU_BOOST */
+#endif /* #ifdef CONFIG_RCU_TRACE */
 };
 
 static struct rcu_preempt_ctrlblk rcu_preempt_ctrlblk = {
@@ -122,6 +184,210 @@
 }
 
 /*
+ * Advance a ->blkd_tasks-list pointer to the next entry, instead
+ * returning NULL if at the end of the list.
+ */
+static struct list_head *rcu_next_node_entry(struct task_struct *t)
+{
+	struct list_head *np;
+
+	np = t->rcu_node_entry.next;
+	if (np == &rcu_preempt_ctrlblk.blkd_tasks)
+		np = NULL;
+	return np;
+}
+
+#ifdef CONFIG_RCU_TRACE
+
+#ifdef CONFIG_RCU_BOOST
+static void rcu_initiate_boost_trace(void);
+static void rcu_initiate_exp_boost_trace(void);
+#endif /* #ifdef CONFIG_RCU_BOOST */
+
+/*
+ * Dump additional statistice for TINY_PREEMPT_RCU.
+ */
+static void show_tiny_preempt_stats(struct seq_file *m)
+{
+	seq_printf(m, "rcu_preempt: qlen=%ld gp=%lu g%u/p%u/c%u tasks=%c%c%c\n",
+		   rcu_preempt_ctrlblk.rcb.qlen,
+		   rcu_preempt_ctrlblk.n_grace_periods,
+		   rcu_preempt_ctrlblk.gpnum,
+		   rcu_preempt_ctrlblk.gpcpu,
+		   rcu_preempt_ctrlblk.completed,
+		   "T."[list_empty(&rcu_preempt_ctrlblk.blkd_tasks)],
+		   "N."[!rcu_preempt_ctrlblk.gp_tasks],
+		   "E."[!rcu_preempt_ctrlblk.exp_tasks]);
+#ifdef CONFIG_RCU_BOOST
+	seq_printf(m, "             ttb=%c btg=",
+		   "B."[!rcu_preempt_ctrlblk.boost_tasks]);
+	switch (rcu_preempt_ctrlblk.boosted_this_gp) {
+	case -1:
+		seq_puts(m, "exp");
+		break;
+	case 0:
+		seq_puts(m, "no");
+		break;
+	case 1:
+		seq_puts(m, "begun");
+		break;
+	case 2:
+		seq_puts(m, "done");
+		break;
+	default:
+		seq_printf(m, "?%d?", rcu_preempt_ctrlblk.boosted_this_gp);
+	}
+	seq_printf(m, " ntb=%lu neb=%lu nnb=%lu j=%04x bt=%04x\n",
+		   rcu_preempt_ctrlblk.n_tasks_boosted,
+		   rcu_preempt_ctrlblk.n_exp_boosts,
+		   rcu_preempt_ctrlblk.n_normal_boosts,
+		   (int)(jiffies & 0xffff),
+		   (int)(rcu_preempt_ctrlblk.boost_time & 0xffff));
+	seq_printf(m, "             %s: nt=%lu gt=%lu bt=%lu b=%lu ny=%lu nos=%lu\n",
+		   "normal balk",
+		   rcu_preempt_ctrlblk.n_normal_balk_blkd_tasks,
+		   rcu_preempt_ctrlblk.n_normal_balk_gp_tasks,
+		   rcu_preempt_ctrlblk.n_normal_balk_boost_tasks,
+		   rcu_preempt_ctrlblk.n_normal_balk_boosted,
+		   rcu_preempt_ctrlblk.n_normal_balk_notyet,
+		   rcu_preempt_ctrlblk.n_normal_balk_nos);
+	seq_printf(m, "             exp balk: bt=%lu nos=%lu\n",
+		   rcu_preempt_ctrlblk.n_exp_balk_blkd_tasks,
+		   rcu_preempt_ctrlblk.n_exp_balk_nos);
+#endif /* #ifdef CONFIG_RCU_BOOST */
+}
+
+#endif /* #ifdef CONFIG_RCU_TRACE */
+
+#ifdef CONFIG_RCU_BOOST
+
+#include "rtmutex_common.h"
+
+/*
+ * Carry out RCU priority boosting on the task indicated by ->boost_tasks,
+ * and advance ->boost_tasks to the next task in the ->blkd_tasks list.
+ */
+static int rcu_boost(void)
+{
+	unsigned long flags;
+	struct rt_mutex mtx;
+	struct list_head *np;
+	struct task_struct *t;
+
+	if (rcu_preempt_ctrlblk.boost_tasks == NULL)
+		return 0;  /* Nothing to boost. */
+	raw_local_irq_save(flags);
+	rcu_preempt_ctrlblk.boosted_this_gp++;
+	t = container_of(rcu_preempt_ctrlblk.boost_tasks, struct task_struct,
+			 rcu_node_entry);
+	np = rcu_next_node_entry(t);
+	rt_mutex_init_proxy_locked(&mtx, t);
+	t->rcu_boost_mutex = &mtx;
+	t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BOOSTED;
+	raw_local_irq_restore(flags);
+	rt_mutex_lock(&mtx);
+	RCU_TRACE(rcu_preempt_ctrlblk.n_tasks_boosted++);
+	rcu_preempt_ctrlblk.boosted_this_gp++;
+	rt_mutex_unlock(&mtx);
+	return rcu_preempt_ctrlblk.boost_tasks != NULL;
+}
+
+/*
+ * Check to see if it is now time to start boosting RCU readers blocking
+ * the current grace period, and, if so, tell the rcu_kthread_task to
+ * start boosting them.  If there is an expedited boost in progress,
+ * we wait for it to complete.
+ *
+ * If there are no blocked readers blocking the current grace period,
+ * return 0 to let the caller know, otherwise return 1.  Note that this
+ * return value is independent of whether or not boosting was done.
+ */
+static int rcu_initiate_boost(void)
+{
+	if (!rcu_preempt_blocked_readers_cgp()) {
+		RCU_TRACE(rcu_preempt_ctrlblk.n_normal_balk_blkd_tasks++);
+		return 0;
+	}
+	if (rcu_preempt_ctrlblk.gp_tasks != NULL &&
+	    rcu_preempt_ctrlblk.boost_tasks == NULL &&
+	    rcu_preempt_ctrlblk.boosted_this_gp == 0 &&
+	    ULONG_CMP_GE(jiffies, rcu_preempt_ctrlblk.boost_time)) {
+		rcu_preempt_ctrlblk.boost_tasks = rcu_preempt_ctrlblk.gp_tasks;
+		invoke_rcu_kthread();
+		RCU_TRACE(rcu_preempt_ctrlblk.n_normal_boosts++);
+	} else
+		RCU_TRACE(rcu_initiate_boost_trace());
+	return 1;
+}
+
+/*
+ * Initiate boosting for an expedited grace period.
+ */
+static void rcu_initiate_expedited_boost(void)
+{
+	unsigned long flags;
+
+	raw_local_irq_save(flags);
+	if (!list_empty(&rcu_preempt_ctrlblk.blkd_tasks)) {
+		rcu_preempt_ctrlblk.boost_tasks =
+			rcu_preempt_ctrlblk.blkd_tasks.next;
+		rcu_preempt_ctrlblk.boosted_this_gp = -1;
+		invoke_rcu_kthread();
+		RCU_TRACE(rcu_preempt_ctrlblk.n_exp_boosts++);
+	} else
+		RCU_TRACE(rcu_initiate_exp_boost_trace());
+	raw_local_irq_restore(flags);
+}
+
+#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000);
+
+/*
+ * Do priority-boost accounting for the start of a new grace period.
+ */
+static void rcu_preempt_boost_start_gp(void)
+{
+	rcu_preempt_ctrlblk.boost_time = jiffies + RCU_BOOST_DELAY_JIFFIES;
+	if (rcu_preempt_ctrlblk.boosted_this_gp > 0)
+		rcu_preempt_ctrlblk.boosted_this_gp = 0;
+}
+
+#else /* #ifdef CONFIG_RCU_BOOST */
+
+/*
+ * If there is no RCU priority boosting, we don't boost.
+ */
+static int rcu_boost(void)
+{
+	return 0;
+}
+
+/*
+ * If there is no RCU priority boosting, we don't initiate boosting,
+ * but we do indicate whether there are blocked readers blocking the
+ * current grace period.
+ */
+static int rcu_initiate_boost(void)
+{
+	return rcu_preempt_blocked_readers_cgp();
+}
+
+/*
+ * If there is no RCU priority boosting, we don't initiate expedited boosting.
+ */
+static void rcu_initiate_expedited_boost(void)
+{
+}
+
+/*
+ * If there is no RCU priority boosting, nothing to do at grace-period start.
+ */
+static void rcu_preempt_boost_start_gp(void)
+{
+}
+
+#endif /* else #ifdef CONFIG_RCU_BOOST */
+
+/*
  * Record a preemptible-RCU quiescent state for the specified CPU.  Note
  * that this just means that the task currently running on the CPU is
  * in a quiescent state.  There might be any number of tasks blocked
@@ -148,11 +414,14 @@
 	rcu_preempt_ctrlblk.gpcpu = rcu_preempt_ctrlblk.gpnum;
 	current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
 
+	/* If there is no GP then there is nothing more to do.  */
+	if (!rcu_preempt_gp_in_progress())
+		return;
 	/*
-	 * If there is no GP, or if blocked readers are still blocking GP,
-	 * then there is nothing more to do.
+	 * Check up on boosting.  If there are no readers blocking the
+	 * current grace period, leave.
 	 */
-	if (!rcu_preempt_gp_in_progress() || rcu_preempt_blocked_readers_cgp())
+	if (rcu_initiate_boost())
 		return;
 
 	/* Advance callbacks. */
@@ -164,9 +433,9 @@
 	if (!rcu_preempt_blocked_readers_any())
 		rcu_preempt_ctrlblk.rcb.donetail = rcu_preempt_ctrlblk.nexttail;
 
-	/* If there are done callbacks, make RCU_SOFTIRQ process them. */
+	/* If there are done callbacks, cause them to be invoked. */
 	if (*rcu_preempt_ctrlblk.rcb.donetail != NULL)
-		raise_softirq(RCU_SOFTIRQ);
+		invoke_rcu_kthread();
 }
 
 /*
@@ -178,12 +447,16 @@
 
 		/* Official start of GP. */
 		rcu_preempt_ctrlblk.gpnum++;
+		RCU_TRACE(rcu_preempt_ctrlblk.n_grace_periods++);
 
 		/* Any blocked RCU readers block new GP. */
 		if (rcu_preempt_blocked_readers_any())
 			rcu_preempt_ctrlblk.gp_tasks =
 				rcu_preempt_ctrlblk.blkd_tasks.next;
 
+		/* Set up for RCU priority boosting. */
+		rcu_preempt_boost_start_gp();
+
 		/* If there is no running reader, CPU is done with GP. */
 		if (!rcu_preempt_running_reader())
 			rcu_preempt_cpu_qs();
@@ -304,14 +577,16 @@
 		 */
 		empty = !rcu_preempt_blocked_readers_cgp();
 		empty_exp = rcu_preempt_ctrlblk.exp_tasks == NULL;
-		np = t->rcu_node_entry.next;
-		if (np == &rcu_preempt_ctrlblk.blkd_tasks)
-			np = NULL;
+		np = rcu_next_node_entry(t);
 		list_del(&t->rcu_node_entry);
 		if (&t->rcu_node_entry == rcu_preempt_ctrlblk.gp_tasks)
 			rcu_preempt_ctrlblk.gp_tasks = np;
 		if (&t->rcu_node_entry == rcu_preempt_ctrlblk.exp_tasks)
 			rcu_preempt_ctrlblk.exp_tasks = np;
+#ifdef CONFIG_RCU_BOOST
+		if (&t->rcu_node_entry == rcu_preempt_ctrlblk.boost_tasks)
+			rcu_preempt_ctrlblk.boost_tasks = np;
+#endif /* #ifdef CONFIG_RCU_BOOST */
 		INIT_LIST_HEAD(&t->rcu_node_entry);
 
 		/*
@@ -331,6 +606,14 @@
 		if (!empty_exp && rcu_preempt_ctrlblk.exp_tasks == NULL)
 			rcu_report_exp_done();
 	}
+#ifdef CONFIG_RCU_BOOST
+	/* Unboost self if was boosted. */
+	if (special & RCU_READ_UNLOCK_BOOSTED) {
+		t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_BOOSTED;
+		rt_mutex_unlock(t->rcu_boost_mutex);
+		t->rcu_boost_mutex = NULL;
+	}
+#endif /* #ifdef CONFIG_RCU_BOOST */
 	local_irq_restore(flags);
 }
 
@@ -374,7 +657,7 @@
 		rcu_preempt_cpu_qs();
 	if (&rcu_preempt_ctrlblk.rcb.rcucblist !=
 	    rcu_preempt_ctrlblk.rcb.donetail)
-		raise_softirq(RCU_SOFTIRQ);
+		invoke_rcu_kthread();
 	if (rcu_preempt_gp_in_progress() &&
 	    rcu_cpu_blocking_cur_gp() &&
 	    rcu_preempt_running_reader())
@@ -383,7 +666,7 @@
 
 /*
  * TINY_PREEMPT_RCU has an extra callback-list tail pointer to
- * update, so this is invoked from __rcu_process_callbacks() to
+ * update, so this is invoked from rcu_process_callbacks() to
  * handle that case.  Of course, it is invoked for all flavors of
  * RCU, but RCU callbacks can appear only on one of the lists, and
  * neither ->nexttail nor ->donetail can possibly be NULL, so there
@@ -400,7 +683,7 @@
  */
 static void rcu_preempt_process_callbacks(void)
 {
-	__rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb);
+	rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb);
 }
 
 /*
@@ -417,6 +700,7 @@
 	local_irq_save(flags);
 	*rcu_preempt_ctrlblk.nexttail = head;
 	rcu_preempt_ctrlblk.nexttail = &head->next;
+	RCU_TRACE(rcu_preempt_ctrlblk.rcb.qlen++);
 	rcu_preempt_start_gp();  /* checks to see if GP needed. */
 	local_irq_restore(flags);
 }
@@ -532,6 +816,7 @@
 
 	/* Wait for tail of ->blkd_tasks list to drain. */
 	if (rcu_preempted_readers_exp())
+		rcu_initiate_expedited_boost();
 		wait_event(sync_rcu_preempt_exp_wq,
 			   !rcu_preempted_readers_exp());
 
@@ -572,6 +857,27 @@
 
 #else /* #ifdef CONFIG_TINY_PREEMPT_RCU */
 
+#ifdef CONFIG_RCU_TRACE
+
+/*
+ * Because preemptible RCU does not exist, it is not necessary to
+ * dump out its statistics.
+ */
+static void show_tiny_preempt_stats(struct seq_file *m)
+{
+}
+
+#endif /* #ifdef CONFIG_RCU_TRACE */
+
+/*
+ * Because preemptible RCU does not exist, it is never necessary to
+ * boost preempted RCU readers.
+ */
+static int rcu_boost(void)
+{
+	return 0;
+}
+
 /*
  * Because preemptible RCU does not exist, it never has any callbacks
  * to check.
@@ -599,17 +905,116 @@
 #endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-
 #include <linux/kernel_stat.h>
 
 /*
  * During boot, we forgive RCU lockdep issues.  After this function is
  * invoked, we start taking RCU lockdep issues seriously.
  */
-void rcu_scheduler_starting(void)
+void __init rcu_scheduler_starting(void)
 {
 	WARN_ON(nr_context_switches() > 0);
 	rcu_scheduler_active = 1;
 }
 
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+#ifdef CONFIG_RCU_BOOST
+#define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO
+#else /* #ifdef CONFIG_RCU_BOOST */
+#define RCU_BOOST_PRIO 1
+#endif /* #else #ifdef CONFIG_RCU_BOOST */
+
+#ifdef CONFIG_RCU_TRACE
+
+#ifdef CONFIG_RCU_BOOST
+
+static void rcu_initiate_boost_trace(void)
+{
+	if (rcu_preempt_ctrlblk.gp_tasks == NULL)
+		rcu_preempt_ctrlblk.n_normal_balk_gp_tasks++;
+	else if (rcu_preempt_ctrlblk.boost_tasks != NULL)
+		rcu_preempt_ctrlblk.n_normal_balk_boost_tasks++;
+	else if (rcu_preempt_ctrlblk.boosted_this_gp != 0)
+		rcu_preempt_ctrlblk.n_normal_balk_boosted++;
+	else if (!ULONG_CMP_GE(jiffies, rcu_preempt_ctrlblk.boost_time))
+		rcu_preempt_ctrlblk.n_normal_balk_notyet++;
+	else
+		rcu_preempt_ctrlblk.n_normal_balk_nos++;
+}
+
+static void rcu_initiate_exp_boost_trace(void)
+{
+	if (list_empty(&rcu_preempt_ctrlblk.blkd_tasks))
+		rcu_preempt_ctrlblk.n_exp_balk_blkd_tasks++;
+	else
+		rcu_preempt_ctrlblk.n_exp_balk_nos++;
+}
+
+#endif /* #ifdef CONFIG_RCU_BOOST */
+
+static void rcu_trace_sub_qlen(struct rcu_ctrlblk *rcp, int n)
+{
+	unsigned long flags;
+
+	raw_local_irq_save(flags);
+	rcp->qlen -= n;
+	raw_local_irq_restore(flags);
+}
+
+/*
+ * Dump statistics for TINY_RCU, such as they are.
+ */
+static int show_tiny_stats(struct seq_file *m, void *unused)
+{
+	show_tiny_preempt_stats(m);
+	seq_printf(m, "rcu_sched: qlen: %ld\n", rcu_sched_ctrlblk.qlen);
+	seq_printf(m, "rcu_bh: qlen: %ld\n", rcu_bh_ctrlblk.qlen);
+	return 0;
+}
+
+static int show_tiny_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, show_tiny_stats, NULL);
+}
+
+static const struct file_operations show_tiny_stats_fops = {
+	.owner = THIS_MODULE,
+	.open = show_tiny_stats_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static struct dentry *rcudir;
+
+static int __init rcutiny_trace_init(void)
+{
+	struct dentry *retval;
+
+	rcudir = debugfs_create_dir("rcu", NULL);
+	if (!rcudir)
+		goto free_out;
+	retval = debugfs_create_file("rcudata", 0444, rcudir,
+				     NULL, &show_tiny_stats_fops);
+	if (!retval)
+		goto free_out;
+	return 0;
+free_out:
+	debugfs_remove_recursive(rcudir);
+	return 1;
+}
+
+static void __exit rcutiny_trace_cleanup(void)
+{
+	debugfs_remove_recursive(rcudir);
+}
+
+module_init(rcutiny_trace_init);
+module_exit(rcutiny_trace_cleanup);
+
+MODULE_AUTHOR("Paul E. McKenney");
+MODULE_DESCRIPTION("Read-Copy Update tracing for tiny implementation");
+MODULE_LICENSE("GPL");
+
+#endif /* #ifdef CONFIG_RCU_TRACE */
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 9d8e8fb..89613f9 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -47,6 +47,7 @@
 #include <linux/srcu.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
+#include <linux/sched.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and "
@@ -64,6 +65,9 @@
 static int fqs_duration = 0;	/* Duration of bursts (us), 0 to disable. */
 static int fqs_holdoff = 0;	/* Hold time within burst (us). */
 static int fqs_stutter = 3;	/* Wait time between bursts (s). */
+static int test_boost = 1;	/* Test RCU prio boost: 0=no, 1=maybe, 2=yes. */
+static int test_boost_interval = 7; /* Interval between boost tests, seconds. */
+static int test_boost_duration = 4; /* Duration of each boost test, seconds. */
 static char *torture_type = "rcu"; /* What RCU implementation to torture. */
 
 module_param(nreaders, int, 0444);
@@ -88,6 +92,12 @@
 MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)");
 module_param(fqs_stutter, int, 0444);
 MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)");
+module_param(test_boost, int, 0444);
+MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
+module_param(test_boost_interval, int, 0444);
+MODULE_PARM_DESC(test_boost_interval, "Interval between boost tests, seconds.");
+module_param(test_boost_duration, int, 0444);
+MODULE_PARM_DESC(test_boost_duration, "Duration of each boost test, seconds.");
 module_param(torture_type, charp, 0444);
 MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, srcu)");
 
@@ -109,6 +119,7 @@
 static struct task_struct *shuffler_task;
 static struct task_struct *stutter_task;
 static struct task_struct *fqs_task;
+static struct task_struct *boost_tasks[NR_CPUS];
 
 #define RCU_TORTURE_PIPE_LEN 10
 
@@ -134,6 +145,12 @@
 static atomic_t n_rcu_torture_free;
 static atomic_t n_rcu_torture_mberror;
 static atomic_t n_rcu_torture_error;
+static long n_rcu_torture_boost_ktrerror;
+static long n_rcu_torture_boost_rterror;
+static long n_rcu_torture_boost_allocerror;
+static long n_rcu_torture_boost_afferror;
+static long n_rcu_torture_boost_failure;
+static long n_rcu_torture_boosts;
 static long n_rcu_torture_timers;
 static struct list_head rcu_torture_removed;
 static cpumask_var_t shuffle_tmp_mask;
@@ -147,6 +164,16 @@
 #endif
 int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT;
 
+#ifdef CONFIG_RCU_BOOST
+#define rcu_can_boost() 1
+#else /* #ifdef CONFIG_RCU_BOOST */
+#define rcu_can_boost() 0
+#endif /* #else #ifdef CONFIG_RCU_BOOST */
+
+static unsigned long boost_starttime;	/* jiffies of next boost test start. */
+DEFINE_MUTEX(boost_mutex);		/* protect setting boost_starttime */
+					/*  and boost task create/destroy. */
+
 /* Mediate rmmod and system shutdown.  Concurrent rmmod & shutdown illegal! */
 
 #define FULLSTOP_DONTSTOP 0	/* Normal operation. */
@@ -277,6 +304,7 @@
 	void (*fqs)(void);
 	int (*stats)(char *page);
 	int irq_capable;
+	int can_boost;
 	char *name;
 };
 
@@ -366,6 +394,7 @@
 	.fqs		= rcu_force_quiescent_state,
 	.stats		= NULL,
 	.irq_capable	= 1,
+	.can_boost	= rcu_can_boost(),
 	.name		= "rcu"
 };
 
@@ -408,6 +437,7 @@
 	.fqs		= rcu_force_quiescent_state,
 	.stats		= NULL,
 	.irq_capable	= 1,
+	.can_boost	= rcu_can_boost(),
 	.name		= "rcu_sync"
 };
 
@@ -424,6 +454,7 @@
 	.fqs		= rcu_force_quiescent_state,
 	.stats		= NULL,
 	.irq_capable	= 1,
+	.can_boost	= rcu_can_boost(),
 	.name		= "rcu_expedited"
 };
 
@@ -684,6 +715,110 @@
 };
 
 /*
+ * RCU torture priority-boost testing.  Runs one real-time thread per
+ * CPU for moderate bursts, repeatedly registering RCU callbacks and
+ * spinning waiting for them to be invoked.  If a given callback takes
+ * too long to be invoked, we assume that priority inversion has occurred.
+ */
+
+struct rcu_boost_inflight {
+	struct rcu_head rcu;
+	int inflight;
+};
+
+static void rcu_torture_boost_cb(struct rcu_head *head)
+{
+	struct rcu_boost_inflight *rbip =
+		container_of(head, struct rcu_boost_inflight, rcu);
+
+	smp_mb(); /* Ensure RCU-core accesses precede clearing ->inflight */
+	rbip->inflight = 0;
+}
+
+static int rcu_torture_boost(void *arg)
+{
+	unsigned long call_rcu_time;
+	unsigned long endtime;
+	unsigned long oldstarttime;
+	struct rcu_boost_inflight rbi = { .inflight = 0 };
+	struct sched_param sp;
+
+	VERBOSE_PRINTK_STRING("rcu_torture_boost started");
+
+	/* Set real-time priority. */
+	sp.sched_priority = 1;
+	if (sched_setscheduler(current, SCHED_FIFO, &sp) < 0) {
+		VERBOSE_PRINTK_STRING("rcu_torture_boost RT prio failed!");
+		n_rcu_torture_boost_rterror++;
+	}
+
+	/* Each pass through the following loop does one boost-test cycle. */
+	do {
+		/* Wait for the next test interval. */
+		oldstarttime = boost_starttime;
+		while (jiffies - oldstarttime > ULONG_MAX / 2) {
+			schedule_timeout_uninterruptible(1);
+			rcu_stutter_wait("rcu_torture_boost");
+			if (kthread_should_stop() ||
+			    fullstop != FULLSTOP_DONTSTOP)
+				goto checkwait;
+		}
+
+		/* Do one boost-test interval. */
+		endtime = oldstarttime + test_boost_duration * HZ;
+		call_rcu_time = jiffies;
+		while (jiffies - endtime > ULONG_MAX / 2) {
+			/* If we don't have a callback in flight, post one. */
+			if (!rbi.inflight) {
+				smp_mb(); /* RCU core before ->inflight = 1. */
+				rbi.inflight = 1;
+				call_rcu(&rbi.rcu, rcu_torture_boost_cb);
+				if (jiffies - call_rcu_time >
+					 test_boost_duration * HZ - HZ / 2) {
+					VERBOSE_PRINTK_STRING("rcu_torture_boost boosting failed");
+					n_rcu_torture_boost_failure++;
+				}
+				call_rcu_time = jiffies;
+			}
+			cond_resched();
+			rcu_stutter_wait("rcu_torture_boost");
+			if (kthread_should_stop() ||
+			    fullstop != FULLSTOP_DONTSTOP)
+				goto checkwait;
+		}
+
+		/*
+		 * Set the start time of the next test interval.
+		 * Yes, this is vulnerable to long delays, but such
+		 * delays simply cause a false negative for the next
+		 * interval.  Besides, we are running at RT priority,
+		 * so delays should be relatively rare.
+		 */
+		while (oldstarttime == boost_starttime) {
+			if (mutex_trylock(&boost_mutex)) {
+				boost_starttime = jiffies +
+						  test_boost_interval * HZ;
+				n_rcu_torture_boosts++;
+				mutex_unlock(&boost_mutex);
+				break;
+			}
+			schedule_timeout_uninterruptible(1);
+		}
+
+		/* Go do the stutter. */
+checkwait:	rcu_stutter_wait("rcu_torture_boost");
+	} while (!kthread_should_stop() && fullstop  == FULLSTOP_DONTSTOP);
+
+	/* Clean up and exit. */
+	VERBOSE_PRINTK_STRING("rcu_torture_boost task stopping");
+	rcutorture_shutdown_absorb("rcu_torture_boost");
+	while (!kthread_should_stop() || rbi.inflight)
+		schedule_timeout_uninterruptible(1);
+	smp_mb(); /* order accesses to ->inflight before stack-frame death. */
+	return 0;
+}
+
+/*
  * RCU torture force-quiescent-state kthread.  Repeatedly induces
  * bursts of calls to force_quiescent_state(), increasing the probability
  * of occurrence of some important types of race conditions.
@@ -933,7 +1068,8 @@
 	cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
 	cnt += sprintf(&page[cnt],
 		       "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d "
-		       "rtmbe: %d nt: %ld",
+		       "rtmbe: %d rtbke: %ld rtbre: %ld rtbae: %ld rtbafe: %ld "
+		       "rtbf: %ld rtb: %ld nt: %ld",
 		       rcu_torture_current,
 		       rcu_torture_current_version,
 		       list_empty(&rcu_torture_freelist),
@@ -941,8 +1077,19 @@
 		       atomic_read(&n_rcu_torture_alloc_fail),
 		       atomic_read(&n_rcu_torture_free),
 		       atomic_read(&n_rcu_torture_mberror),
+		       n_rcu_torture_boost_ktrerror,
+		       n_rcu_torture_boost_rterror,
+		       n_rcu_torture_boost_allocerror,
+		       n_rcu_torture_boost_afferror,
+		       n_rcu_torture_boost_failure,
+		       n_rcu_torture_boosts,
 		       n_rcu_torture_timers);
-	if (atomic_read(&n_rcu_torture_mberror) != 0)
+	if (atomic_read(&n_rcu_torture_mberror) != 0 ||
+	    n_rcu_torture_boost_ktrerror != 0 ||
+	    n_rcu_torture_boost_rterror != 0 ||
+	    n_rcu_torture_boost_allocerror != 0 ||
+	    n_rcu_torture_boost_afferror != 0 ||
+	    n_rcu_torture_boost_failure != 0)
 		cnt += sprintf(&page[cnt], " !!!");
 	cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
 	if (i > 1) {
@@ -1094,22 +1241,91 @@
 }
 
 static inline void
-rcu_torture_print_module_parms(char *tag)
+rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, char *tag)
 {
 	printk(KERN_ALERT "%s" TORTURE_FLAG
 		"--- %s: nreaders=%d nfakewriters=%d "
 		"stat_interval=%d verbose=%d test_no_idle_hz=%d "
 		"shuffle_interval=%d stutter=%d irqreader=%d "
-		"fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d\n",
+		"fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
+		"test_boost=%d/%d test_boost_interval=%d "
+		"test_boost_duration=%d\n",
 		torture_type, tag, nrealreaders, nfakewriters,
 		stat_interval, verbose, test_no_idle_hz, shuffle_interval,
-		stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter);
+		stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
+		test_boost, cur_ops->can_boost,
+		test_boost_interval, test_boost_duration);
 }
 
-static struct notifier_block rcutorture_nb = {
+static struct notifier_block rcutorture_shutdown_nb = {
 	.notifier_call = rcutorture_shutdown_notify,
 };
 
+static void rcutorture_booster_cleanup(int cpu)
+{
+	struct task_struct *t;
+
+	if (boost_tasks[cpu] == NULL)
+		return;
+	mutex_lock(&boost_mutex);
+	VERBOSE_PRINTK_STRING("Stopping rcu_torture_boost task");
+	t = boost_tasks[cpu];
+	boost_tasks[cpu] = NULL;
+	mutex_unlock(&boost_mutex);
+
+	/* This must be outside of the mutex, otherwise deadlock! */
+	kthread_stop(t);
+}
+
+static int rcutorture_booster_init(int cpu)
+{
+	int retval;
+
+	if (boost_tasks[cpu] != NULL)
+		return 0;  /* Already created, nothing more to do. */
+
+	/* Don't allow time recalculation while creating a new task. */
+	mutex_lock(&boost_mutex);
+	VERBOSE_PRINTK_STRING("Creating rcu_torture_boost task");
+	boost_tasks[cpu] = kthread_create(rcu_torture_boost, NULL,
+					  "rcu_torture_boost");
+	if (IS_ERR(boost_tasks[cpu])) {
+		retval = PTR_ERR(boost_tasks[cpu]);
+		VERBOSE_PRINTK_STRING("rcu_torture_boost task create failed");
+		n_rcu_torture_boost_ktrerror++;
+		boost_tasks[cpu] = NULL;
+		mutex_unlock(&boost_mutex);
+		return retval;
+	}
+	kthread_bind(boost_tasks[cpu], cpu);
+	wake_up_process(boost_tasks[cpu]);
+	mutex_unlock(&boost_mutex);
+	return 0;
+}
+
+static int rcutorture_cpu_notify(struct notifier_block *self,
+				 unsigned long action, void *hcpu)
+{
+	long cpu = (long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_DOWN_FAILED:
+		(void)rcutorture_booster_init(cpu);
+		break;
+	case CPU_DOWN_PREPARE:
+		rcutorture_booster_cleanup(cpu);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block rcutorture_cpu_nb = {
+	.notifier_call = rcutorture_cpu_notify,
+};
+
 static void
 rcu_torture_cleanup(void)
 {
@@ -1127,7 +1343,7 @@
 	}
 	fullstop = FULLSTOP_RMMOD;
 	mutex_unlock(&fullstop_mutex);
-	unregister_reboot_notifier(&rcutorture_nb);
+	unregister_reboot_notifier(&rcutorture_shutdown_nb);
 	if (stutter_task) {
 		VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
 		kthread_stop(stutter_task);
@@ -1184,6 +1400,12 @@
 		kthread_stop(fqs_task);
 	}
 	fqs_task = NULL;
+	if ((test_boost == 1 && cur_ops->can_boost) ||
+	    test_boost == 2) {
+		unregister_cpu_notifier(&rcutorture_cpu_nb);
+		for_each_possible_cpu(i)
+			rcutorture_booster_cleanup(i);
+	}
 
 	/* Wait for all RCU callbacks to fire.  */
 
@@ -1195,9 +1417,9 @@
 	if (cur_ops->cleanup)
 		cur_ops->cleanup();
 	if (atomic_read(&n_rcu_torture_error))
-		rcu_torture_print_module_parms("End of test: FAILURE");
+		rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
 	else
-		rcu_torture_print_module_parms("End of test: SUCCESS");
+		rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
 }
 
 static int __init
@@ -1242,7 +1464,7 @@
 		nrealreaders = nreaders;
 	else
 		nrealreaders = 2 * num_online_cpus();
-	rcu_torture_print_module_parms("Start of test");
+	rcu_torture_print_module_parms(cur_ops, "Start of test");
 	fullstop = FULLSTOP_DONTSTOP;
 
 	/* Set up the freelist. */
@@ -1263,6 +1485,12 @@
 	atomic_set(&n_rcu_torture_free, 0);
 	atomic_set(&n_rcu_torture_mberror, 0);
 	atomic_set(&n_rcu_torture_error, 0);
+	n_rcu_torture_boost_ktrerror = 0;
+	n_rcu_torture_boost_rterror = 0;
+	n_rcu_torture_boost_allocerror = 0;
+	n_rcu_torture_boost_afferror = 0;
+	n_rcu_torture_boost_failure = 0;
+	n_rcu_torture_boosts = 0;
 	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
 		atomic_set(&rcu_torture_wcount[i], 0);
 	for_each_possible_cpu(cpu) {
@@ -1376,7 +1604,27 @@
 			goto unwind;
 		}
 	}
-	register_reboot_notifier(&rcutorture_nb);
+	if (test_boost_interval < 1)
+		test_boost_interval = 1;
+	if (test_boost_duration < 2)
+		test_boost_duration = 2;
+	if ((test_boost == 1 && cur_ops->can_boost) ||
+	    test_boost == 2) {
+		int retval;
+
+		boost_starttime = jiffies + test_boost_interval * HZ;
+		register_cpu_notifier(&rcutorture_cpu_nb);
+		for_each_possible_cpu(i) {
+			if (cpu_is_offline(i))
+				continue;  /* Heuristic: CPU can go offline. */
+			retval = rcutorture_booster_init(i);
+			if (retval < 0) {
+				firsterr = retval;
+				goto unwind;
+			}
+		}
+	}
+	register_reboot_notifier(&rcutorture_shutdown_nb);
 	mutex_unlock(&fullstop_mutex);
 	return 0;
 
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index ccdc04c..dd4aea8 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -67,9 +67,6 @@
 	.gpnum = -300, \
 	.completed = -300, \
 	.onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname.onofflock), \
-	.orphan_cbs_list = NULL, \
-	.orphan_cbs_tail = &structname.orphan_cbs_list, \
-	.orphan_qlen = 0, \
 	.fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname.fqslock), \
 	.n_force_qs = 0, \
 	.n_force_qs_ngp = 0, \
@@ -367,8 +364,8 @@
 	WARN_ON_ONCE(rdtp->dynticks & 0x1);
 
 	/* If the interrupt queued a callback, get out of dyntick mode. */
-	if (__get_cpu_var(rcu_sched_data).nxtlist ||
-	    __get_cpu_var(rcu_bh_data).nxtlist)
+	if (__this_cpu_read(rcu_sched_data.nxtlist) ||
+	    __this_cpu_read(rcu_bh_data.nxtlist))
 		set_need_resched();
 }
 
@@ -620,9 +617,17 @@
 static void __note_new_gpnum(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp)
 {
 	if (rdp->gpnum != rnp->gpnum) {
-		rdp->qs_pending = 1;
-		rdp->passed_quiesc = 0;
+		/*
+		 * If the current grace period is waiting for this CPU,
+		 * set up to detect a quiescent state, otherwise don't
+		 * go looking for one.
+		 */
 		rdp->gpnum = rnp->gpnum;
+		if (rnp->qsmask & rdp->grpmask) {
+			rdp->qs_pending = 1;
+			rdp->passed_quiesc = 0;
+		} else
+			rdp->qs_pending = 0;
 	}
 }
 
@@ -681,6 +686,24 @@
 
 		/* Remember that we saw this grace-period completion. */
 		rdp->completed = rnp->completed;
+
+		/*
+		 * If we were in an extended quiescent state, we may have
+		 * missed some grace periods that others CPUs handled on
+		 * our behalf. Catch up with this state to avoid noting
+		 * spurious new grace periods.  If another grace period
+		 * has started, then rnp->gpnum will have advanced, so
+		 * we will detect this later on.
+		 */
+		if (ULONG_CMP_LT(rdp->gpnum, rdp->completed))
+			rdp->gpnum = rdp->completed;
+
+		/*
+		 * If RCU does not need a quiescent state from this CPU,
+		 * then make sure that this CPU doesn't go looking for one.
+		 */
+		if ((rnp->qsmask & rdp->grpmask) == 0)
+			rdp->qs_pending = 0;
 	}
 }
 
@@ -984,53 +1007,31 @@
 #ifdef CONFIG_HOTPLUG_CPU
 
 /*
- * Move a dying CPU's RCU callbacks to the ->orphan_cbs_list for the
- * specified flavor of RCU.  The callbacks will be adopted by the next
- * _rcu_barrier() invocation or by the CPU_DEAD notifier, whichever
- * comes first.  Because this is invoked from the CPU_DYING notifier,
- * irqs are already disabled.
+ * Move a dying CPU's RCU callbacks to online CPU's callback list.
+ * Synchronization is not required because this function executes
+ * in stop_machine() context.
  */
-static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
+static void rcu_send_cbs_to_online(struct rcu_state *rsp)
 {
 	int i;
+	/* current DYING CPU is cleared in the cpu_online_mask */
+	int receive_cpu = cpumask_any(cpu_online_mask);
 	struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
+	struct rcu_data *receive_rdp = per_cpu_ptr(rsp->rda, receive_cpu);
 
 	if (rdp->nxtlist == NULL)
 		return;  /* irqs disabled, so comparison is stable. */
-	raw_spin_lock(&rsp->onofflock);  /* irqs already disabled. */
-	*rsp->orphan_cbs_tail = rdp->nxtlist;
-	rsp->orphan_cbs_tail = rdp->nxttail[RCU_NEXT_TAIL];
+
+	*receive_rdp->nxttail[RCU_NEXT_TAIL] = rdp->nxtlist;
+	receive_rdp->nxttail[RCU_NEXT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+	receive_rdp->qlen += rdp->qlen;
+	receive_rdp->n_cbs_adopted += rdp->qlen;
+	rdp->n_cbs_orphaned += rdp->qlen;
+
 	rdp->nxtlist = NULL;
 	for (i = 0; i < RCU_NEXT_SIZE; i++)
 		rdp->nxttail[i] = &rdp->nxtlist;
-	rsp->orphan_qlen += rdp->qlen;
-	rdp->n_cbs_orphaned += rdp->qlen;
 	rdp->qlen = 0;
-	raw_spin_unlock(&rsp->onofflock);  /* irqs remain disabled. */
-}
-
-/*
- * Adopt previously orphaned RCU callbacks.
- */
-static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
-{
-	unsigned long flags;
-	struct rcu_data *rdp;
-
-	raw_spin_lock_irqsave(&rsp->onofflock, flags);
-	rdp = this_cpu_ptr(rsp->rda);
-	if (rsp->orphan_cbs_list == NULL) {
-		raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
-		return;
-	}
-	*rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_list;
-	rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_cbs_tail;
-	rdp->qlen += rsp->orphan_qlen;
-	rdp->n_cbs_adopted += rsp->orphan_qlen;
-	rsp->orphan_cbs_list = NULL;
-	rsp->orphan_cbs_tail = &rsp->orphan_cbs_list;
-	rsp->orphan_qlen = 0;
-	raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
 }
 
 /*
@@ -1081,8 +1082,6 @@
 		raw_spin_unlock_irqrestore(&rnp->lock, flags);
 	if (need_report & RCU_OFL_TASKS_EXP_GP)
 		rcu_report_exp_rnp(rsp, rnp);
-
-	rcu_adopt_orphan_cbs(rsp);
 }
 
 /*
@@ -1100,11 +1099,7 @@
 
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
 
-static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
-{
-}
-
-static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+static void rcu_send_cbs_to_online(struct rcu_state *rsp)
 {
 }
 
@@ -1440,22 +1435,11 @@
 	 */
 	local_irq_save(flags);
 	rdp = this_cpu_ptr(rsp->rda);
-	rcu_process_gp_end(rsp, rdp);
-	check_for_new_grace_period(rsp, rdp);
 
 	/* Add the callback to our list. */
 	*rdp->nxttail[RCU_NEXT_TAIL] = head;
 	rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
 
-	/* Start a new grace period if one not already started. */
-	if (!rcu_gp_in_progress(rsp)) {
-		unsigned long nestflag;
-		struct rcu_node *rnp_root = rcu_get_root(rsp);
-
-		raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
-		rcu_start_gp(rsp, nestflag);  /* releases rnp_root->lock. */
-	}
-
 	/*
 	 * Force the grace period if too many callbacks or too long waiting.
 	 * Enforce hysteresis, and don't invoke force_quiescent_state()
@@ -1464,12 +1448,27 @@
 	 * is the only one waiting for a grace period to complete.
 	 */
 	if (unlikely(++rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
-		rdp->blimit = LONG_MAX;
-		if (rsp->n_force_qs == rdp->n_force_qs_snap &&
-		    *rdp->nxttail[RCU_DONE_TAIL] != head)
-			force_quiescent_state(rsp, 0);
-		rdp->n_force_qs_snap = rsp->n_force_qs;
-		rdp->qlen_last_fqs_check = rdp->qlen;
+
+		/* Are we ignoring a completed grace period? */
+		rcu_process_gp_end(rsp, rdp);
+		check_for_new_grace_period(rsp, rdp);
+
+		/* Start a new grace period if one not already started. */
+		if (!rcu_gp_in_progress(rsp)) {
+			unsigned long nestflag;
+			struct rcu_node *rnp_root = rcu_get_root(rsp);
+
+			raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
+			rcu_start_gp(rsp, nestflag);  /* rlses rnp_root->lock */
+		} else {
+			/* Give the grace period a kick. */
+			rdp->blimit = LONG_MAX;
+			if (rsp->n_force_qs == rdp->n_force_qs_snap &&
+			    *rdp->nxttail[RCU_DONE_TAIL] != head)
+				force_quiescent_state(rsp, 0);
+			rdp->n_force_qs_snap = rsp->n_force_qs;
+			rdp->qlen_last_fqs_check = rdp->qlen;
+		}
 	} else if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies))
 		force_quiescent_state(rsp, 1);
 	local_irq_restore(flags);
@@ -1699,13 +1698,12 @@
 	 * decrement rcu_barrier_cpu_count -- otherwise the first CPU
 	 * might complete its grace period before all of the other CPUs
 	 * did their increment, causing this function to return too
-	 * early.
+	 * early.  Note that on_each_cpu() disables irqs, which prevents
+	 * any CPUs from coming online or going offline until each online
+	 * CPU has queued its RCU-barrier callback.
 	 */
 	atomic_set(&rcu_barrier_cpu_count, 1);
-	preempt_disable(); /* stop CPU_DYING from filling orphan_cbs_list */
-	rcu_adopt_orphan_cbs(rsp);
 	on_each_cpu(rcu_barrier_func, (void *)call_rcu_func, 1);
-	preempt_enable(); /* CPU_DYING can again fill orphan_cbs_list */
 	if (atomic_dec_and_test(&rcu_barrier_cpu_count))
 		complete(&rcu_barrier_completion);
 	wait_for_completion(&rcu_barrier_completion);
@@ -1831,18 +1829,13 @@
 	case CPU_DYING:
 	case CPU_DYING_FROZEN:
 		/*
-		 * preempt_disable() in _rcu_barrier() prevents stop_machine(),
-		 * so when "on_each_cpu(rcu_barrier_func, (void *)type, 1);"
-		 * returns, all online cpus have queued rcu_barrier_func().
-		 * The dying CPU clears its cpu_online_mask bit and
-		 * moves all of its RCU callbacks to ->orphan_cbs_list
-		 * in the context of stop_machine(), so subsequent calls
-		 * to _rcu_barrier() will adopt these callbacks and only
-		 * then queue rcu_barrier_func() on all remaining CPUs.
+		 * The whole machine is "stopped" except this CPU, so we can
+		 * touch any data without introducing corruption. We send the
+		 * dying CPU's callbacks to an arbitrarily chosen online CPU.
 		 */
-		rcu_send_cbs_to_orphanage(&rcu_bh_state);
-		rcu_send_cbs_to_orphanage(&rcu_sched_state);
-		rcu_preempt_send_cbs_to_orphanage();
+		rcu_send_cbs_to_online(&rcu_bh_state);
+		rcu_send_cbs_to_online(&rcu_sched_state);
+		rcu_preempt_send_cbs_to_online();
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
@@ -1880,8 +1873,9 @@
 {
 	int i;
 
-	for (i = NUM_RCU_LVLS - 1; i >= 0; i--)
+	for (i = NUM_RCU_LVLS - 1; i > 0; i--)
 		rsp->levelspread[i] = CONFIG_RCU_FANOUT;
+	rsp->levelspread[0] = RCU_FANOUT_LEAF;
 }
 #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */
 static void __init rcu_init_levelspread(struct rcu_state *rsp)
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 91d4170..e8f057e 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -31,46 +31,51 @@
 /*
  * Define shape of hierarchy based on NR_CPUS and CONFIG_RCU_FANOUT.
  * In theory, it should be possible to add more levels straightforwardly.
- * In practice, this has not been tested, so there is probably some
- * bug somewhere.
+ * In practice, this did work well going from three levels to four.
+ * Of course, your mileage may vary.
  */
 #define MAX_RCU_LVLS 4
-#define RCU_FANOUT	      (CONFIG_RCU_FANOUT)
-#define RCU_FANOUT_SQ	      (RCU_FANOUT * RCU_FANOUT)
-#define RCU_FANOUT_CUBE	      (RCU_FANOUT_SQ * RCU_FANOUT)
-#define RCU_FANOUT_FOURTH     (RCU_FANOUT_CUBE * RCU_FANOUT)
+#if CONFIG_RCU_FANOUT > 16
+#define RCU_FANOUT_LEAF       16
+#else /* #if CONFIG_RCU_FANOUT > 16 */
+#define RCU_FANOUT_LEAF       (CONFIG_RCU_FANOUT)
+#endif /* #else #if CONFIG_RCU_FANOUT > 16 */
+#define RCU_FANOUT_1	      (RCU_FANOUT_LEAF)
+#define RCU_FANOUT_2	      (RCU_FANOUT_1 * CONFIG_RCU_FANOUT)
+#define RCU_FANOUT_3	      (RCU_FANOUT_2 * CONFIG_RCU_FANOUT)
+#define RCU_FANOUT_4	      (RCU_FANOUT_3 * CONFIG_RCU_FANOUT)
 
-#if NR_CPUS <= RCU_FANOUT
+#if NR_CPUS <= RCU_FANOUT_1
 #  define NUM_RCU_LVLS	      1
 #  define NUM_RCU_LVL_0	      1
 #  define NUM_RCU_LVL_1	      (NR_CPUS)
 #  define NUM_RCU_LVL_2	      0
 #  define NUM_RCU_LVL_3	      0
 #  define NUM_RCU_LVL_4	      0
-#elif NR_CPUS <= RCU_FANOUT_SQ
+#elif NR_CPUS <= RCU_FANOUT_2
 #  define NUM_RCU_LVLS	      2
 #  define NUM_RCU_LVL_0	      1
-#  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
+#  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
 #  define NUM_RCU_LVL_2	      (NR_CPUS)
 #  define NUM_RCU_LVL_3	      0
 #  define NUM_RCU_LVL_4	      0
-#elif NR_CPUS <= RCU_FANOUT_CUBE
+#elif NR_CPUS <= RCU_FANOUT_3
 #  define NUM_RCU_LVLS	      3
 #  define NUM_RCU_LVL_0	      1
-#  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ)
-#  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
-#  define NUM_RCU_LVL_3	      NR_CPUS
+#  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
+#  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+#  define NUM_RCU_LVL_3	      (NR_CPUS)
 #  define NUM_RCU_LVL_4	      0
-#elif NR_CPUS <= RCU_FANOUT_FOURTH
+#elif NR_CPUS <= RCU_FANOUT_4
 #  define NUM_RCU_LVLS	      4
 #  define NUM_RCU_LVL_0	      1
-#  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_CUBE)
-#  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ)
-#  define NUM_RCU_LVL_3	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
-#  define NUM_RCU_LVL_4	      NR_CPUS
+#  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
+#  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
+#  define NUM_RCU_LVL_3	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+#  define NUM_RCU_LVL_4	      (NR_CPUS)
 #else
 # error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
-#endif /* #if (NR_CPUS) <= RCU_FANOUT */
+#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
 
 #define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3 + NUM_RCU_LVL_4)
 #define NUM_RCU_NODES (RCU_SUM - NR_CPUS)
@@ -203,8 +208,8 @@
 	long		qlen_last_fqs_check;
 					/* qlen at last check for QS forcing */
 	unsigned long	n_cbs_invoked;	/* count of RCU cbs invoked. */
-	unsigned long	n_cbs_orphaned;	/* RCU cbs sent to orphanage. */
-	unsigned long	n_cbs_adopted;	/* RCU cbs adopted from orphanage. */
+	unsigned long   n_cbs_orphaned; /* RCU cbs orphaned by dying CPU */
+	unsigned long   n_cbs_adopted;  /* RCU cbs adopted from dying CPU */
 	unsigned long	n_force_qs_snap;
 					/* did other CPU force QS recently? */
 	long		blimit;		/* Upper limit on a processed batch */
@@ -309,15 +314,7 @@
 	/* End of fields guarded by root rcu_node's lock. */
 
 	raw_spinlock_t onofflock;		/* exclude on/offline and */
-						/*  starting new GP.  Also */
-						/*  protects the following */
-						/*  orphan_cbs fields. */
-	struct rcu_head *orphan_cbs_list;	/* list of rcu_head structs */
-						/*  orphaned by all CPUs in */
-						/*  a given leaf rcu_node */
-						/*  going offline. */
-	struct rcu_head **orphan_cbs_tail;	/* And tail pointer. */
-	long orphan_qlen;			/* Number of orphaned cbs. */
+						/*  starting new GP. */
 	raw_spinlock_t fqslock;			/* Only one task forcing */
 						/*  quiescent states. */
 	unsigned long jiffies_force_qs;		/* Time at which to invoke */
@@ -390,7 +387,7 @@
 static int rcu_preempt_pending(int cpu);
 static int rcu_preempt_needs_cpu(int cpu);
 static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
-static void rcu_preempt_send_cbs_to_orphanage(void);
+static void rcu_preempt_send_cbs_to_online(void);
 static void __init __rcu_init_preempt(void);
 static void rcu_needs_cpu_flush(void);
 
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 71a4147..a363871 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -25,6 +25,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/stop_machine.h>
 
 /*
  * Check the RCU kernel configuration parameters and print informative
@@ -773,11 +774,11 @@
 }
 
 /*
- * Move preemptable RCU's callbacks to ->orphan_cbs_list.
+ * Move preemptable RCU's callbacks from dying CPU to other online CPU.
  */
-static void rcu_preempt_send_cbs_to_orphanage(void)
+static void rcu_preempt_send_cbs_to_online(void)
 {
-	rcu_send_cbs_to_orphanage(&rcu_preempt_state);
+	rcu_send_cbs_to_online(&rcu_preempt_state);
 }
 
 /*
@@ -1001,7 +1002,7 @@
 /*
  * Because there is no preemptable RCU, there are no callbacks to move.
  */
-static void rcu_preempt_send_cbs_to_orphanage(void)
+static void rcu_preempt_send_cbs_to_online(void)
 {
 }
 
@@ -1014,6 +1015,132 @@
 
 #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
 
+#ifndef CONFIG_SMP
+
+void synchronize_sched_expedited(void)
+{
+	cond_resched();
+}
+EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
+
+#else /* #ifndef CONFIG_SMP */
+
+static atomic_t sync_sched_expedited_started = ATOMIC_INIT(0);
+static atomic_t sync_sched_expedited_done = ATOMIC_INIT(0);
+
+static int synchronize_sched_expedited_cpu_stop(void *data)
+{
+	/*
+	 * There must be a full memory barrier on each affected CPU
+	 * between the time that try_stop_cpus() is called and the
+	 * time that it returns.
+	 *
+	 * In the current initial implementation of cpu_stop, the
+	 * above condition is already met when the control reaches
+	 * this point and the following smp_mb() is not strictly
+	 * necessary.  Do smp_mb() anyway for documentation and
+	 * robustness against future implementation changes.
+	 */
+	smp_mb(); /* See above comment block. */
+	return 0;
+}
+
+/*
+ * Wait for an rcu-sched grace period to elapse, but use "big hammer"
+ * approach to force grace period to end quickly.  This consumes
+ * significant time on all CPUs, and is thus not recommended for
+ * any sort of common-case code.
+ *
+ * Note that it is illegal to call this function while holding any
+ * lock that is acquired by a CPU-hotplug notifier.  Failing to
+ * observe this restriction will result in deadlock.
+ *
+ * This implementation can be thought of as an application of ticket
+ * locking to RCU, with sync_sched_expedited_started and
+ * sync_sched_expedited_done taking on the roles of the halves
+ * of the ticket-lock word.  Each task atomically increments
+ * sync_sched_expedited_started upon entry, snapshotting the old value,
+ * then attempts to stop all the CPUs.  If this succeeds, then each
+ * CPU will have executed a context switch, resulting in an RCU-sched
+ * grace period.  We are then done, so we use atomic_cmpxchg() to
+ * update sync_sched_expedited_done to match our snapshot -- but
+ * only if someone else has not already advanced past our snapshot.
+ *
+ * On the other hand, if try_stop_cpus() fails, we check the value
+ * of sync_sched_expedited_done.  If it has advanced past our
+ * initial snapshot, then someone else must have forced a grace period
+ * some time after we took our snapshot.  In this case, our work is
+ * done for us, and we can simply return.  Otherwise, we try again,
+ * but keep our initial snapshot for purposes of checking for someone
+ * doing our work for us.
+ *
+ * If we fail too many times in a row, we fall back to synchronize_sched().
+ */
+void synchronize_sched_expedited(void)
+{
+	int firstsnap, s, snap, trycount = 0;
+
+	/* Note that atomic_inc_return() implies full memory barrier. */
+	firstsnap = snap = atomic_inc_return(&sync_sched_expedited_started);
+	get_online_cpus();
+
+	/*
+	 * Each pass through the following loop attempts to force a
+	 * context switch on each CPU.
+	 */
+	while (try_stop_cpus(cpu_online_mask,
+			     synchronize_sched_expedited_cpu_stop,
+			     NULL) == -EAGAIN) {
+		put_online_cpus();
+
+		/* No joy, try again later.  Or just synchronize_sched(). */
+		if (trycount++ < 10)
+			udelay(trycount * num_online_cpus());
+		else {
+			synchronize_sched();
+			return;
+		}
+
+		/* Check to see if someone else did our work for us. */
+		s = atomic_read(&sync_sched_expedited_done);
+		if (UINT_CMP_GE((unsigned)s, (unsigned)firstsnap)) {
+			smp_mb(); /* ensure test happens before caller kfree */
+			return;
+		}
+
+		/*
+		 * Refetching sync_sched_expedited_started allows later
+		 * callers to piggyback on our grace period.  We subtract
+		 * 1 to get the same token that the last incrementer got.
+		 * We retry after they started, so our grace period works
+		 * for them, and they started after our first try, so their
+		 * grace period works for us.
+		 */
+		get_online_cpus();
+		snap = atomic_read(&sync_sched_expedited_started) - 1;
+		smp_mb(); /* ensure read is before try_stop_cpus(). */
+	}
+
+	/*
+	 * Everyone up to our most recent fetch is covered by our grace
+	 * period.  Update the counter, but only if our work is still
+	 * relevant -- which it won't be if someone who started later
+	 * than we did beat us to the punch.
+	 */
+	do {
+		s = atomic_read(&sync_sched_expedited_done);
+		if (UINT_CMP_GE((unsigned)s, (unsigned)snap)) {
+			smp_mb(); /* ensure test happens before caller kfree */
+			break;
+		}
+	} while (atomic_cmpxchg(&sync_sched_expedited_done, s, snap) != s);
+
+	put_online_cpus();
+}
+EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
+
+#endif /* #else #ifndef CONFIG_SMP */
+
 #if !defined(CONFIG_RCU_FAST_NO_HZ)
 
 /*
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index d15430b..c8e9785 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -166,13 +166,13 @@
 
 	gpnum = rsp->gpnum;
 	seq_printf(m, "c=%lu g=%lu s=%d jfq=%ld j=%x "
-		      "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld\n",
+		      "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu\n",
 		   rsp->completed, gpnum, rsp->signaled,
 		   (long)(rsp->jiffies_force_qs - jiffies),
 		   (int)(jiffies & 0xffff),
 		   rsp->n_force_qs, rsp->n_force_qs_ngp,
 		   rsp->n_force_qs - rsp->n_force_qs_ngp,
-		   rsp->n_force_qs_lh, rsp->orphan_qlen);
+		   rsp->n_force_qs_lh);
 	for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) {
 		if (rnp->level != level) {
 			seq_puts(m, "\n");
@@ -300,7 +300,7 @@
 
 static struct dentry *rcudir;
 
-static int __init rcuclassic_trace_init(void)
+static int __init rcutree_trace_init(void)
 {
 	struct dentry *retval;
 
@@ -337,14 +337,14 @@
 	return 1;
 }
 
-static void __exit rcuclassic_trace_cleanup(void)
+static void __exit rcutree_trace_cleanup(void)
 {
 	debugfs_remove_recursive(rcudir);
 }
 
 
-module_init(rcuclassic_trace_init);
-module_exit(rcuclassic_trace_cleanup);
+module_init(rcutree_trace_init);
+module_exit(rcutree_trace_cleanup);
 
 MODULE_AUTHOR("Paul E. McKenney");
 MODULE_DESCRIPTION("Read-Copy Update tracing for hierarchical implementation");
diff --git a/kernel/sched.c b/kernel/sched.c
index 297d1a0..a0eb094 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -75,9 +75,11 @@
 
 #include <asm/tlb.h>
 #include <asm/irq_regs.h>
+#include <asm/mutex.h>
 
 #include "sched_cpupri.h"
 #include "workqueue_sched.h"
+#include "sched_autogroup.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/sched.h>
@@ -253,6 +255,8 @@
 	/* runqueue "owned" by this group on each cpu */
 	struct cfs_rq **cfs_rq;
 	unsigned long shares;
+
+	atomic_t load_weight;
 #endif
 
 #ifdef CONFIG_RT_GROUP_SCHED
@@ -268,25 +272,18 @@
 	struct task_group *parent;
 	struct list_head siblings;
 	struct list_head children;
+
+#ifdef CONFIG_SCHED_AUTOGROUP
+	struct autogroup *autogroup;
+#endif
 };
 
-#define root_task_group init_task_group
-
-/* task_group_lock serializes add/remove of task groups and also changes to
- * a task group's cpu shares.
- */
+/* task_group_lock serializes the addition/removal of task groups */
 static DEFINE_SPINLOCK(task_group_lock);
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 
-#ifdef CONFIG_SMP
-static int root_task_group_empty(void)
-{
-	return list_empty(&root_task_group.children);
-}
-#endif
-
-# define INIT_TASK_GROUP_LOAD	NICE_0_LOAD
+# define ROOT_TASK_GROUP_LOAD	NICE_0_LOAD
 
 /*
  * A weight of 0 or 1 can cause arithmetics problems.
@@ -299,13 +296,13 @@
 #define MIN_SHARES	2
 #define MAX_SHARES	(1UL << 18)
 
-static int init_task_group_load = INIT_TASK_GROUP_LOAD;
+static int root_task_group_load = ROOT_TASK_GROUP_LOAD;
 #endif
 
 /* Default task group.
  *	Every task in system belong to this group at bootup.
  */
-struct task_group init_task_group;
+struct task_group root_task_group;
 
 #endif	/* CONFIG_CGROUP_SCHED */
 
@@ -342,6 +339,7 @@
 	 * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
 	 * list is used during load balance.
 	 */
+	int on_list;
 	struct list_head leaf_cfs_rq_list;
 	struct task_group *tg;	/* group that "owns" this runqueue */
 
@@ -360,14 +358,17 @@
 	unsigned long h_load;
 
 	/*
-	 * this cpu's part of tg->shares
+	 * Maintaining per-cpu shares distribution for group scheduling
+	 *
+	 * load_stamp is the last time we updated the load average
+	 * load_last is the last time we updated the load average and saw load
+	 * load_unacc_exec_time is currently unaccounted execution time
 	 */
-	unsigned long shares;
+	u64 load_avg;
+	u64 load_period;
+	u64 load_stamp, load_last, load_unacc_exec_time;
 
-	/*
-	 * load.weight at the time we set shares
-	 */
-	unsigned long rq_weight;
+	unsigned long load_contribution;
 #endif
 #endif
 };
@@ -605,11 +606,14 @@
  */
 static inline struct task_group *task_group(struct task_struct *p)
 {
+	struct task_group *tg;
 	struct cgroup_subsys_state *css;
 
 	css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
 			lockdep_is_held(&task_rq(p)->lock));
-	return container_of(css, struct task_group, css);
+	tg = container_of(css, struct task_group, css);
+
+	return autogroup_task_group(p, tg);
 }
 
 /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
@@ -737,7 +741,7 @@
 	buf[cnt] = 0;
 	cmp = strstrip(buf);
 
-	if (strncmp(buf, "NO_", 3) == 0) {
+	if (strncmp(cmp, "NO_", 3) == 0) {
 		neg = 1;
 		cmp += 3;
 	}
@@ -793,20 +797,6 @@
 const_debug unsigned int sysctl_sched_nr_migrate = 32;
 
 /*
- * ratelimit for updating the group shares.
- * default: 0.25ms
- */
-unsigned int sysctl_sched_shares_ratelimit = 250000;
-unsigned int normalized_sysctl_sched_shares_ratelimit = 250000;
-
-/*
- * Inject some fuzzyness into changing the per-cpu group shares
- * this avoids remote rq-locks at the expense of fairness.
- * default: 4
- */
-unsigned int sysctl_sched_shares_thresh = 4;
-
-/*
  * period over which we average the RT time consumption, measured
  * in ms.
  *
@@ -1355,6 +1345,12 @@
 	lw->inv_weight = 0;
 }
 
+static inline void update_load_set(struct load_weight *lw, unsigned long w)
+{
+	lw->weight = w;
+	lw->inv_weight = 0;
+}
+
 /*
  * To aid in avoiding the subversion of "niceness" due to uneven distribution
  * of tasks with abnormal "nice" values across CPUs the contribution that
@@ -1543,101 +1539,6 @@
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 
-static __read_mostly unsigned long __percpu *update_shares_data;
-
-static void __set_se_shares(struct sched_entity *se, unsigned long shares);
-
-/*
- * Calculate and set the cpu's group shares.
- */
-static void update_group_shares_cpu(struct task_group *tg, int cpu,
-				    unsigned long sd_shares,
-				    unsigned long sd_rq_weight,
-				    unsigned long *usd_rq_weight)
-{
-	unsigned long shares, rq_weight;
-	int boost = 0;
-
-	rq_weight = usd_rq_weight[cpu];
-	if (!rq_weight) {
-		boost = 1;
-		rq_weight = NICE_0_LOAD;
-	}
-
-	/*
-	 *             \Sum_j shares_j * rq_weight_i
-	 * shares_i =  -----------------------------
-	 *                  \Sum_j rq_weight_j
-	 */
-	shares = (sd_shares * rq_weight) / sd_rq_weight;
-	shares = clamp_t(unsigned long, shares, MIN_SHARES, MAX_SHARES);
-
-	if (abs(shares - tg->se[cpu]->load.weight) >
-			sysctl_sched_shares_thresh) {
-		struct rq *rq = cpu_rq(cpu);
-		unsigned long flags;
-
-		raw_spin_lock_irqsave(&rq->lock, flags);
-		tg->cfs_rq[cpu]->rq_weight = boost ? 0 : rq_weight;
-		tg->cfs_rq[cpu]->shares = boost ? 0 : shares;
-		__set_se_shares(tg->se[cpu], shares);
-		raw_spin_unlock_irqrestore(&rq->lock, flags);
-	}
-}
-
-/*
- * Re-compute the task group their per cpu shares over the given domain.
- * This needs to be done in a bottom-up fashion because the rq weight of a
- * parent group depends on the shares of its child groups.
- */
-static int tg_shares_up(struct task_group *tg, void *data)
-{
-	unsigned long weight, rq_weight = 0, sum_weight = 0, shares = 0;
-	unsigned long *usd_rq_weight;
-	struct sched_domain *sd = data;
-	unsigned long flags;
-	int i;
-
-	if (!tg->se[0])
-		return 0;
-
-	local_irq_save(flags);
-	usd_rq_weight = per_cpu_ptr(update_shares_data, smp_processor_id());
-
-	for_each_cpu(i, sched_domain_span(sd)) {
-		weight = tg->cfs_rq[i]->load.weight;
-		usd_rq_weight[i] = weight;
-
-		rq_weight += weight;
-		/*
-		 * If there are currently no tasks on the cpu pretend there
-		 * is one of average load so that when a new task gets to
-		 * run here it will not get delayed by group starvation.
-		 */
-		if (!weight)
-			weight = NICE_0_LOAD;
-
-		sum_weight += weight;
-		shares += tg->cfs_rq[i]->shares;
-	}
-
-	if (!rq_weight)
-		rq_weight = sum_weight;
-
-	if ((!shares && rq_weight) || shares > tg->shares)
-		shares = tg->shares;
-
-	if (!sd->parent || !(sd->parent->flags & SD_LOAD_BALANCE))
-		shares = tg->shares;
-
-	for_each_cpu(i, sched_domain_span(sd))
-		update_group_shares_cpu(tg, i, shares, rq_weight, usd_rq_weight);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
 /*
  * Compute the cpu's hierarchical load factor for each task group.
  * This needs to be done in a top-down fashion because the load of a child
@@ -1652,7 +1553,7 @@
 		load = cpu_rq(cpu)->load.weight;
 	} else {
 		load = tg->parent->cfs_rq[cpu]->h_load;
-		load *= tg->cfs_rq[cpu]->shares;
+		load *= tg->se[cpu]->load.weight;
 		load /= tg->parent->cfs_rq[cpu]->load.weight + 1;
 	}
 
@@ -1661,34 +1562,11 @@
 	return 0;
 }
 
-static void update_shares(struct sched_domain *sd)
-{
-	s64 elapsed;
-	u64 now;
-
-	if (root_task_group_empty())
-		return;
-
-	now = local_clock();
-	elapsed = now - sd->last_update;
-
-	if (elapsed >= (s64)(u64)sysctl_sched_shares_ratelimit) {
-		sd->last_update = now;
-		walk_tg_tree(tg_nop, tg_shares_up, sd);
-	}
-}
-
 static void update_h_load(long cpu)
 {
 	walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
 }
 
-#else
-
-static inline void update_shares(struct sched_domain *sd)
-{
-}
-
 #endif
 
 #ifdef CONFIG_PREEMPT
@@ -1810,15 +1688,6 @@
 
 #endif
 
-#ifdef CONFIG_FAIR_GROUP_SCHED
-static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares)
-{
-#ifdef CONFIG_SMP
-	cfs_rq->shares = shares;
-#endif
-}
-#endif
-
 static void calc_load_account_idle(struct rq *this_rq);
 static void update_sysctl(void);
 static int get_update_sysctl_factor(void);
@@ -2063,6 +1932,7 @@
 #include "sched_idletask.c"
 #include "sched_fair.c"
 #include "sched_rt.c"
+#include "sched_autogroup.c"
 #include "sched_stoptask.c"
 #ifdef CONFIG_SCHED_DEBUG
 # include "sched_debug.c"
@@ -2255,10 +2125,8 @@
  * The task's runqueue lock must be held.
  * Returns true if you have to wait for migration thread.
  */
-static bool migrate_task(struct task_struct *p, int dest_cpu)
+static bool migrate_task(struct task_struct *p, struct rq *rq)
 {
-	struct rq *rq = task_rq(p);
-
 	/*
 	 * If the task is not on a runqueue (and not running), then
 	 * the next wake-up will properly place the task.
@@ -2438,18 +2306,15 @@
 		return dest_cpu;
 
 	/* No more Mr. Nice Guy. */
-	if (unlikely(dest_cpu >= nr_cpu_ids)) {
-		dest_cpu = cpuset_cpus_allowed_fallback(p);
-		/*
-		 * Don't tell them about moving exiting tasks or
-		 * kernel threads (both mm NULL), since they never
-		 * leave kernel.
-		 */
-		if (p->mm && printk_ratelimit()) {
-			printk(KERN_INFO "process %d (%s) no "
-			       "longer affine to cpu%d\n",
-			       task_pid_nr(p), p->comm, cpu);
-		}
+	dest_cpu = cpuset_cpus_allowed_fallback(p);
+	/*
+	 * Don't tell them about moving exiting tasks or
+	 * kernel threads (both mm NULL), since they never
+	 * leave kernel.
+	 */
+	if (p->mm && printk_ratelimit()) {
+		printk(KERN_INFO "process %d (%s) no longer affine to cpu%d\n",
+				task_pid_nr(p), p->comm, cpu);
 	}
 
 	return dest_cpu;
@@ -2785,7 +2650,9 @@
 	/* Want to start with kernel preemption disabled. */
 	task_thread_info(p)->preempt_count = 1;
 #endif
+#ifdef CONFIG_SMP
 	plist_node_init(&p->pushable_tasks, MAX_PRIO);
+#endif
 
 	put_cpu();
 }
@@ -3549,7 +3416,7 @@
 	 * select_task_rq() can race against ->cpus_allowed
 	 */
 	if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed) &&
-	    likely(cpu_active(dest_cpu)) && migrate_task(p, dest_cpu)) {
+	    likely(cpu_active(dest_cpu)) && migrate_task(p, rq)) {
 		struct migration_arg arg = { p, dest_cpu };
 
 		task_rq_unlock(rq, &flags);
@@ -4214,7 +4081,7 @@
 		if (task_thread_info(rq->curr) != owner || need_resched())
 			return 0;
 
-		cpu_relax();
+		arch_mutex_cpu_relax();
 	}
 
 	return 1;
@@ -4526,7 +4393,7 @@
  * This waits for either a completion of a specific task to be signaled or for a
  * specified timeout to expire. It is interruptible. The timeout is in jiffies.
  */
-unsigned long __sched
+long __sched
 wait_for_completion_interruptible_timeout(struct completion *x,
 					  unsigned long timeout)
 {
@@ -4559,7 +4426,7 @@
  * signaled or for a specified timeout to expire. It can be
  * interrupted by a kill signal. The timeout is in jiffies.
  */
-unsigned long __sched
+long __sched
 wait_for_completion_killable_timeout(struct completion *x,
 				     unsigned long timeout)
 {
@@ -4901,7 +4768,7 @@
 }
 
 static int __sched_setscheduler(struct task_struct *p, int policy,
-				struct sched_param *param, bool user)
+				const struct sched_param *param, bool user)
 {
 	int retval, oldprio, oldpolicy = -1, on_rq, running;
 	unsigned long flags;
@@ -5056,7 +4923,7 @@
  * NOTE that the task may be already dead.
  */
 int sched_setscheduler(struct task_struct *p, int policy,
-		       struct sched_param *param)
+		       const struct sched_param *param)
 {
 	return __sched_setscheduler(p, policy, param, true);
 }
@@ -5074,7 +4941,7 @@
  * but our caller might not have that capability.
  */
 int sched_setscheduler_nocheck(struct task_struct *p, int policy,
-			       struct sched_param *param)
+			       const struct sched_param *param)
 {
 	return __sched_setscheduler(p, policy, param, false);
 }
@@ -5590,7 +5457,7 @@
 	unsigned state;
 
 	state = p->state ? __ffs(p->state) + 1 : 0;
-	printk(KERN_INFO "%-13.13s %c", p->comm,
+	printk(KERN_INFO "%-15.15s %c", p->comm,
 		state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?');
 #if BITS_PER_LONG == 32
 	if (state == TASK_RUNNING)
@@ -5754,7 +5621,6 @@
 	SET_SYSCTL(sched_min_granularity);
 	SET_SYSCTL(sched_latency);
 	SET_SYSCTL(sched_wakeup_granularity);
-	SET_SYSCTL(sched_shares_ratelimit);
 #undef SET_SYSCTL
 }
 
@@ -5830,7 +5696,7 @@
 		goto out;
 
 	dest_cpu = cpumask_any_and(cpu_active_mask, new_mask);
-	if (migrate_task(p, dest_cpu)) {
+	if (migrate_task(p, rq)) {
 		struct migration_arg arg = { p, dest_cpu };
 		/* Need help from migration thread: drop lock and wait. */
 		task_rq_unlock(rq, &flags);
@@ -5912,96 +5778,6 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/*
- * Figure out where task on dead CPU should go, use force if necessary.
- */
-void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
-{
-	struct rq *rq = cpu_rq(dead_cpu);
-	int needs_cpu, uninitialized_var(dest_cpu);
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	raw_spin_lock(&rq->lock);
-	needs_cpu = (task_cpu(p) == dead_cpu) && (p->state != TASK_WAKING);
-	if (needs_cpu)
-		dest_cpu = select_fallback_rq(dead_cpu, p);
-	raw_spin_unlock(&rq->lock);
-	/*
-	 * It can only fail if we race with set_cpus_allowed(),
-	 * in the racer should migrate the task anyway.
-	 */
-	if (needs_cpu)
-		__migrate_task(p, dead_cpu, dest_cpu);
-	local_irq_restore(flags);
-}
-
-/*
- * While a dead CPU has no uninterruptible tasks queued at this point,
- * it might still have a nonzero ->nr_uninterruptible counter, because
- * for performance reasons the counter is not stricly tracking tasks to
- * their home CPUs. So we just add the counter to another CPU's counter,
- * to keep the global sum constant after CPU-down:
- */
-static void migrate_nr_uninterruptible(struct rq *rq_src)
-{
-	struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask));
-	unsigned long flags;
-
-	local_irq_save(flags);
-	double_rq_lock(rq_src, rq_dest);
-	rq_dest->nr_uninterruptible += rq_src->nr_uninterruptible;
-	rq_src->nr_uninterruptible = 0;
-	double_rq_unlock(rq_src, rq_dest);
-	local_irq_restore(flags);
-}
-
-/* Run through task list and migrate tasks from the dead cpu. */
-static void migrate_live_tasks(int src_cpu)
-{
-	struct task_struct *p, *t;
-
-	read_lock(&tasklist_lock);
-
-	do_each_thread(t, p) {
-		if (p == current)
-			continue;
-
-		if (task_cpu(p) == src_cpu)
-			move_task_off_dead_cpu(src_cpu, p);
-	} while_each_thread(t, p);
-
-	read_unlock(&tasklist_lock);
-}
-
-/*
- * Schedules idle task to be the next runnable task on current CPU.
- * It does so by boosting its priority to highest possible.
- * Used by CPU offline code.
- */
-void sched_idle_next(void)
-{
-	int this_cpu = smp_processor_id();
-	struct rq *rq = cpu_rq(this_cpu);
-	struct task_struct *p = rq->idle;
-	unsigned long flags;
-
-	/* cpu has to be offline */
-	BUG_ON(cpu_online(this_cpu));
-
-	/*
-	 * Strictly not necessary since rest of the CPUs are stopped by now
-	 * and interrupts disabled on the current cpu.
-	 */
-	raw_spin_lock_irqsave(&rq->lock, flags);
-
-	__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
-
-	activate_task(rq, p, 0);
-
-	raw_spin_unlock_irqrestore(&rq->lock, flags);
-}
 
 /*
  * Ensures that the idle task is using init_mm right before its cpu goes
@@ -6018,47 +5794,19 @@
 	mmdrop(mm);
 }
 
-/* called under rq->lock with disabled interrupts */
-static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
+/*
+ * While a dead CPU has no uninterruptible tasks queued at this point,
+ * it might still have a nonzero ->nr_uninterruptible counter, because
+ * for performance reasons the counter is not stricly tracking tasks to
+ * their home CPUs. So we just add the counter to another CPU's counter,
+ * to keep the global sum constant after CPU-down:
+ */
+static void migrate_nr_uninterruptible(struct rq *rq_src)
 {
-	struct rq *rq = cpu_rq(dead_cpu);
+	struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask));
 
-	/* Must be exiting, otherwise would be on tasklist. */
-	BUG_ON(!p->exit_state);
-
-	/* Cannot have done final schedule yet: would have vanished. */
-	BUG_ON(p->state == TASK_DEAD);
-
-	get_task_struct(p);
-
-	/*
-	 * Drop lock around migration; if someone else moves it,
-	 * that's OK. No task can be added to this CPU, so iteration is
-	 * fine.
-	 */
-	raw_spin_unlock_irq(&rq->lock);
-	move_task_off_dead_cpu(dead_cpu, p);
-	raw_spin_lock_irq(&rq->lock);
-
-	put_task_struct(p);
-}
-
-/* release_task() removes task from tasklist, so we won't find dead tasks. */
-static void migrate_dead_tasks(unsigned int dead_cpu)
-{
-	struct rq *rq = cpu_rq(dead_cpu);
-	struct task_struct *next;
-
-	for ( ; ; ) {
-		if (!rq->nr_running)
-			break;
-		next = pick_next_task(rq);
-		if (!next)
-			break;
-		next->sched_class->put_prev_task(rq, next);
-		migrate_dead(dead_cpu, next);
-
-	}
+	rq_dest->nr_uninterruptible += rq_src->nr_uninterruptible;
+	rq_src->nr_uninterruptible = 0;
 }
 
 /*
@@ -6069,6 +5817,56 @@
 	atomic_long_sub(rq->calc_load_active, &calc_load_tasks);
 	rq->calc_load_active = 0;
 }
+
+/*
+ * Migrate all tasks from the rq, sleeping tasks will be migrated by
+ * try_to_wake_up()->select_task_rq().
+ *
+ * Called with rq->lock held even though we'er in stop_machine() and
+ * there's no concurrency possible, we hold the required locks anyway
+ * because of lock validation efforts.
+ */
+static void migrate_tasks(unsigned int dead_cpu)
+{
+	struct rq *rq = cpu_rq(dead_cpu);
+	struct task_struct *next, *stop = rq->stop;
+	int dest_cpu;
+
+	/*
+	 * Fudge the rq selection such that the below task selection loop
+	 * doesn't get stuck on the currently eligible stop task.
+	 *
+	 * We're currently inside stop_machine() and the rq is either stuck
+	 * in the stop_machine_cpu_stop() loop, or we're executing this code,
+	 * either way we should never end up calling schedule() until we're
+	 * done here.
+	 */
+	rq->stop = NULL;
+
+	for ( ; ; ) {
+		/*
+		 * There's this thread running, bail when that's the only
+		 * remaining thread.
+		 */
+		if (rq->nr_running == 1)
+			break;
+
+		next = pick_next_task(rq);
+		BUG_ON(!next);
+		next->sched_class->put_prev_task(rq, next);
+
+		/* Find suitable destination for @next, with force if needed. */
+		dest_cpu = select_fallback_rq(dead_cpu, next);
+		raw_spin_unlock(&rq->lock);
+
+		__migrate_task(next, dead_cpu, dest_cpu);
+
+		raw_spin_lock(&rq->lock);
+	}
+
+	rq->stop = stop;
+}
+
 #endif /* CONFIG_HOTPLUG_CPU */
 
 #if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL)
@@ -6278,15 +6076,13 @@
 	unsigned long flags;
 	struct rq *rq = cpu_rq(cpu);
 
-	switch (action) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 
 	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
 		rq->calc_load_update = calc_load_update;
 		break;
 
 	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
 		/* Update our root-domain */
 		raw_spin_lock_irqsave(&rq->lock, flags);
 		if (rq->rd) {
@@ -6298,30 +6094,19 @@
 		break;
 
 #ifdef CONFIG_HOTPLUG_CPU
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		migrate_live_tasks(cpu);
-		/* Idle task back to normal (off runqueue, low prio) */
-		raw_spin_lock_irq(&rq->lock);
-		deactivate_task(rq, rq->idle, 0);
-		__setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
-		rq->idle->sched_class = &idle_sched_class;
-		migrate_dead_tasks(cpu);
-		raw_spin_unlock_irq(&rq->lock);
-		migrate_nr_uninterruptible(rq);
-		BUG_ON(rq->nr_running != 0);
-		calc_global_load_remove(rq);
-		break;
-
 	case CPU_DYING:
-	case CPU_DYING_FROZEN:
 		/* Update our root-domain */
 		raw_spin_lock_irqsave(&rq->lock, flags);
 		if (rq->rd) {
 			BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
 			set_rq_offline(rq);
 		}
+		migrate_tasks(cpu);
+		BUG_ON(rq->nr_running != 1); /* the migration thread */
 		raw_spin_unlock_irqrestore(&rq->lock, flags);
+
+		migrate_nr_uninterruptible(rq);
+		calc_global_load_remove(rq);
 		break;
 #endif
 	}
@@ -8052,18 +7837,16 @@
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
-				struct sched_entity *se, int cpu, int add,
+				struct sched_entity *se, int cpu,
 				struct sched_entity *parent)
 {
 	struct rq *rq = cpu_rq(cpu);
 	tg->cfs_rq[cpu] = cfs_rq;
 	init_cfs_rq(cfs_rq, rq);
 	cfs_rq->tg = tg;
-	if (add)
-		list_add(&cfs_rq->leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
 
 	tg->se[cpu] = se;
-	/* se could be NULL for init_task_group */
+	/* se could be NULL for root_task_group */
 	if (!se)
 		return;
 
@@ -8073,15 +7856,14 @@
 		se->cfs_rq = parent->my_q;
 
 	se->my_q = cfs_rq;
-	se->load.weight = tg->shares;
-	se->load.inv_weight = 0;
+	update_load_set(&se->load, 0);
 	se->parent = parent;
 }
 #endif
 
 #ifdef CONFIG_RT_GROUP_SCHED
 static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
-		struct sched_rt_entity *rt_se, int cpu, int add,
+		struct sched_rt_entity *rt_se, int cpu,
 		struct sched_rt_entity *parent)
 {
 	struct rq *rq = cpu_rq(cpu);
@@ -8090,8 +7872,6 @@
 	init_rt_rq(rt_rq, rq);
 	rt_rq->tg = tg;
 	rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime;
-	if (add)
-		list_add(&rt_rq->leaf_rt_rq_list, &rq->leaf_rt_rq_list);
 
 	tg->rt_se[cpu] = rt_se;
 	if (!rt_se)
@@ -8126,18 +7906,18 @@
 		ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT);
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-		init_task_group.se = (struct sched_entity **)ptr;
+		root_task_group.se = (struct sched_entity **)ptr;
 		ptr += nr_cpu_ids * sizeof(void **);
 
-		init_task_group.cfs_rq = (struct cfs_rq **)ptr;
+		root_task_group.cfs_rq = (struct cfs_rq **)ptr;
 		ptr += nr_cpu_ids * sizeof(void **);
 
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 #ifdef CONFIG_RT_GROUP_SCHED
-		init_task_group.rt_se = (struct sched_rt_entity **)ptr;
+		root_task_group.rt_se = (struct sched_rt_entity **)ptr;
 		ptr += nr_cpu_ids * sizeof(void **);
 
-		init_task_group.rt_rq = (struct rt_rq **)ptr;
+		root_task_group.rt_rq = (struct rt_rq **)ptr;
 		ptr += nr_cpu_ids * sizeof(void **);
 
 #endif /* CONFIG_RT_GROUP_SCHED */
@@ -8157,20 +7937,16 @@
 			global_rt_period(), global_rt_runtime());
 
 #ifdef CONFIG_RT_GROUP_SCHED
-	init_rt_bandwidth(&init_task_group.rt_bandwidth,
+	init_rt_bandwidth(&root_task_group.rt_bandwidth,
 			global_rt_period(), global_rt_runtime());
 #endif /* CONFIG_RT_GROUP_SCHED */
 
 #ifdef CONFIG_CGROUP_SCHED
-	list_add(&init_task_group.list, &task_groups);
-	INIT_LIST_HEAD(&init_task_group.children);
-
+	list_add(&root_task_group.list, &task_groups);
+	INIT_LIST_HEAD(&root_task_group.children);
+	autogroup_init(&init_task);
 #endif /* CONFIG_CGROUP_SCHED */
 
-#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
-	update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),
-					    __alignof__(unsigned long));
-#endif
 	for_each_possible_cpu(i) {
 		struct rq *rq;
 
@@ -8182,38 +7958,34 @@
 		init_cfs_rq(&rq->cfs, rq);
 		init_rt_rq(&rq->rt, rq);
 #ifdef CONFIG_FAIR_GROUP_SCHED
-		init_task_group.shares = init_task_group_load;
+		root_task_group.shares = root_task_group_load;
 		INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
-#ifdef CONFIG_CGROUP_SCHED
 		/*
-		 * How much cpu bandwidth does init_task_group get?
+		 * How much cpu bandwidth does root_task_group get?
 		 *
 		 * In case of task-groups formed thr' the cgroup filesystem, it
 		 * gets 100% of the cpu resources in the system. This overall
 		 * system cpu resource is divided among the tasks of
-		 * init_task_group and its child task-groups in a fair manner,
+		 * root_task_group and its child task-groups in a fair manner,
 		 * based on each entity's (task or task-group's) weight
 		 * (se->load.weight).
 		 *
-		 * In other words, if init_task_group has 10 tasks of weight
+		 * In other words, if root_task_group has 10 tasks of weight
 		 * 1024) and two child groups A0 and A1 (of weight 1024 each),
 		 * then A0's share of the cpu resource is:
 		 *
 		 *	A0's bandwidth = 1024 / (10*1024 + 1024 + 1024) = 8.33%
 		 *
-		 * We achieve this by letting init_task_group's tasks sit
-		 * directly in rq->cfs (i.e init_task_group->se[] = NULL).
+		 * We achieve this by letting root_task_group's tasks sit
+		 * directly in rq->cfs (i.e root_task_group->se[] = NULL).
 		 */
-		init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, 1, NULL);
-#endif
+		init_tg_cfs_entry(&root_task_group, &rq->cfs, NULL, i, NULL);
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
 		rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime;
 #ifdef CONFIG_RT_GROUP_SCHED
 		INIT_LIST_HEAD(&rq->leaf_rt_rq_list);
-#ifdef CONFIG_CGROUP_SCHED
-		init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, 1, NULL);
-#endif
+		init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, NULL);
 #endif
 
 		for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
@@ -8293,8 +8065,6 @@
 		zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
 #endif /* SMP */
 
-	perf_event_init();
-
 	scheduler_running = 1;
 }
 
@@ -8488,7 +8258,7 @@
 		if (!se)
 			goto err_free_rq;
 
-		init_tg_cfs_entry(tg, cfs_rq, se, i, 0, parent->se[i]);
+		init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]);
 	}
 
 	return 1;
@@ -8499,15 +8269,21 @@
 	return 0;
 }
 
-static inline void register_fair_sched_group(struct task_group *tg, int cpu)
-{
-	list_add_rcu(&tg->cfs_rq[cpu]->leaf_cfs_rq_list,
-			&cpu_rq(cpu)->leaf_cfs_rq_list);
-}
-
 static inline void unregister_fair_sched_group(struct task_group *tg, int cpu)
 {
-	list_del_rcu(&tg->cfs_rq[cpu]->leaf_cfs_rq_list);
+	struct rq *rq = cpu_rq(cpu);
+	unsigned long flags;
+
+	/*
+	* Only empty task groups can be destroyed; so we can speculatively
+	* check on_list without danger of it being re-added.
+	*/
+	if (!tg->cfs_rq[cpu]->on_list)
+		return;
+
+	raw_spin_lock_irqsave(&rq->lock, flags);
+	list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
+	raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
 #else /* !CONFG_FAIR_GROUP_SCHED */
 static inline void free_fair_sched_group(struct task_group *tg)
@@ -8520,10 +8296,6 @@
 	return 1;
 }
 
-static inline void register_fair_sched_group(struct task_group *tg, int cpu)
-{
-}
-
 static inline void unregister_fair_sched_group(struct task_group *tg, int cpu)
 {
 }
@@ -8578,7 +8350,7 @@
 		if (!rt_se)
 			goto err_free_rq;
 
-		init_tg_rt_entry(tg, rt_rq, rt_se, i, 0, parent->rt_se[i]);
+		init_tg_rt_entry(tg, rt_rq, rt_se, i, parent->rt_se[i]);
 	}
 
 	return 1;
@@ -8588,17 +8360,6 @@
 err:
 	return 0;
 }
-
-static inline void register_rt_sched_group(struct task_group *tg, int cpu)
-{
-	list_add_rcu(&tg->rt_rq[cpu]->leaf_rt_rq_list,
-			&cpu_rq(cpu)->leaf_rt_rq_list);
-}
-
-static inline void unregister_rt_sched_group(struct task_group *tg, int cpu)
-{
-	list_del_rcu(&tg->rt_rq[cpu]->leaf_rt_rq_list);
-}
 #else /* !CONFIG_RT_GROUP_SCHED */
 static inline void free_rt_sched_group(struct task_group *tg)
 {
@@ -8609,14 +8370,6 @@
 {
 	return 1;
 }
-
-static inline void register_rt_sched_group(struct task_group *tg, int cpu)
-{
-}
-
-static inline void unregister_rt_sched_group(struct task_group *tg, int cpu)
-{
-}
 #endif /* CONFIG_RT_GROUP_SCHED */
 
 #ifdef CONFIG_CGROUP_SCHED
@@ -8624,6 +8377,7 @@
 {
 	free_fair_sched_group(tg);
 	free_rt_sched_group(tg);
+	autogroup_free(tg);
 	kfree(tg);
 }
 
@@ -8632,7 +8386,6 @@
 {
 	struct task_group *tg;
 	unsigned long flags;
-	int i;
 
 	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
 	if (!tg)
@@ -8645,10 +8398,6 @@
 		goto err;
 
 	spin_lock_irqsave(&task_group_lock, flags);
-	for_each_possible_cpu(i) {
-		register_fair_sched_group(tg, i);
-		register_rt_sched_group(tg, i);
-	}
 	list_add_rcu(&tg->list, &task_groups);
 
 	WARN_ON(!parent); /* root should already exist */
@@ -8678,11 +8427,11 @@
 	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(&task_group_lock, flags);
-	for_each_possible_cpu(i) {
+	/* end participation in shares distribution */
+	for_each_possible_cpu(i)
 		unregister_fair_sched_group(tg, i);
-		unregister_rt_sched_group(tg, i);
-	}
+
+	spin_lock_irqsave(&task_group_lock, flags);
 	list_del_rcu(&tg->list);
 	list_del_rcu(&tg->siblings);
 	spin_unlock_irqrestore(&task_group_lock, flags);
@@ -8729,33 +8478,6 @@
 #endif /* CONFIG_CGROUP_SCHED */
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-static void __set_se_shares(struct sched_entity *se, unsigned long shares)
-{
-	struct cfs_rq *cfs_rq = se->cfs_rq;
-	int on_rq;
-
-	on_rq = se->on_rq;
-	if (on_rq)
-		dequeue_entity(cfs_rq, se, 0);
-
-	se->load.weight = shares;
-	se->load.inv_weight = 0;
-
-	if (on_rq)
-		enqueue_entity(cfs_rq, se, 0);
-}
-
-static void set_se_shares(struct sched_entity *se, unsigned long shares)
-{
-	struct cfs_rq *cfs_rq = se->cfs_rq;
-	struct rq *rq = cfs_rq->rq;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&rq->lock, flags);
-	__set_se_shares(se, shares);
-	raw_spin_unlock_irqrestore(&rq->lock, flags);
-}
-
 static DEFINE_MUTEX(shares_mutex);
 
 int sched_group_set_shares(struct task_group *tg, unsigned long shares)
@@ -8778,37 +8500,19 @@
 	if (tg->shares == shares)
 		goto done;
 
-	spin_lock_irqsave(&task_group_lock, flags);
-	for_each_possible_cpu(i)
-		unregister_fair_sched_group(tg, i);
-	list_del_rcu(&tg->siblings);
-	spin_unlock_irqrestore(&task_group_lock, flags);
-
-	/* wait for any ongoing reference to this group to finish */
-	synchronize_sched();
-
-	/*
-	 * Now we are free to modify the group's share on each cpu
-	 * w/o tripping rebalance_share or load_balance_fair.
-	 */
 	tg->shares = shares;
 	for_each_possible_cpu(i) {
-		/*
-		 * force a rebalance
-		 */
-		cfs_rq_set_shares(tg->cfs_rq[i], 0);
-		set_se_shares(tg->se[i], shares);
+		struct rq *rq = cpu_rq(i);
+		struct sched_entity *se;
+
+		se = tg->se[i];
+		/* Propagate contribution to hierarchy */
+		raw_spin_lock_irqsave(&rq->lock, flags);
+		for_each_sched_entity(se)
+			update_cfs_shares(group_cfs_rq(se), 0);
+		raw_spin_unlock_irqrestore(&rq->lock, flags);
 	}
 
-	/*
-	 * Enable load balance activity on this group, by inserting it back on
-	 * each cpu's rq->leaf_cfs_rq_list.
-	 */
-	spin_lock_irqsave(&task_group_lock, flags);
-	for_each_possible_cpu(i)
-		register_fair_sched_group(tg, i);
-	list_add_rcu(&tg->siblings, &tg->parent->children);
-	spin_unlock_irqrestore(&task_group_lock, flags);
 done:
 	mutex_unlock(&shares_mutex);
 	return 0;
@@ -9107,7 +8811,7 @@
 
 	if (!cgrp->parent) {
 		/* This is early initialization for the top cgroup */
-		return &init_task_group.css;
+		return &root_task_group.css;
 	}
 
 	parent = cgroup_tg(cgrp->parent);
@@ -9534,72 +9238,3 @@
 };
 #endif	/* CONFIG_CGROUP_CPUACCT */
 
-#ifndef CONFIG_SMP
-
-void synchronize_sched_expedited(void)
-{
-	barrier();
-}
-EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
-
-#else /* #ifndef CONFIG_SMP */
-
-static atomic_t synchronize_sched_expedited_count = ATOMIC_INIT(0);
-
-static int synchronize_sched_expedited_cpu_stop(void *data)
-{
-	/*
-	 * There must be a full memory barrier on each affected CPU
-	 * between the time that try_stop_cpus() is called and the
-	 * time that it returns.
-	 *
-	 * In the current initial implementation of cpu_stop, the
-	 * above condition is already met when the control reaches
-	 * this point and the following smp_mb() is not strictly
-	 * necessary.  Do smp_mb() anyway for documentation and
-	 * robustness against future implementation changes.
-	 */
-	smp_mb(); /* See above comment block. */
-	return 0;
-}
-
-/*
- * Wait for an rcu-sched grace period to elapse, but use "big hammer"
- * approach to force grace period to end quickly.  This consumes
- * significant time on all CPUs, and is thus not recommended for
- * any sort of common-case code.
- *
- * Note that it is illegal to call this function while holding any
- * lock that is acquired by a CPU-hotplug notifier.  Failing to
- * observe this restriction will result in deadlock.
- */
-void synchronize_sched_expedited(void)
-{
-	int snap, trycount = 0;
-
-	smp_mb();  /* ensure prior mod happens before capturing snap. */
-	snap = atomic_read(&synchronize_sched_expedited_count) + 1;
-	get_online_cpus();
-	while (try_stop_cpus(cpu_online_mask,
-			     synchronize_sched_expedited_cpu_stop,
-			     NULL) == -EAGAIN) {
-		put_online_cpus();
-		if (trycount++ < 10)
-			udelay(trycount * num_online_cpus());
-		else {
-			synchronize_sched();
-			return;
-		}
-		if (atomic_read(&synchronize_sched_expedited_count) - snap > 0) {
-			smp_mb(); /* ensure test happens before caller kfree */
-			return;
-		}
-		get_online_cpus();
-	}
-	atomic_inc(&synchronize_sched_expedited_count);
-	smp_mb__after_atomic_inc(); /* ensure post-GP actions seen after GP. */
-	put_online_cpus();
-}
-EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
-
-#endif /* #else #ifndef CONFIG_SMP */
diff --git a/kernel/sched_autogroup.c b/kernel/sched_autogroup.c
new file mode 100644
index 0000000..32a723b
--- /dev/null
+++ b/kernel/sched_autogroup.c
@@ -0,0 +1,238 @@
+#ifdef CONFIG_SCHED_AUTOGROUP
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/utsname.h>
+
+unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
+static struct autogroup autogroup_default;
+static atomic_t autogroup_seq_nr;
+
+static void __init autogroup_init(struct task_struct *init_task)
+{
+	autogroup_default.tg = &root_task_group;
+	root_task_group.autogroup = &autogroup_default;
+	kref_init(&autogroup_default.kref);
+	init_rwsem(&autogroup_default.lock);
+	init_task->signal->autogroup = &autogroup_default;
+}
+
+static inline void autogroup_free(struct task_group *tg)
+{
+	kfree(tg->autogroup);
+}
+
+static inline void autogroup_destroy(struct kref *kref)
+{
+	struct autogroup *ag = container_of(kref, struct autogroup, kref);
+
+	sched_destroy_group(ag->tg);
+}
+
+static inline void autogroup_kref_put(struct autogroup *ag)
+{
+	kref_put(&ag->kref, autogroup_destroy);
+}
+
+static inline struct autogroup *autogroup_kref_get(struct autogroup *ag)
+{
+	kref_get(&ag->kref);
+	return ag;
+}
+
+static inline struct autogroup *autogroup_task_get(struct task_struct *p)
+{
+	struct autogroup *ag;
+	unsigned long flags;
+
+	if (!lock_task_sighand(p, &flags))
+		return autogroup_kref_get(&autogroup_default);
+
+	ag = autogroup_kref_get(p->signal->autogroup);
+	unlock_task_sighand(p, &flags);
+
+	return ag;
+}
+
+static inline struct autogroup *autogroup_create(void)
+{
+	struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL);
+	struct task_group *tg;
+
+	if (!ag)
+		goto out_fail;
+
+	tg = sched_create_group(&root_task_group);
+
+	if (IS_ERR(tg))
+		goto out_free;
+
+	kref_init(&ag->kref);
+	init_rwsem(&ag->lock);
+	ag->id = atomic_inc_return(&autogroup_seq_nr);
+	ag->tg = tg;
+	tg->autogroup = ag;
+
+	return ag;
+
+out_free:
+	kfree(ag);
+out_fail:
+	if (printk_ratelimit()) {
+		printk(KERN_WARNING "autogroup_create: %s failure.\n",
+			ag ? "sched_create_group()" : "kmalloc()");
+	}
+
+	return autogroup_kref_get(&autogroup_default);
+}
+
+static inline bool
+task_wants_autogroup(struct task_struct *p, struct task_group *tg)
+{
+	if (tg != &root_task_group)
+		return false;
+
+	if (p->sched_class != &fair_sched_class)
+		return false;
+
+	/*
+	 * We can only assume the task group can't go away on us if
+	 * autogroup_move_group() can see us on ->thread_group list.
+	 */
+	if (p->flags & PF_EXITING)
+		return false;
+
+	return true;
+}
+
+static inline struct task_group *
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
+{
+	int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
+
+	if (enabled && task_wants_autogroup(p, tg))
+		return p->signal->autogroup->tg;
+
+	return tg;
+}
+
+static void
+autogroup_move_group(struct task_struct *p, struct autogroup *ag)
+{
+	struct autogroup *prev;
+	struct task_struct *t;
+	unsigned long flags;
+
+	BUG_ON(!lock_task_sighand(p, &flags));
+
+	prev = p->signal->autogroup;
+	if (prev == ag) {
+		unlock_task_sighand(p, &flags);
+		return;
+	}
+
+	p->signal->autogroup = autogroup_kref_get(ag);
+
+	t = p;
+	do {
+		sched_move_task(t);
+	} while_each_thread(p, t);
+
+	unlock_task_sighand(p, &flags);
+	autogroup_kref_put(prev);
+}
+
+/* Allocates GFP_KERNEL, cannot be called under any spinlock */
+void sched_autogroup_create_attach(struct task_struct *p)
+{
+	struct autogroup *ag = autogroup_create();
+
+	autogroup_move_group(p, ag);
+	/* drop extra refrence added by autogroup_create() */
+	autogroup_kref_put(ag);
+}
+EXPORT_SYMBOL(sched_autogroup_create_attach);
+
+/* Cannot be called under siglock.  Currently has no users */
+void sched_autogroup_detach(struct task_struct *p)
+{
+	autogroup_move_group(p, &autogroup_default);
+}
+EXPORT_SYMBOL(sched_autogroup_detach);
+
+void sched_autogroup_fork(struct signal_struct *sig)
+{
+	sig->autogroup = autogroup_task_get(current);
+}
+
+void sched_autogroup_exit(struct signal_struct *sig)
+{
+	autogroup_kref_put(sig->autogroup);
+}
+
+static int __init setup_autogroup(char *str)
+{
+	sysctl_sched_autogroup_enabled = 0;
+
+	return 1;
+}
+
+__setup("noautogroup", setup_autogroup);
+
+#ifdef CONFIG_PROC_FS
+
+int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice)
+{
+	static unsigned long next = INITIAL_JIFFIES;
+	struct autogroup *ag;
+	int err;
+
+	if (*nice < -20 || *nice > 19)
+		return -EINVAL;
+
+	err = security_task_setnice(current, *nice);
+	if (err)
+		return err;
+
+	if (*nice < 0 && !can_nice(current, *nice))
+		return -EPERM;
+
+	/* this is a heavy operation taking global locks.. */
+	if (!capable(CAP_SYS_ADMIN) && time_before(jiffies, next))
+		return -EAGAIN;
+
+	next = HZ / 10 + jiffies;
+	ag = autogroup_task_get(p);
+
+	down_write(&ag->lock);
+	err = sched_group_set_shares(ag->tg, prio_to_weight[*nice + 20]);
+	if (!err)
+		ag->nice = *nice;
+	up_write(&ag->lock);
+
+	autogroup_kref_put(ag);
+
+	return err;
+}
+
+void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)
+{
+	struct autogroup *ag = autogroup_task_get(p);
+
+	down_read(&ag->lock);
+	seq_printf(m, "/autogroup-%ld nice %d\n", ag->id, ag->nice);
+	up_read(&ag->lock);
+
+	autogroup_kref_put(ag);
+}
+#endif /* CONFIG_PROC_FS */
+
+#ifdef CONFIG_SCHED_DEBUG
+static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
+{
+	return snprintf(buf, buflen, "%s-%ld", "/autogroup", tg->autogroup->id);
+}
+#endif /* CONFIG_SCHED_DEBUG */
+
+#endif /* CONFIG_SCHED_AUTOGROUP */
diff --git a/kernel/sched_autogroup.h b/kernel/sched_autogroup.h
new file mode 100644
index 0000000..5358e24
--- /dev/null
+++ b/kernel/sched_autogroup.h
@@ -0,0 +1,32 @@
+#ifdef CONFIG_SCHED_AUTOGROUP
+
+struct autogroup {
+	struct kref		kref;
+	struct task_group	*tg;
+	struct rw_semaphore	lock;
+	unsigned long		id;
+	int			nice;
+};
+
+static inline struct task_group *
+autogroup_task_group(struct task_struct *p, struct task_group *tg);
+
+#else /* !CONFIG_SCHED_AUTOGROUP */
+
+static inline void autogroup_init(struct task_struct *init_task) {  }
+static inline void autogroup_free(struct task_group *tg) { }
+
+static inline struct task_group *
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
+{
+	return tg;
+}
+
+#ifdef CONFIG_SCHED_DEBUG
+static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
+{
+	return 0;
+}
+#endif
+
+#endif /* CONFIG_SCHED_AUTOGROUP */
diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c
index 52f1a14..9d8af0b 100644
--- a/kernel/sched_clock.c
+++ b/kernel/sched_clock.c
@@ -79,7 +79,7 @@
 }
 EXPORT_SYMBOL_GPL(sched_clock);
 
-static __read_mostly int sched_clock_running;
+__read_mostly int sched_clock_running;
 
 #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
 __read_mostly int sched_clock_stable;
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
index 2e1b0d1..1dfae3d 100644
--- a/kernel/sched_debug.c
+++ b/kernel/sched_debug.c
@@ -54,8 +54,7 @@
 #define SPLIT_NS(x) nsec_high(x), nsec_low(x)
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-static void print_cfs_group_stats(struct seq_file *m, int cpu,
-		struct task_group *tg)
+static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group *tg)
 {
 	struct sched_entity *se = tg->se[cpu];
 	if (!se)
@@ -110,16 +109,6 @@
 		0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L);
 #endif
 
-#ifdef CONFIG_CGROUP_SCHED
-	{
-		char path[64];
-
-		rcu_read_lock();
-		cgroup_path(task_group(p)->css.cgroup, path, sizeof(path));
-		rcu_read_unlock();
-		SEQ_printf(m, " %s", path);
-	}
-#endif
 	SEQ_printf(m, "\n");
 }
 
@@ -147,19 +136,6 @@
 	read_unlock_irqrestore(&tasklist_lock, flags);
 }
 
-#if defined(CONFIG_CGROUP_SCHED) && \
-	(defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED))
-static void task_group_path(struct task_group *tg, char *buf, int buflen)
-{
-	/* may be NULL if the underlying cgroup isn't fully-created yet */
-	if (!tg->css.cgroup) {
-		buf[0] = '\0';
-		return;
-	}
-	cgroup_path(tg->css.cgroup, buf, buflen);
-}
-#endif
-
 void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
 {
 	s64 MIN_vruntime = -1, min_vruntime, max_vruntime = -1,
@@ -168,16 +144,7 @@
 	struct sched_entity *last;
 	unsigned long flags;
 
-#if defined(CONFIG_CGROUP_SCHED) && defined(CONFIG_FAIR_GROUP_SCHED)
-	char path[128];
-	struct task_group *tg = cfs_rq->tg;
-
-	task_group_path(tg, path, sizeof(path));
-
-	SEQ_printf(m, "\ncfs_rq[%d]:%s\n", cpu, path);
-#else
 	SEQ_printf(m, "\ncfs_rq[%d]:\n", cpu);
-#endif
 	SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "exec_clock",
 			SPLIT_NS(cfs_rq->exec_clock));
 
@@ -202,32 +169,29 @@
 	spread0 = min_vruntime - rq0_min_vruntime;
 	SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "spread0",
 			SPLIT_NS(spread0));
-	SEQ_printf(m, "  .%-30s: %ld\n", "nr_running", cfs_rq->nr_running);
-	SEQ_printf(m, "  .%-30s: %ld\n", "load", cfs_rq->load.weight);
-
 	SEQ_printf(m, "  .%-30s: %d\n", "nr_spread_over",
 			cfs_rq->nr_spread_over);
+	SEQ_printf(m, "  .%-30s: %ld\n", "nr_running", cfs_rq->nr_running);
+	SEQ_printf(m, "  .%-30s: %ld\n", "load", cfs_rq->load.weight);
 #ifdef CONFIG_FAIR_GROUP_SCHED
 #ifdef CONFIG_SMP
-	SEQ_printf(m, "  .%-30s: %lu\n", "shares", cfs_rq->shares);
+	SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "load_avg",
+			SPLIT_NS(cfs_rq->load_avg));
+	SEQ_printf(m, "  .%-30s: %Ld.%06ld\n", "load_period",
+			SPLIT_NS(cfs_rq->load_period));
+	SEQ_printf(m, "  .%-30s: %ld\n", "load_contrib",
+			cfs_rq->load_contribution);
+	SEQ_printf(m, "  .%-30s: %d\n", "load_tg",
+			atomic_read(&cfs_rq->tg->load_weight));
 #endif
+
 	print_cfs_group_stats(m, cpu, cfs_rq->tg);
 #endif
 }
 
 void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq)
 {
-#if defined(CONFIG_CGROUP_SCHED) && defined(CONFIG_RT_GROUP_SCHED)
-	char path[128];
-	struct task_group *tg = rt_rq->tg;
-
-	task_group_path(tg, path, sizeof(path));
-
-	SEQ_printf(m, "\nrt_rq[%d]:%s\n", cpu, path);
-#else
 	SEQ_printf(m, "\nrt_rq[%d]:\n", cpu);
-#endif
-
 
 #define P(x) \
 	SEQ_printf(m, "  .%-30s: %Ld\n", #x, (long long)(rt_rq->x))
@@ -243,6 +207,8 @@
 #undef P
 }
 
+extern __read_mostly int sched_clock_running;
+
 static void print_cpu(struct seq_file *m, int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
@@ -314,21 +280,42 @@
 
 static int sched_debug_show(struct seq_file *m, void *v)
 {
-	u64 now = ktime_to_ns(ktime_get());
+	u64 ktime, sched_clk, cpu_clk;
+	unsigned long flags;
 	int cpu;
 
-	SEQ_printf(m, "Sched Debug Version: v0.09, %s %.*s\n",
+	local_irq_save(flags);
+	ktime = ktime_to_ns(ktime_get());
+	sched_clk = sched_clock();
+	cpu_clk = local_clock();
+	local_irq_restore(flags);
+
+	SEQ_printf(m, "Sched Debug Version: v0.10, %s %.*s\n",
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
 		init_utsname()->version);
 
-	SEQ_printf(m, "now at %Lu.%06ld msecs\n", SPLIT_NS(now));
+#define P(x) \
+	SEQ_printf(m, "%-40s: %Ld\n", #x, (long long)(x))
+#define PN(x) \
+	SEQ_printf(m, "%-40s: %Ld.%06ld\n", #x, SPLIT_NS(x))
+	PN(ktime);
+	PN(sched_clk);
+	PN(cpu_clk);
+	P(jiffies);
+#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
+	P(sched_clock_stable);
+#endif
+#undef PN
+#undef P
+
+	SEQ_printf(m, "\n");
+	SEQ_printf(m, "sysctl_sched\n");
 
 #define P(x) \
 	SEQ_printf(m, "  .%-40s: %Ld\n", #x, (long long)(x))
 #define PN(x) \
 	SEQ_printf(m, "  .%-40s: %Ld.%06ld\n", #x, SPLIT_NS(x))
-	P(jiffies);
 	PN(sysctl_sched_latency);
 	PN(sysctl_sched_min_granularity);
 	PN(sysctl_sched_wakeup_granularity);
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 00ebd76..c62ebae 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -89,6 +89,13 @@
 
 const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
 
+/*
+ * The exponential sliding  window over which load is averaged for shares
+ * distribution.
+ * (default: 10msec)
+ */
+unsigned int __read_mostly sysctl_sched_shares_window = 10000000UL;
+
 static const struct sched_class fair_sched_class;
 
 /**************************************************************
@@ -143,6 +150,36 @@
 	return cfs_rq->tg->cfs_rq[this_cpu];
 }
 
+static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
+{
+	if (!cfs_rq->on_list) {
+		/*
+		 * Ensure we either appear before our parent (if already
+		 * enqueued) or force our parent to appear after us when it is
+		 * enqueued.  The fact that we always enqueue bottom-up
+		 * reduces this to two cases.
+		 */
+		if (cfs_rq->tg->parent &&
+		    cfs_rq->tg->parent->cfs_rq[cpu_of(rq_of(cfs_rq))]->on_list) {
+			list_add_rcu(&cfs_rq->leaf_cfs_rq_list,
+				&rq_of(cfs_rq)->leaf_cfs_rq_list);
+		} else {
+			list_add_tail_rcu(&cfs_rq->leaf_cfs_rq_list,
+				&rq_of(cfs_rq)->leaf_cfs_rq_list);
+		}
+
+		cfs_rq->on_list = 1;
+	}
+}
+
+static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
+{
+	if (cfs_rq->on_list) {
+		list_del_rcu(&cfs_rq->leaf_cfs_rq_list);
+		cfs_rq->on_list = 0;
+	}
+}
+
 /* Iterate thr' all leaf cfs_rq's on a runqueue */
 #define for_each_leaf_cfs_rq(rq, cfs_rq) \
 	list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
@@ -246,6 +283,14 @@
 	return &cpu_rq(this_cpu)->cfs;
 }
 
+static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
+{
+}
+
+static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
+{
+}
+
 #define for_each_leaf_cfs_rq(rq, cfs_rq) \
 		for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
 
@@ -417,7 +462,6 @@
 	WRT_SYSCTL(sched_min_granularity);
 	WRT_SYSCTL(sched_latency);
 	WRT_SYSCTL(sched_wakeup_granularity);
-	WRT_SYSCTL(sched_shares_ratelimit);
 #undef WRT_SYSCTL
 
 	return 0;
@@ -495,6 +539,9 @@
 	return calc_delta_fair(sched_slice(cfs_rq, se), se);
 }
 
+static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update);
+static void update_cfs_shares(struct cfs_rq *cfs_rq, long weight_delta);
+
 /*
  * Update the current task's runtime statistics. Skip current tasks that
  * are not in our scheduling class.
@@ -514,6 +561,10 @@
 
 	curr->vruntime += delta_exec_weighted;
 	update_min_vruntime(cfs_rq);
+
+#if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED
+	cfs_rq->load_unacc_exec_time += delta_exec;
+#endif
 }
 
 static void update_curr(struct cfs_rq *cfs_rq)
@@ -633,7 +684,6 @@
 		list_add(&se->group_node, &cfs_rq->tasks);
 	}
 	cfs_rq->nr_running++;
-	se->on_rq = 1;
 }
 
 static void
@@ -647,9 +697,140 @@
 		list_del_init(&se->group_node);
 	}
 	cfs_rq->nr_running--;
-	se->on_rq = 0;
 }
 
+#if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED
+static void update_cfs_rq_load_contribution(struct cfs_rq *cfs_rq,
+					    int global_update)
+{
+	struct task_group *tg = cfs_rq->tg;
+	long load_avg;
+
+	load_avg = div64_u64(cfs_rq->load_avg, cfs_rq->load_period+1);
+	load_avg -= cfs_rq->load_contribution;
+
+	if (global_update || abs(load_avg) > cfs_rq->load_contribution / 8) {
+		atomic_add(load_avg, &tg->load_weight);
+		cfs_rq->load_contribution += load_avg;
+	}
+}
+
+static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
+{
+	u64 period = sysctl_sched_shares_window;
+	u64 now, delta;
+	unsigned long load = cfs_rq->load.weight;
+
+	if (!cfs_rq)
+		return;
+
+	now = rq_of(cfs_rq)->clock;
+	delta = now - cfs_rq->load_stamp;
+
+	/* truncate load history at 4 idle periods */
+	if (cfs_rq->load_stamp > cfs_rq->load_last &&
+	    now - cfs_rq->load_last > 4 * period) {
+		cfs_rq->load_period = 0;
+		cfs_rq->load_avg = 0;
+	}
+
+	cfs_rq->load_stamp = now;
+	cfs_rq->load_unacc_exec_time = 0;
+	cfs_rq->load_period += delta;
+	if (load) {
+		cfs_rq->load_last = now;
+		cfs_rq->load_avg += delta * load;
+	}
+
+	/* consider updating load contribution on each fold or truncate */
+	if (global_update || cfs_rq->load_period > period
+	    || !cfs_rq->load_period)
+		update_cfs_rq_load_contribution(cfs_rq, global_update);
+
+	while (cfs_rq->load_period > period) {
+		/*
+		 * Inline assembly required to prevent the compiler
+		 * optimising this loop into a divmod call.
+		 * See __iter_div_u64_rem() for another example of this.
+		 */
+		asm("" : "+rm" (cfs_rq->load_period));
+		cfs_rq->load_period /= 2;
+		cfs_rq->load_avg /= 2;
+	}
+
+	if (!cfs_rq->curr && !cfs_rq->nr_running && !cfs_rq->load_avg)
+		list_del_leaf_cfs_rq(cfs_rq);
+}
+
+static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+			    unsigned long weight)
+{
+	if (se->on_rq) {
+		/* commit outstanding execution time */
+		if (cfs_rq->curr == se)
+			update_curr(cfs_rq);
+		account_entity_dequeue(cfs_rq, se);
+	}
+
+	update_load_set(&se->load, weight);
+
+	if (se->on_rq)
+		account_entity_enqueue(cfs_rq, se);
+}
+
+static void update_cfs_shares(struct cfs_rq *cfs_rq, long weight_delta)
+{
+	struct task_group *tg;
+	struct sched_entity *se;
+	long load_weight, load, shares;
+
+	if (!cfs_rq)
+		return;
+
+	tg = cfs_rq->tg;
+	se = tg->se[cpu_of(rq_of(cfs_rq))];
+	if (!se)
+		return;
+
+	load = cfs_rq->load.weight + weight_delta;
+
+	load_weight = atomic_read(&tg->load_weight);
+	load_weight -= cfs_rq->load_contribution;
+	load_weight += load;
+
+	shares = (tg->shares * load);
+	if (load_weight)
+		shares /= load_weight;
+
+	if (shares < MIN_SHARES)
+		shares = MIN_SHARES;
+	if (shares > tg->shares)
+		shares = tg->shares;
+
+	reweight_entity(cfs_rq_of(se), se, shares);
+}
+
+static void update_entity_shares_tick(struct cfs_rq *cfs_rq)
+{
+	if (cfs_rq->load_unacc_exec_time > sysctl_sched_shares_window) {
+		update_cfs_load(cfs_rq, 0);
+		update_cfs_shares(cfs_rq, 0);
+	}
+}
+#else /* CONFIG_FAIR_GROUP_SCHED */
+static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
+{
+}
+
+static inline void update_cfs_shares(struct cfs_rq *cfs_rq, long weight_delta)
+{
+}
+
+static inline void update_entity_shares_tick(struct cfs_rq *cfs_rq)
+{
+}
+#endif /* CONFIG_FAIR_GROUP_SCHED */
+
 static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
 #ifdef CONFIG_SCHEDSTATS
@@ -771,6 +952,8 @@
 	 * Update run-time statistics of the 'current'.
 	 */
 	update_curr(cfs_rq);
+	update_cfs_load(cfs_rq, 0);
+	update_cfs_shares(cfs_rq, se->load.weight);
 	account_entity_enqueue(cfs_rq, se);
 
 	if (flags & ENQUEUE_WAKEUP) {
@@ -782,6 +965,10 @@
 	check_spread(cfs_rq, se);
 	if (se != cfs_rq->curr)
 		__enqueue_entity(cfs_rq, se);
+	se->on_rq = 1;
+
+	if (cfs_rq->nr_running == 1)
+		list_add_leaf_cfs_rq(cfs_rq);
 }
 
 static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
@@ -825,8 +1012,11 @@
 
 	if (se != cfs_rq->curr)
 		__dequeue_entity(cfs_rq, se);
+	se->on_rq = 0;
+	update_cfs_load(cfs_rq, 0);
 	account_entity_dequeue(cfs_rq, se);
 	update_min_vruntime(cfs_rq);
+	update_cfs_shares(cfs_rq, 0);
 
 	/*
 	 * Normalize the entity after updating the min_vruntime because the
@@ -955,6 +1145,11 @@
 	 */
 	update_curr(cfs_rq);
 
+	/*
+	 * Update share accounting for long-running entities.
+	 */
+	update_entity_shares_tick(cfs_rq);
+
 #ifdef CONFIG_SCHED_HRTICK
 	/*
 	 * queued ticks are scheduled to match the slice, so don't bother
@@ -1055,6 +1250,13 @@
 		flags = ENQUEUE_WAKEUP;
 	}
 
+	for_each_sched_entity(se) {
+		struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+		update_cfs_load(cfs_rq, 0);
+		update_cfs_shares(cfs_rq, 0);
+	}
+
 	hrtick_update(rq);
 }
 
@@ -1071,12 +1273,20 @@
 	for_each_sched_entity(se) {
 		cfs_rq = cfs_rq_of(se);
 		dequeue_entity(cfs_rq, se, flags);
+
 		/* Don't dequeue parent if it has other entities besides us */
 		if (cfs_rq->load.weight)
 			break;
 		flags |= DEQUEUE_SLEEP;
 	}
 
+	for_each_sched_entity(se) {
+		struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+		update_cfs_load(cfs_rq, 0);
+		update_cfs_shares(cfs_rq, 0);
+	}
+
 	hrtick_update(rq);
 }
 
@@ -1143,51 +1353,20 @@
  * Adding load to a group doesn't make a group heavier, but can cause movement
  * of group shares between cpus. Assuming the shares were perfectly aligned one
  * can calculate the shift in shares.
- *
- * The problem is that perfectly aligning the shares is rather expensive, hence
- * we try to avoid doing that too often - see update_shares(), which ratelimits
- * this change.
- *
- * We compensate this by not only taking the current delta into account, but
- * also considering the delta between when the shares were last adjusted and
- * now.
- *
- * We still saw a performance dip, some tracing learned us that between
- * cgroup:/ and cgroup:/foo balancing the number of affine wakeups increased
- * significantly. Therefore try to bias the error in direction of failing
- * the affine wakeup.
- *
  */
-static long effective_load(struct task_group *tg, int cpu,
-		long wl, long wg)
+static long effective_load(struct task_group *tg, int cpu, long wl, long wg)
 {
 	struct sched_entity *se = tg->se[cpu];
 
 	if (!tg->parent)
 		return wl;
 
-	/*
-	 * By not taking the decrease of shares on the other cpu into
-	 * account our error leans towards reducing the affine wakeups.
-	 */
-	if (!wl && sched_feat(ASYM_EFF_LOAD))
-		return wl;
-
 	for_each_sched_entity(se) {
 		long S, rw, s, a, b;
-		long more_w;
-
-		/*
-		 * Instead of using this increment, also add the difference
-		 * between when the shares were last updated and now.
-		 */
-		more_w = se->my_q->load.weight - se->my_q->rq_weight;
-		wl += more_w;
-		wg += more_w;
 
 		S = se->my_q->tg->shares;
-		s = se->my_q->shares;
-		rw = se->my_q->rq_weight;
+		s = se->load.weight;
+		rw = se->my_q->load.weight;
 
 		a = S*(rw + wl);
 		b = S*rw + s*wg;
@@ -1508,23 +1687,6 @@
 			sd = tmp;
 	}
 
-#ifdef CONFIG_FAIR_GROUP_SCHED
-	if (sched_feat(LB_SHARES_UPDATE)) {
-		/*
-		 * Pick the largest domain to update shares over
-		 */
-		tmp = sd;
-		if (affine_sd && (!tmp || affine_sd->span_weight > sd->span_weight))
-			tmp = affine_sd;
-
-		if (tmp) {
-			raw_spin_unlock(&rq->lock);
-			update_shares(tmp);
-			raw_spin_lock(&rq->lock);
-		}
-	}
-#endif
-
 	if (affine_sd) {
 		if (cpu == prev_cpu || wake_affine(affine_sd, p, sync))
 			return select_idle_sibling(p, cpu);
@@ -1909,6 +2071,48 @@
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
+/*
+ * update tg->load_weight by folding this cpu's load_avg
+ */
+static int update_shares_cpu(struct task_group *tg, int cpu)
+{
+	struct cfs_rq *cfs_rq;
+	unsigned long flags;
+	struct rq *rq;
+
+	if (!tg->se[cpu])
+		return 0;
+
+	rq = cpu_rq(cpu);
+	cfs_rq = tg->cfs_rq[cpu];
+
+	raw_spin_lock_irqsave(&rq->lock, flags);
+
+	update_rq_clock(rq);
+	update_cfs_load(cfs_rq, 1);
+
+	/*
+	 * We need to update shares after updating tg->load_weight in
+	 * order to adjust the weight of groups with long running tasks.
+	 */
+	update_cfs_shares(cfs_rq, 0);
+
+	raw_spin_unlock_irqrestore(&rq->lock, flags);
+
+	return 0;
+}
+
+static void update_shares(int cpu)
+{
+	struct cfs_rq *cfs_rq;
+	struct rq *rq = cpu_rq(cpu);
+
+	rcu_read_lock();
+	for_each_leaf_cfs_rq(rq, cfs_rq)
+		update_shares_cpu(cfs_rq->tg, cpu);
+	rcu_read_unlock();
+}
+
 static unsigned long
 load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
 		  unsigned long max_load_move,
@@ -1956,6 +2160,10 @@
 	return max_load_move - rem_load_move;
 }
 #else
+static inline void update_shares(int cpu)
+{
+}
+
 static unsigned long
 load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
 		  unsigned long max_load_move,
@@ -3032,7 +3240,6 @@
 	schedstat_inc(sd, lb_count[idle]);
 
 redo:
-	update_shares(sd);
 	group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle,
 				   cpus, balance);
 
@@ -3174,8 +3381,6 @@
 	else
 		ld_moved = 0;
 out:
-	if (ld_moved)
-		update_shares(sd);
 	return ld_moved;
 }
 
@@ -3199,6 +3404,7 @@
 	 */
 	raw_spin_unlock(&this_rq->lock);
 
+	update_shares(this_cpu);
 	for_each_domain(this_cpu, sd) {
 		unsigned long interval;
 		int balance = 1;
@@ -3569,6 +3775,8 @@
 	int update_next_balance = 0;
 	int need_serialize;
 
+	update_shares(cpu);
+
 	for_each_domain(cpu, sd) {
 		if (!(sd->flags & SD_LOAD_BALANCE))
 			continue;
diff --git a/kernel/sched_features.h b/kernel/sched_features.h
index 185f920..68e69ac 100644
--- a/kernel/sched_features.h
+++ b/kernel/sched_features.h
@@ -52,8 +52,6 @@
 SCHED_FEAT(HRTICK, 0)
 SCHED_FEAT(DOUBLE_TICK, 0)
 SCHED_FEAT(LB_BIAS, 1)
-SCHED_FEAT(LB_SHARES_UPDATE, 1)
-SCHED_FEAT(ASYM_EFF_LOAD, 1)
 
 /*
  * Spin-wait on mutex acquisition when the mutex owner is running on
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index bea7d79..c914ec7 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -183,6 +183,17 @@
 	return ktime_to_ns(rt_rq->tg->rt_bandwidth.rt_period);
 }
 
+static inline void list_add_leaf_rt_rq(struct rt_rq *rt_rq)
+{
+	list_add_rcu(&rt_rq->leaf_rt_rq_list,
+			&rq_of_rt_rq(rt_rq)->leaf_rt_rq_list);
+}
+
+static inline void list_del_leaf_rt_rq(struct rt_rq *rt_rq)
+{
+	list_del_rcu(&rt_rq->leaf_rt_rq_list);
+}
+
 #define for_each_leaf_rt_rq(rt_rq, rq) \
 	list_for_each_entry_rcu(rt_rq, &rq->leaf_rt_rq_list, leaf_rt_rq_list)
 
@@ -276,6 +287,14 @@
 	return ktime_to_ns(def_rt_bandwidth.rt_period);
 }
 
+static inline void list_add_leaf_rt_rq(struct rt_rq *rt_rq)
+{
+}
+
+static inline void list_del_leaf_rt_rq(struct rt_rq *rt_rq)
+{
+}
+
 #define for_each_leaf_rt_rq(rt_rq, rq) \
 	for (rt_rq = &rq->rt; rt_rq; rt_rq = NULL)
 
@@ -825,6 +844,9 @@
 	if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running))
 		return;
 
+	if (!rt_rq->rt_nr_running)
+		list_add_leaf_rt_rq(rt_rq);
+
 	if (head)
 		list_add(&rt_se->run_list, queue);
 	else
@@ -844,6 +866,8 @@
 		__clear_bit(rt_se_prio(rt_se), array->bitmap);
 
 	dec_rt_tasks(rt_se, rt_rq);
+	if (!rt_rq->rt_nr_running)
+		list_del_leaf_rt_rq(rt_rq);
 }
 
 /*
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 18f4be0..0823778 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -70,7 +70,7 @@
 static void wakeup_softirqd(void)
 {
 	/* Interrupts are disabled: no need to stop preemption */
-	struct task_struct *tsk = __get_cpu_var(ksoftirqd);
+	struct task_struct *tsk = __this_cpu_read(ksoftirqd);
 
 	if (tsk && tsk->state != TASK_RUNNING)
 		wake_up_process(tsk);
@@ -388,8 +388,8 @@
 
 	local_irq_save(flags);
 	t->next = NULL;
-	*__get_cpu_var(tasklet_vec).tail = t;
-	__get_cpu_var(tasklet_vec).tail = &(t->next);
+	*__this_cpu_read(tasklet_vec.tail) = t;
+	__this_cpu_write(tasklet_vec.tail, &(t->next));
 	raise_softirq_irqoff(TASKLET_SOFTIRQ);
 	local_irq_restore(flags);
 }
@@ -402,8 +402,8 @@
 
 	local_irq_save(flags);
 	t->next = NULL;
-	*__get_cpu_var(tasklet_hi_vec).tail = t;
-	__get_cpu_var(tasklet_hi_vec).tail = &(t->next);
+	*__this_cpu_read(tasklet_hi_vec.tail) = t;
+	__this_cpu_write(tasklet_hi_vec.tail,  &(t->next));
 	raise_softirq_irqoff(HI_SOFTIRQ);
 	local_irq_restore(flags);
 }
@@ -414,8 +414,8 @@
 {
 	BUG_ON(!irqs_disabled());
 
-	t->next = __get_cpu_var(tasklet_hi_vec).head;
-	__get_cpu_var(tasklet_hi_vec).head = t;
+	t->next = __this_cpu_read(tasklet_hi_vec.head);
+	__this_cpu_write(tasklet_hi_vec.head, t);
 	__raise_softirq_irqoff(HI_SOFTIRQ);
 }
 
@@ -426,9 +426,9 @@
 	struct tasklet_struct *list;
 
 	local_irq_disable();
-	list = __get_cpu_var(tasklet_vec).head;
-	__get_cpu_var(tasklet_vec).head = NULL;
-	__get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
+	list = __this_cpu_read(tasklet_vec.head);
+	__this_cpu_write(tasklet_vec.head, NULL);
+	__this_cpu_write(tasklet_vec.tail, &__get_cpu_var(tasklet_vec).head);
 	local_irq_enable();
 
 	while (list) {
@@ -449,8 +449,8 @@
 
 		local_irq_disable();
 		t->next = NULL;
-		*__get_cpu_var(tasklet_vec).tail = t;
-		__get_cpu_var(tasklet_vec).tail = &(t->next);
+		*__this_cpu_read(tasklet_vec.tail) = t;
+		__this_cpu_write(tasklet_vec.tail, &(t->next));
 		__raise_softirq_irqoff(TASKLET_SOFTIRQ);
 		local_irq_enable();
 	}
@@ -461,9 +461,9 @@
 	struct tasklet_struct *list;
 
 	local_irq_disable();
-	list = __get_cpu_var(tasklet_hi_vec).head;
-	__get_cpu_var(tasklet_hi_vec).head = NULL;
-	__get_cpu_var(tasklet_hi_vec).tail = &__get_cpu_var(tasklet_hi_vec).head;
+	list = __this_cpu_read(tasklet_hi_vec.head);
+	__this_cpu_write(tasklet_hi_vec.head, NULL);
+	__this_cpu_write(tasklet_hi_vec.tail, &__get_cpu_var(tasklet_hi_vec).head);
 	local_irq_enable();
 
 	while (list) {
@@ -484,8 +484,8 @@
 
 		local_irq_disable();
 		t->next = NULL;
-		*__get_cpu_var(tasklet_hi_vec).tail = t;
-		__get_cpu_var(tasklet_hi_vec).tail = &(t->next);
+		*__this_cpu_read(tasklet_hi_vec.tail) = t;
+		__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
 		__raise_softirq_irqoff(HI_SOFTIRQ);
 		local_irq_enable();
 	}
@@ -802,16 +802,16 @@
 
 	/* Find end, append list for that CPU. */
 	if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) {
-		*(__get_cpu_var(tasklet_vec).tail) = per_cpu(tasklet_vec, cpu).head;
-		__get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail;
+		*__this_cpu_read(tasklet_vec.tail) = per_cpu(tasklet_vec, cpu).head;
+		this_cpu_write(tasklet_vec.tail, per_cpu(tasklet_vec, cpu).tail);
 		per_cpu(tasklet_vec, cpu).head = NULL;
 		per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
 	}
 	raise_softirq_irqoff(TASKLET_SOFTIRQ);
 
 	if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) {
-		*__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head;
-		__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail;
+		*__this_cpu_read(tasklet_hi_vec.tail) = per_cpu(tasklet_hi_vec, cpu).head;
+		__this_cpu_write(tasklet_hi_vec.tail, per_cpu(tasklet_hi_vec, cpu).tail);
 		per_cpu(tasklet_hi_vec, cpu).head = NULL;
 		per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
 	}
@@ -853,7 +853,9 @@
 			     cpumask_any(cpu_online_mask));
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN: {
-		struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+		static const struct sched_param param = {
+			.sched_priority = MAX_RT_PRIO-1
+		};
 
 		p = per_cpu(ksoftirqd, hotcpu);
 		per_cpu(ksoftirqd, hotcpu) = NULL;
diff --git a/kernel/srcu.c b/kernel/srcu.c
index c71e075..98d8c1e 100644
--- a/kernel/srcu.c
+++ b/kernel/srcu.c
@@ -31,6 +31,7 @@
 #include <linux/rcupdate.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
+#include <linux/delay.h>
 #include <linux/srcu.h>
 
 static int init_srcu_struct_fields(struct srcu_struct *sp)
@@ -203,9 +204,14 @@
 	 * all srcu_read_lock() calls using the old counters have completed.
 	 * Their corresponding critical sections might well be still
 	 * executing, but the srcu_read_lock() primitives themselves
-	 * will have finished executing.
+	 * will have finished executing.  We initially give readers
+	 * an arbitrarily chosen 10 microseconds to get out of their
+	 * SRCU read-side critical sections, then loop waiting 1/HZ
+	 * seconds per iteration.
 	 */
 
+	if (srcu_readers_active_idx(sp, idx))
+		udelay(CONFIG_SRCU_SYNCHRONIZE_DELAY);
 	while (srcu_readers_active_idx(sp, idx))
 		schedule_timeout_interruptible(1);
 
diff --git a/kernel/sys.c b/kernel/sys.c
index 7f5a0cd..2745dcd 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1080,8 +1080,10 @@
 	err = session;
 out:
 	write_unlock_irq(&tasklist_lock);
-	if (err > 0)
+	if (err > 0) {
 		proc_sid_connector(group_leader);
+		sched_autogroup_create_attach(group_leader);
+	}
 	return err;
 }
 
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 5abfa15..ae5cbb1 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -259,8 +259,6 @@
 static int max_wakeup_granularity_ns = NSEC_PER_SEC;	/* 1 second */
 static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE;
 static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1;
-static int min_sched_shares_ratelimit = 100000; /* 100 usec */
-static int max_sched_shares_ratelimit = NSEC_PER_SEC; /* 1 second */
 #endif
 
 #ifdef CONFIG_COMPACTION
@@ -305,15 +303,6 @@
 		.extra2		= &max_wakeup_granularity_ns,
 	},
 	{
-		.procname	= "sched_shares_ratelimit",
-		.data		= &sysctl_sched_shares_ratelimit,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= sched_proc_update_handler,
-		.extra1		= &min_sched_shares_ratelimit,
-		.extra2		= &max_sched_shares_ratelimit,
-	},
-	{
 		.procname	= "sched_tunable_scaling",
 		.data		= &sysctl_sched_tunable_scaling,
 		.maxlen		= sizeof(enum sched_tunable_scaling),
@@ -323,14 +312,6 @@
 		.extra2		= &max_sched_tunable_scaling,
 	},
 	{
-		.procname	= "sched_shares_thresh",
-		.data		= &sysctl_sched_shares_thresh,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
-		.extra1		= &zero,
-	},
-	{
 		.procname	= "sched_migration_cost",
 		.data		= &sysctl_sched_migration_cost,
 		.maxlen		= sizeof(unsigned int),
@@ -352,6 +333,13 @@
 		.proc_handler	= proc_dointvec,
 	},
 	{
+		.procname	= "sched_shares_window",
+		.data		= &sysctl_sched_shares_window,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
 		.procname	= "timer_migration",
 		.data		= &sysctl_timer_migration,
 		.maxlen		= sizeof(unsigned int),
@@ -382,6 +370,17 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
+#ifdef CONFIG_SCHED_AUTOGROUP
+	{
+		.procname	= "sched_autogroup_enabled",
+		.data		= &sysctl_sched_autogroup_enabled,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+		.extra1		= &zero,
+		.extra2		= &one,
+	},
+#endif
 #ifdef CONFIG_PROVE_LOCKING
 	{
 		.procname	= "prove_locking",
@@ -745,8 +744,15 @@
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
+	{
+		.procname       = "nmi_watchdog",
+		.data           = &watchdog_enabled,
+		.maxlen         = sizeof (int),
+		.mode           = 0644,
+		.proc_handler   = proc_dowatchdog_enabled,
+	},
 #endif
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) && !defined(CONFIG_LOCKUP_DETECTOR)
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
 	{
 		.procname       = "unknown_nmi_panic",
 		.data           = &unknown_nmi_panic,
@@ -754,13 +760,6 @@
 		.mode           = 0644,
 		.proc_handler   = proc_dointvec,
 	},
-	{
-		.procname       = "nmi_watchdog",
-		.data           = &nmi_watchdog_enabled,
-		.maxlen         = sizeof (int),
-		.mode           = 0644,
-		.proc_handler   = proc_nmi_enabled,
-	},
 #endif
 #if defined(CONFIG_X86)
 	{
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 1357c57..4b2545a 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -136,7 +136,6 @@
 	{ CTL_INT,	KERN_IA64_UNALIGNED,		"ignore-unaligned-usertrap" },
 	{ CTL_INT,	KERN_COMPAT_LOG,		"compat-log" },
 	{ CTL_INT,	KERN_MAX_LOCK_DEPTH,		"max_lock_depth" },
-	{ CTL_INT,	KERN_NMI_WATCHDOG,		"nmi_watchdog" },
 	{ CTL_INT,	KERN_PANIC_ON_NMI,		"panic_on_unrecovered_nmi" },
 	{}
 };
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 3308fd7..69691eb 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -89,8 +89,7 @@
 		return -ENOMEM;
 
 	if (!info) {
-		int seq = get_cpu_var(taskstats_seqnum)++;
-		put_cpu_var(taskstats_seqnum);
+		int seq = this_cpu_inc_return(taskstats_seqnum) - 1;
 
 		reply = genlmsg_put(skb, 0, seq, &family, 0, cmd);
 	} else
@@ -612,7 +611,7 @@
 		fill_tgid_exit(tsk);
 	}
 
-	listeners = &__raw_get_cpu_var(listener_array);
+	listeners = __this_cpu_ptr(&listener_array);
 	if (list_empty(&listeners->list))
 		return;
 
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index c18d7ef..df140cd 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -152,6 +152,7 @@
 	 */
 	for (sft = 32; sft > 0; sft--) {
 		tmp = (u64) to << sft;
+		tmp += from / 2;
 		do_div(tmp, from);
 		if ((tmp >> sftacc) == 0)
 			break;
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index b6b898d..051bc80 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -49,7 +49,7 @@
  */
 int tick_is_oneshot_available(void)
 {
-	struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+	struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
 
 	return dev && (dev->features & CLOCK_EVT_FEAT_ONESHOT);
 }
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
index aada0e5..5cbc101 100644
--- a/kernel/time/tick-oneshot.c
+++ b/kernel/time/tick-oneshot.c
@@ -95,7 +95,7 @@
  */
 int tick_program_event(ktime_t expires, int force)
 {
-	struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+	struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
 
 	return tick_dev_program_event(dev, expires, force);
 }
@@ -167,7 +167,7 @@
 	int ret;
 
 	local_irq_save(flags);
-	ret = __get_cpu_var(tick_cpu_device).mode == TICKDEV_MODE_ONESHOT;
+	ret = __this_cpu_read(tick_cpu_device.mode) == TICKDEV_MODE_ONESHOT;
 	local_irq_restore(flags);
 
 	return ret;
diff --git a/kernel/time/timecompare.c b/kernel/time/timecompare.c
index ac38fbb..a9ae369 100644
--- a/kernel/time/timecompare.c
+++ b/kernel/time/timecompare.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/math64.h>
+#include <linux/kernel.h>
 
 /*
  * fixed point arithmetic scale factor for skew
@@ -57,11 +58,11 @@
 	int index;
 	int num_samples = sync->num_samples;
 
-	if (num_samples > sizeof(buffer)/sizeof(buffer[0])) {
+	if (num_samples > ARRAY_SIZE(buffer)) {
 		samples = kmalloc(sizeof(*samples) * num_samples, GFP_ATOMIC);
 		if (!samples) {
 			samples = buffer;
-			num_samples = sizeof(buffer)/sizeof(buffer[0]);
+			num_samples = ARRAY_SIZE(buffer);
 		}
 	} else {
 		samples = buffer;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 49010d8..5bb86da 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -32,6 +32,8 @@
 	cycle_t cycle_interval;
 	/* Number of clock shifted nano seconds in one NTP interval. */
 	u64	xtime_interval;
+	/* shifted nano seconds left over when rounding cycle_interval */
+	s64	xtime_remainder;
 	/* Raw nano seconds accumulated per NTP interval. */
 	u32	raw_interval;
 
@@ -62,7 +64,7 @@
 static void timekeeper_setup_internals(struct clocksource *clock)
 {
 	cycle_t interval;
-	u64 tmp;
+	u64 tmp, ntpinterval;
 
 	timekeeper.clock = clock;
 	clock->cycle_last = clock->read(clock);
@@ -70,6 +72,7 @@
 	/* Do the ns -> cycle conversion first, using original mult */
 	tmp = NTP_INTERVAL_LENGTH;
 	tmp <<= clock->shift;
+	ntpinterval = tmp;
 	tmp += clock->mult/2;
 	do_div(tmp, clock->mult);
 	if (tmp == 0)
@@ -80,6 +83,7 @@
 
 	/* Go back from cycles -> shifted ns */
 	timekeeper.xtime_interval = (u64) interval * clock->mult;
+	timekeeper.xtime_remainder = ntpinterval - timekeeper.xtime_interval;
 	timekeeper.raw_interval =
 		((u64) interval * clock->mult) >> clock->shift;
 
@@ -719,7 +723,8 @@
 
 	/* Accumulate error between NTP and clock interval */
 	timekeeper.ntp_error += tick_length << shift;
-	timekeeper.ntp_error -= timekeeper.xtime_interval <<
+	timekeeper.ntp_error -=
+	    (timekeeper.xtime_interval + timekeeper.xtime_remainder) <<
 				(timekeeper.ntp_error_shift + shift);
 
 	return offset;
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index ab8f5e3..32a19f9 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -79,26 +79,26 @@
 {
 	struct hrtimer *timer, tmp;
 	unsigned long next = 0, i;
-	struct rb_node *curr;
+	struct timerqueue_node *curr;
 	unsigned long flags;
 
 next_one:
 	i = 0;
 	raw_spin_lock_irqsave(&base->cpu_base->lock, flags);
 
-	curr = base->first;
+	curr = timerqueue_getnext(&base->active);
 	/*
 	 * Crude but we have to do this O(N*N) thing, because
 	 * we have to unlock the base when printing:
 	 */
 	while (curr && i < next) {
-		curr = rb_next(curr);
+		curr = timerqueue_iterate_next(curr);
 		i++;
 	}
 
 	if (curr) {
 
-		timer = rb_entry(curr, struct hrtimer, node);
+		timer = container_of(curr, struct hrtimer, node);
 		tmp = *timer;
 		raw_spin_unlock_irqrestore(&base->cpu_base->lock, flags);
 
diff --git a/kernel/timer.c b/kernel/timer.c
index 353b922..43ca993 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -88,18 +88,6 @@
 EXPORT_SYMBOL(boot_tvec_bases);
 static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
 
-/*
- * Note that all tvec_bases are 2 byte aligned and lower bit of
- * base in timer_list is guaranteed to be zero. Use the LSB to
- * indicate whether the timer is deferrable.
- *
- * A deferrable timer will work normally when the system is busy, but
- * will not cause a CPU to come out of idle just to service it; instead,
- * the timer will be serviced when the CPU eventually wakes up with a
- * subsequent non-deferrable timer.
- */
-#define TBASE_DEFERRABLE_FLAG		(0x1)
-
 /* Functions below help us manage 'deferrable' flag */
 static inline unsigned int tbase_get_deferrable(struct tvec_base *base)
 {
@@ -113,8 +101,7 @@
 
 static inline void timer_set_deferrable(struct timer_list *timer)
 {
-	timer->base = ((struct tvec_base *)((unsigned long)(timer->base) |
-				       TBASE_DEFERRABLE_FLAG));
+	timer->base = TBASE_MAKE_DEFERRED(timer->base);
 }
 
 static inline void
@@ -343,15 +330,6 @@
 }
 EXPORT_SYMBOL_GPL(set_timer_slack);
 
-
-static inline void set_running_timer(struct tvec_base *base,
-					struct timer_list *timer)
-{
-#ifdef CONFIG_SMP
-	base->running_timer = timer;
-#endif
-}
-
 static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
 {
 	unsigned long expires = timer->expires;
@@ -936,15 +914,12 @@
 }
 EXPORT_SYMBOL(del_timer);
 
-#ifdef CONFIG_SMP
 /**
  * try_to_del_timer_sync - Try to deactivate a timer
  * @timer: timer do del
  *
  * This function tries to deactivate a timer. Upon successful (ret >= 0)
  * exit the timer is not queued and the handler is not running on any CPU.
- *
- * It must not be called from interrupt contexts.
  */
 int try_to_del_timer_sync(struct timer_list *timer)
 {
@@ -973,6 +948,7 @@
 }
 EXPORT_SYMBOL(try_to_del_timer_sync);
 
+#ifdef CONFIG_SMP
 /**
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
@@ -983,7 +959,7 @@
  *
  * Synchronization rules: Callers must prevent restarting of the timer,
  * otherwise this function is meaningless. It must not be called from
- * interrupt contexts. The caller must not hold locks which would prevent
+ * hardirq contexts. The caller must not hold locks which would prevent
  * completion of the timer's handler. The timer's handler must not call
  * add_timer_on(). Upon exit the timer is not queued and the handler is
  * not running on any CPU.
@@ -993,14 +969,16 @@
 int del_timer_sync(struct timer_list *timer)
 {
 #ifdef CONFIG_LOCKDEP
-	unsigned long flags;
-
-	local_irq_save(flags);
+	local_bh_disable();
 	lock_map_acquire(&timer->lockdep_map);
 	lock_map_release(&timer->lockdep_map);
-	local_irq_restore(flags);
+	local_bh_enable();
 #endif
-
+	/*
+	 * don't use it in hardirq context, because it
+	 * could lead to deadlock.
+	 */
+	WARN_ON(in_irq());
 	for (;;) {
 		int ret = try_to_del_timer_sync(timer);
 		if (ret >= 0)
@@ -1111,7 +1089,7 @@
 
 			timer_stats_account_timer(timer);
 
-			set_running_timer(base, timer);
+			base->running_timer = timer;
 			detach_timer(timer, 1);
 
 			spin_unlock_irq(&base->lock);
@@ -1119,7 +1097,7 @@
 			spin_lock_irq(&base->lock);
 		}
 	}
-	set_running_timer(base, NULL);
+	base->running_timer = NULL;
 	spin_unlock_irq(&base->lock);
 }
 
@@ -1249,7 +1227,7 @@
  */
 unsigned long get_next_timer_interrupt(unsigned long now)
 {
-	struct tvec_base *base = __get_cpu_var(tvec_bases);
+	struct tvec_base *base = __this_cpu_read(tvec_bases);
 	unsigned long expires;
 
 	/*
@@ -1298,7 +1276,7 @@
  */
 static void run_timer_softirq(struct softirq_action *h)
 {
-	struct tvec_base *base = __get_cpu_var(tvec_bases);
+	struct tvec_base *base = __this_cpu_read(tvec_bases);
 
 	hrtimer_run_pending();
 
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index ea37e2f..14674dc 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -69,6 +69,21 @@
 	select CONTEXT_SWITCH_TRACER
 	bool
 
+config EVENT_POWER_TRACING_DEPRECATED
+	depends on EVENT_TRACING
+	bool "Deprecated power event trace API, to be removed"
+	default y
+	help
+	  Provides old power event types:
+	  C-state/idle accounting events:
+	  power:power_start
+	  power:power_end
+	  and old cpufreq accounting event:
+	  power:power_frequency
+	  This is for userspace compatibility
+	  and will vanish after 5 kernel iterations,
+	  namely 2.6.41.
+
 config CONTEXT_SWITCH_TRACER
 	bool
 
diff --git a/kernel/trace/power-traces.c b/kernel/trace/power-traces.c
index a22582a..f55fcf6 100644
--- a/kernel/trace/power-traces.c
+++ b/kernel/trace/power-traces.c
@@ -13,5 +13,8 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/power.h>
 
-EXPORT_TRACEPOINT_SYMBOL_GPL(power_frequency);
+#ifdef EVENT_POWER_TRACING_DEPRECATED
+EXPORT_TRACEPOINT_SYMBOL_GPL(power_start);
+#endif
+EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle);
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 9ed509a..bd1c35a 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -3853,6 +3853,13 @@
 
 		/* Need to copy one event at a time */
 		do {
+			/* We need the size of one event, because
+			 * rb_advance_reader only advances by one event,
+			 * whereas rb_event_ts_length may include the size of
+			 * one or two events.
+			 * We have already ensured there's enough space if this
+			 * is a time extend. */
+			size = rb_event_length(event);
 			memcpy(bpage->data + pos, rpage->data + rpos, size);
 
 			len -= size;
@@ -3867,7 +3874,7 @@
 			event = rb_reader_event(cpu_buffer);
 			/* Always keep the time extend and data together */
 			size = rb_event_ts_length(event);
-		} while (len > size);
+		} while (len >= size);
 
 		/* update bpage */
 		local_set(&bpage->commit, pos);
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 39c059c..19a359d 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -21,17 +21,46 @@
 /* Count the events in use (per event id, not per instance) */
 static int	total_ref_count;
 
+static int perf_trace_event_perm(struct ftrace_event_call *tp_event,
+				 struct perf_event *p_event)
+{
+	/* No tracing, just counting, so no obvious leak */
+	if (!(p_event->attr.sample_type & PERF_SAMPLE_RAW))
+		return 0;
+
+	/* Some events are ok to be traced by non-root users... */
+	if (p_event->attach_state == PERF_ATTACH_TASK) {
+		if (tp_event->flags & TRACE_EVENT_FL_CAP_ANY)
+			return 0;
+	}
+
+	/*
+	 * ...otherwise raw tracepoint data can be a severe data leak,
+	 * only allow root to have these.
+	 */
+	if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	return 0;
+}
+
 static int perf_trace_event_init(struct ftrace_event_call *tp_event,
 				 struct perf_event *p_event)
 {
 	struct hlist_head __percpu *list;
-	int ret = -ENOMEM;
+	int ret;
 	int cpu;
 
+	ret = perf_trace_event_perm(tp_event, p_event);
+	if (ret)
+		return ret;
+
 	p_event->tp_event = tp_event;
 	if (tp_event->perf_refcount++ > 0)
 		return 0;
 
+	ret = -ENOMEM;
+
 	list = alloc_percpu(struct hlist_head);
 	if (!list)
 		goto fail;
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 0725eea..35fde09 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -27,6 +27,12 @@
 
 DEFINE_MUTEX(event_mutex);
 
+DEFINE_MUTEX(event_storage_mutex);
+EXPORT_SYMBOL_GPL(event_storage_mutex);
+
+char event_storage[EVENT_STORAGE_SIZE];
+EXPORT_SYMBOL_GPL(event_storage);
+
 LIST_HEAD(ftrace_events);
 LIST_HEAD(ftrace_common_fields);
 
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index 4ba44de..4b74d71 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -83,13 +83,19 @@
 
 #undef __array
 #define __array(type, item, len)					\
-	BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);				\
-	ret = trace_define_field(event_call, #type "[" #len "]", #item,	\
+	do {								\
+		BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);			\
+		mutex_lock(&event_storage_mutex);			\
+		snprintf(event_storage, sizeof(event_storage),		\
+			 "%s[%d]", #type, len);				\
+		ret = trace_define_field(event_call, event_storage, #item, \
 				 offsetof(typeof(field), item),		\
 				 sizeof(field.item),			\
 				 is_signed_type(type), FILTER_OTHER);	\
-	if (ret)							\
-		return ret;
+		mutex_unlock(&event_storage_mutex);			\
+		if (ret)						\
+			return ret;					\
+	} while (0);
 
 #undef __array_desc
 #define __array_desc(type, container, item, len)			\
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 155a415..659732e 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -558,7 +558,7 @@
 static int trace_wakeup_test_thread(void *data)
 {
 	/* Make this a RT thread, doesn't need to be too high */
-	struct sched_param param = { .sched_priority = 5 };
+	static const struct sched_param param = { .sched_priority = 5 };
 	struct completion *x = data;
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
diff --git a/kernel/user.c b/kernel/user.c
index 2c7d8d5..5c598ca 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -158,6 +158,7 @@
 		spin_lock_irq(&uidhash_lock);
 		up = uid_hash_find(uid, hashent);
 		if (up) {
+			put_user_ns(ns);
 			key_put(new->uid_keyring);
 			key_put(new->session_keyring);
 			kmem_cache_free(uid_cachep, new);
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 6e3c41a..d7ebdf4 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -57,6 +57,8 @@
 {
 	if (!strncmp(str, "panic", 5))
 		hardlockup_panic = 1;
+	else if (!strncmp(str, "0", 1))
+		no_watchdog = 1;
 	return 1;
 }
 __setup("nmi_watchdog=", hardlockup_panic_setup);
@@ -116,12 +118,12 @@
 {
 	int this_cpu = smp_processor_id();
 
-	__get_cpu_var(watchdog_touch_ts) = get_timestamp(this_cpu);
+	__this_cpu_write(watchdog_touch_ts, get_timestamp(this_cpu));
 }
 
 void touch_softlockup_watchdog(void)
 {
-	__raw_get_cpu_var(watchdog_touch_ts) = 0;
+	__this_cpu_write(watchdog_touch_ts, 0);
 }
 EXPORT_SYMBOL(touch_softlockup_watchdog);
 
@@ -165,12 +167,12 @@
 /* watchdog detector functions */
 static int is_hardlockup(void)
 {
-	unsigned long hrint = __get_cpu_var(hrtimer_interrupts);
+	unsigned long hrint = __this_cpu_read(hrtimer_interrupts);
 
-	if (__get_cpu_var(hrtimer_interrupts_saved) == hrint)
+	if (__this_cpu_read(hrtimer_interrupts_saved) == hrint)
 		return 1;
 
-	__get_cpu_var(hrtimer_interrupts_saved) = hrint;
+	__this_cpu_write(hrtimer_interrupts_saved, hrint);
 	return 0;
 }
 #endif
@@ -203,8 +205,8 @@
 	/* Ensure the watchdog never gets throttled */
 	event->hw.interrupts = 0;
 
-	if (__get_cpu_var(watchdog_nmi_touch) == true) {
-		__get_cpu_var(watchdog_nmi_touch) = false;
+	if (__this_cpu_read(watchdog_nmi_touch) == true) {
+		__this_cpu_write(watchdog_nmi_touch, false);
 		return;
 	}
 
@@ -218,7 +220,7 @@
 		int this_cpu = smp_processor_id();
 
 		/* only print hardlockups once */
-		if (__get_cpu_var(hard_watchdog_warn) == true)
+		if (__this_cpu_read(hard_watchdog_warn) == true)
 			return;
 
 		if (hardlockup_panic)
@@ -226,16 +228,16 @@
 		else
 			WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
 
-		__get_cpu_var(hard_watchdog_warn) = true;
+		__this_cpu_write(hard_watchdog_warn, true);
 		return;
 	}
 
-	__get_cpu_var(hard_watchdog_warn) = false;
+	__this_cpu_write(hard_watchdog_warn, false);
 	return;
 }
 static void watchdog_interrupt_count(void)
 {
-	__get_cpu_var(hrtimer_interrupts)++;
+	__this_cpu_inc(hrtimer_interrupts);
 }
 #else
 static inline void watchdog_interrupt_count(void) { return; }
@@ -244,7 +246,7 @@
 /* watchdog kicker functions */
 static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 {
-	unsigned long touch_ts = __get_cpu_var(watchdog_touch_ts);
+	unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts);
 	struct pt_regs *regs = get_irq_regs();
 	int duration;
 
@@ -252,18 +254,18 @@
 	watchdog_interrupt_count();
 
 	/* kick the softlockup detector */
-	wake_up_process(__get_cpu_var(softlockup_watchdog));
+	wake_up_process(__this_cpu_read(softlockup_watchdog));
 
 	/* .. and repeat */
 	hrtimer_forward_now(hrtimer, ns_to_ktime(get_sample_period()));
 
 	if (touch_ts == 0) {
-		if (unlikely(__get_cpu_var(softlockup_touch_sync))) {
+		if (unlikely(__this_cpu_read(softlockup_touch_sync))) {
 			/*
 			 * If the time stamp was touched atomically
 			 * make sure the scheduler tick is up to date.
 			 */
-			__get_cpu_var(softlockup_touch_sync) = false;
+			__this_cpu_write(softlockup_touch_sync, false);
 			sched_clock_tick();
 		}
 		__touch_watchdog();
@@ -279,7 +281,7 @@
 	duration = is_softlockup(touch_ts);
 	if (unlikely(duration)) {
 		/* only warn once */
-		if (__get_cpu_var(soft_watchdog_warn) == true)
+		if (__this_cpu_read(soft_watchdog_warn) == true)
 			return HRTIMER_RESTART;
 
 		printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
@@ -294,9 +296,9 @@
 
 		if (softlockup_panic)
 			panic("softlockup: hung tasks");
-		__get_cpu_var(soft_watchdog_warn) = true;
+		__this_cpu_write(soft_watchdog_warn, true);
 	} else
-		__get_cpu_var(soft_watchdog_warn) = false;
+		__this_cpu_write(soft_watchdog_warn, false);
 
 	return HRTIMER_RESTART;
 }
@@ -307,7 +309,7 @@
  */
 static int watchdog(void *unused)
 {
-	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+	static struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 	struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
@@ -364,7 +366,8 @@
 		goto out_save;
 	}
 
-	printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event);
+	printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n",
+	       cpu, PTR_ERR(event));
 	return PTR_ERR(event);
 
 	/* success path */
@@ -547,13 +550,13 @@
 	.notifier_call = cpu_callback
 };
 
-static int __init spawn_watchdog_task(void)
+void __init lockup_detector_init(void)
 {
 	void *cpu = (void *)(long)smp_processor_id();
 	int err;
 
 	if (no_watchdog)
-		return 0;
+		return;
 
 	err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
 	WARN_ON(notifier_to_errno(err));
@@ -561,6 +564,5 @@
 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
 	register_cpu_notifier(&cpu_nfb);
 
-	return 0;
+	return;
 }
-early_initcall(spawn_watchdog_task);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index e785b0f..8ee6ec8 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -932,6 +932,38 @@
 		wake_up_worker(gcwq);
 }
 
+/*
+ * Test whether @work is being queued from another work executing on the
+ * same workqueue.  This is rather expensive and should only be used from
+ * cold paths.
+ */
+static bool is_chained_work(struct workqueue_struct *wq)
+{
+	unsigned long flags;
+	unsigned int cpu;
+
+	for_each_gcwq_cpu(cpu) {
+		struct global_cwq *gcwq = get_gcwq(cpu);
+		struct worker *worker;
+		struct hlist_node *pos;
+		int i;
+
+		spin_lock_irqsave(&gcwq->lock, flags);
+		for_each_busy_worker(worker, i, pos, gcwq) {
+			if (worker->task != current)
+				continue;
+			spin_unlock_irqrestore(&gcwq->lock, flags);
+			/*
+			 * I'm @worker, no locking necessary.  See if @work
+			 * is headed to the same workqueue.
+			 */
+			return worker->current_cwq->wq == wq;
+		}
+		spin_unlock_irqrestore(&gcwq->lock, flags);
+	}
+	return false;
+}
+
 static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
 			 struct work_struct *work)
 {
@@ -943,7 +975,9 @@
 
 	debug_work_activate(work);
 
-	if (WARN_ON_ONCE(wq->flags & WQ_DYING))
+	/* if dying, only works from the same workqueue are allowed */
+	if (unlikely(wq->flags & WQ_DYING) &&
+	    WARN_ON_ONCE(!is_chained_work(wq)))
 		return;
 
 	/* determine gcwq to use */
@@ -2936,11 +2970,35 @@
  */
 void destroy_workqueue(struct workqueue_struct *wq)
 {
+	unsigned int flush_cnt = 0;
 	unsigned int cpu;
 
+	/*
+	 * Mark @wq dying and drain all pending works.  Once WQ_DYING is
+	 * set, only chain queueing is allowed.  IOW, only currently
+	 * pending or running work items on @wq can queue further work
+	 * items on it.  @wq is flushed repeatedly until it becomes empty.
+	 * The number of flushing is detemined by the depth of chaining and
+	 * should be relatively short.  Whine if it takes too long.
+	 */
 	wq->flags |= WQ_DYING;
+reflush:
 	flush_workqueue(wq);
 
+	for_each_cwq_cpu(cpu, wq) {
+		struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq);
+
+		if (!cwq->nr_active && list_empty(&cwq->delayed_works))
+			continue;
+
+		if (++flush_cnt == 10 ||
+		    (flush_cnt % 100 == 0 && flush_cnt <= 1000))
+			printk(KERN_WARNING "workqueue %s: flush on "
+			       "destruction isn't complete after %u tries\n",
+			       wq->name, flush_cnt);
+		goto reflush;
+	}
+
 	/*
 	 * wq list is used to freeze wq, remove from list after
 	 * flushing is complete in case freeze races us.
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 28b42b9..2d05adb 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -173,7 +173,8 @@
 	  An NMI is generated every 60 seconds or so to check for hardlockups.
 
 config HARDLOCKUP_DETECTOR
-	def_bool LOCKUP_DETECTOR && PERF_EVENTS && HAVE_PERF_EVENTS_NMI
+	def_bool LOCKUP_DETECTOR && PERF_EVENTS && HAVE_PERF_EVENTS_NMI && \
+		 !ARCH_HAS_NMI_WATCHDOG
 
 config BOOTPARAM_SOFTLOCKUP_PANIC
 	bool "Panic (Reboot) On Soft Lockups"
diff --git a/lib/Makefile b/lib/Makefile
index 76d3b8514..d7b6e30a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -8,7 +8,7 @@
 endif
 
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
-	 rbtree.o radix-tree.o dump_stack.o \
+	 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
 	 idr.o int_sqrt.o extable.o prio_tree.o \
 	 sha1.o irq_regs.o reciprocal_div.o argv_split.o \
 	 proportions.o prio_heap.o ratelimit.o show_mem.o \
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 604678d..28f2c33 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -72,18 +72,16 @@
 void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
 {
 	s64 count;
-	s32 *pcount;
 
 	preempt_disable();
-	pcount = this_cpu_ptr(fbc->counters);
-	count = *pcount + amount;
+	count = __this_cpu_read(*fbc->counters) + amount;
 	if (count >= batch || count <= -batch) {
 		spin_lock(&fbc->lock);
 		fbc->count += count;
-		*pcount = 0;
+		__this_cpu_write(*fbc->counters, 0);
 		spin_unlock(&fbc->lock);
 	} else {
-		*pcount = count;
+		__this_cpu_write(*fbc->counters, count);
 	}
 	preempt_enable();
 }
diff --git a/lib/timerqueue.c b/lib/timerqueue.c
new file mode 100644
index 0000000..e3a1050
--- /dev/null
+++ b/lib/timerqueue.c
@@ -0,0 +1,107 @@
+/*
+ *  Generic Timer-queue
+ *
+ *  Manages a simple queue of timers, ordered by expiration time.
+ *  Uses rbtrees for quick list adds and expiration.
+ *
+ *  NOTE: All of the following functions need to be serialized
+ *  to avoid races. No locking is done by this libary 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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/timerqueue.h>
+#include <linux/rbtree.h>
+#include <linux/module.h>
+
+/**
+ * timerqueue_add - Adds timer to timerqueue.
+ *
+ * @head: head of timerqueue
+ * @node: timer node to be added
+ *
+ * Adds the timer node to the timerqueue, sorted by the
+ * node's expires value.
+ */
+void timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node)
+{
+	struct rb_node **p = &head->head.rb_node;
+	struct rb_node *parent = NULL;
+	struct timerqueue_node  *ptr;
+
+	/* Make sure we don't add nodes that are already added */
+	WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node));
+
+	while (*p) {
+		parent = *p;
+		ptr = rb_entry(parent, struct timerqueue_node, node);
+		if (node->expires.tv64 < ptr->expires.tv64)
+			p = &(*p)->rb_left;
+		else
+			p = &(*p)->rb_right;
+	}
+	rb_link_node(&node->node, parent, p);
+	rb_insert_color(&node->node, &head->head);
+
+	if (!head->next || node->expires.tv64 < head->next->expires.tv64)
+		head->next = node;
+}
+EXPORT_SYMBOL_GPL(timerqueue_add);
+
+/**
+ * timerqueue_del - Removes a timer from the timerqueue.
+ *
+ * @head: head of timerqueue
+ * @node: timer node to be removed
+ *
+ * Removes the timer node from the timerqueue.
+ */
+void timerqueue_del(struct timerqueue_head *head, struct timerqueue_node *node)
+{
+	WARN_ON_ONCE(RB_EMPTY_NODE(&node->node));
+
+	/* update next pointer */
+	if (head->next == node) {
+		struct rb_node *rbn = rb_next(&node->node);
+
+		head->next = rbn ?
+			rb_entry(rbn, struct timerqueue_node, node) : NULL;
+	}
+	rb_erase(&node->node, &head->head);
+	RB_CLEAR_NODE(&node->node);
+}
+EXPORT_SYMBOL_GPL(timerqueue_del);
+
+/**
+ * timerqueue_iterate_next - Returns the timer after the provided timer
+ *
+ * @node: Pointer to a timer.
+ *
+ * Provides the timer that is after the given node. This is used, when
+ * necessary, to iterate through the list of timers in a timer list
+ * without modifying the list.
+ */
+struct timerqueue_node *timerqueue_iterate_next(struct timerqueue_node *node)
+{
+	struct rb_node *next;
+
+	if (!node)
+		return NULL;
+	next = rb_next(&node->node);
+	if (!next)
+		return NULL;
+	return container_of(next, struct timerqueue_node, node);
+}
+EXPORT_SYMBOL_GPL(timerqueue_iterate_next);
diff --git a/mm/filemap.c b/mm/filemap.c
index 6b9aee2..ca38939 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -102,9 +102,6 @@
  *    ->inode_lock		(zap_pte_range->set_page_dirty)
  *    ->private_lock		(zap_pte_range->__set_page_dirty_buffers)
  *
- *  ->task->proc_lock
- *    ->dcache_lock		(proc_pid_lookup)
- *
  *  (code doesn't rely on that order, so you could switch it around)
  *  ->tasklist_lock             (memory_failure, collect_procs_ao)
  *    ->i_mmap_lock
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 7a22b41..00bb8a6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1925,19 +1925,18 @@
 
 		rcu_read_lock();
 		p = rcu_dereference(mm->owner);
-		VM_BUG_ON(!p);
 		/*
-		 * because we don't have task_lock(), "p" can exit while
-		 * we're here. In that case, "mem" can point to root
-		 * cgroup but never be NULL. (and task_struct itself is freed
-		 * by RCU, cgroup itself is RCU safe.) Then, we have small
-		 * risk here to get wrong cgroup. But such kind of mis-account
-		 * by race always happens because we don't have cgroup_mutex().
-		 * It's overkill and we allow that small race, here.
+		 * Because we don't have task_lock(), "p" can exit.
+		 * In that case, "mem" can point to root or p can be NULL with
+		 * race with swapoff. Then, we have small risk of mis-accouning.
+		 * But such kind of mis-account by race always happens because
+		 * we don't have cgroup_mutex(). It's overkill and we allo that
+		 * small race, here.
+		 * (*) swapoff at el will charge against mm-struct not against
+		 * task-struct. So, mm->owner can be NULL.
 		 */
 		mem = mem_cgroup_from_task(p);
-		VM_BUG_ON(!mem);
-		if (mem_cgroup_is_root(mem)) {
+		if (!mem || mem_cgroup_is_root(mem)) {
 			rcu_read_unlock();
 			goto done;
 		}
diff --git a/mm/nommu.c b/mm/nommu.c
index 27a9ac5..ef4045d 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -10,7 +10,7 @@
  *  Copyright (c) 2000-2003 David McCullough <davidm@snapgear.com>
  *  Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org>
  *  Copyright (c) 2002      Greg Ungerer <gerg@snapgear.com>
- *  Copyright (c) 2007-2009 Paul Mundt <lethal@linux-sh.org>
+ *  Copyright (c) 2007-2010 Paul Mundt <lethal@linux-sh.org>
  */
 
 #include <linux/module.h>
@@ -328,6 +328,7 @@
 {
 	return vmalloc(size);
 }
+EXPORT_SYMBOL(vmalloc_node);
 
 /**
  * vzalloc_node - allocate memory on a specific node with zero fill
@@ -440,6 +441,31 @@
 {
 }
 
+/**
+ *	alloc_vm_area - allocate a range of kernel address space
+ *	@size:		size of the area
+ *
+ *	Returns:	NULL on failure, vm_struct on success
+ *
+ *	This function reserves a range of kernel address space, and
+ *	allocates pagetables to map that range.  No actual mappings
+ *	are created.  If the kernel address space is not shared
+ *	between processes, it syncs the pagetable across all
+ *	processes.
+ */
+struct vm_struct *alloc_vm_area(size_t size)
+{
+	BUG();
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(alloc_vm_area);
+
+void free_vm_area(struct vm_struct *area)
+{
+	BUG();
+}
+EXPORT_SYMBOL_GPL(free_vm_area);
+
 int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
 		   struct page *page)
 {
diff --git a/mm/percpu.c b/mm/percpu.c
index 02ba912..3dd4984 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -293,12 +293,8 @@
 
 	if (size <= PAGE_SIZE)
 		return kzalloc(size, GFP_KERNEL);
-	else {
-		void *ptr = vmalloc(size);
-		if (ptr)
-			memset(ptr, 0, size);
-		return ptr;
-	}
+	else
+		return vzalloc(size);
 }
 
 /**
diff --git a/mm/shmem.c b/mm/shmem.c
index 47fdeeb..5ee67c9 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2415,13 +2415,20 @@
 	return &p->vfs_inode;
 }
 
+static void shmem_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(shmem_inode_cachep, SHMEM_I(inode));
+}
+
 static void shmem_destroy_inode(struct inode *inode)
 {
 	if ((inode->i_mode & S_IFMT) == S_IFREG) {
 		/* only struct inode is valid if it's an inline symlink */
 		mpol_free_shared_policy(&SHMEM_I(inode)->policy);
 	}
-	kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
+	call_rcu(&inode->i_rcu, shmem_i_callback);
 }
 
 static void init_once(void *foo)
diff --git a/mm/slab.c b/mm/slab.c
index b1e40da..e9f9298 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -829,12 +829,12 @@
 
 static void next_reap_node(void)
 {
-	int node = __get_cpu_var(slab_reap_node);
+	int node = __this_cpu_read(slab_reap_node);
 
 	node = next_node(node, node_online_map);
 	if (unlikely(node >= MAX_NUMNODES))
 		node = first_node(node_online_map);
-	__get_cpu_var(slab_reap_node) = node;
+	__this_cpu_write(slab_reap_node, node);
 }
 
 #else
@@ -1012,7 +1012,7 @@
  */
 static void reap_alien(struct kmem_cache *cachep, struct kmem_list3 *l3)
 {
-	int node = __get_cpu_var(slab_reap_node);
+	int node = __this_cpu_read(slab_reap_node);
 
 	if (l3->alien) {
 		struct array_cache *ac = l3->alien[node];
@@ -1293,7 +1293,7 @@
 		 * anything expensive but will only modify reap_work
 		 * and reschedule the timer.
 		*/
-		cancel_rearming_delayed_work(&per_cpu(slab_reap_work, cpu));
+		cancel_delayed_work_sync(&per_cpu(slab_reap_work, cpu));
 		/* Now the cache_reaper is guaranteed to be not running. */
 		per_cpu(slab_reap_work, cpu).work.func = NULL;
   		break;
@@ -2781,7 +2781,7 @@
 /*
  * Map pages beginning at addr to the given cache and slab. This is required
  * for the slab allocator to be able to lookup the cache and slab of a
- * virtual address for kfree, ksize, kmem_ptr_validate, and slab debugging.
+ * virtual address for kfree, ksize, and slab debugging.
  */
 static void slab_map_pages(struct kmem_cache *cache, struct slab *slab,
 			   void *addr)
@@ -3660,36 +3660,6 @@
 EXPORT_SYMBOL(kmem_cache_alloc_notrace);
 #endif
 
-/**
- * kmem_ptr_validate - check if an untrusted pointer might be a slab entry.
- * @cachep: the cache we're checking against
- * @ptr: pointer to validate
- *
- * This verifies that the untrusted pointer looks sane;
- * it is _not_ a guarantee that the pointer is actually
- * part of the slab cache in question, but it at least
- * validates that the pointer can be dereferenced and
- * looks half-way sane.
- *
- * Currently only used for dentry validation.
- */
-int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr)
-{
-	unsigned long size = cachep->buffer_size;
-	struct page *page;
-
-	if (unlikely(!kern_ptr_validate(ptr, size)))
-		goto out;
-	page = virt_to_page(ptr);
-	if (unlikely(!PageSlab(page)))
-		goto out;
-	if (unlikely(page_get_cache(page) != cachep))
-		goto out;
-	return 1;
-out:
-	return 0;
-}
-
 #ifdef CONFIG_NUMA
 void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
diff --git a/mm/slob.c b/mm/slob.c
index 617b6d6..3588eaa 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -678,11 +678,6 @@
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
-int kmem_ptr_validate(struct kmem_cache *a, const void *b)
-{
-	return 0;
-}
-
 static unsigned int slob_ready __read_mostly;
 
 int slab_is_available(void)
diff --git a/mm/slub.c b/mm/slub.c
index bec0e35..a2fe172 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1917,17 +1917,6 @@
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
-/* Figure out on which slab page the object resides */
-static struct page *get_object_page(const void *x)
-{
-	struct page *page = virt_to_head_page(x);
-
-	if (!PageSlab(page))
-		return NULL;
-
-	return page;
-}
-
 /*
  * Object placement in a slab is made very easy because we always start at
  * offset 0. If we tune the size of the object to the alignment then we can
@@ -2386,35 +2375,6 @@
 }
 
 /*
- * Check if a given pointer is valid
- */
-int kmem_ptr_validate(struct kmem_cache *s, const void *object)
-{
-	struct page *page;
-
-	if (!kern_ptr_validate(object, s->size))
-		return 0;
-
-	page = get_object_page(object);
-
-	if (!page || s != page->slab)
-		/* No slab or wrong slab */
-		return 0;
-
-	if (!check_valid_pointer(s, page, object))
-		return 0;
-
-	/*
-	 * We could also check if the object is on the slabs freelist.
-	 * But this would be too expensive and it seems that the main
-	 * purpose of kmem_ptr_valid() is to check if the object belongs
-	 * to a certain slab.
-	 */
-	return 1;
-}
-EXPORT_SYMBOL(kmem_ptr_validate);
-
-/*
  * Determine the size of a slab object
  */
 unsigned int kmem_cache_size(struct kmem_cache *s)
diff --git a/mm/util.c b/mm/util.c
index 73dac81..f126975 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -186,27 +186,6 @@
 }
 EXPORT_SYMBOL(kzfree);
 
-int kern_ptr_validate(const void *ptr, unsigned long size)
-{
-	unsigned long addr = (unsigned long)ptr;
-	unsigned long min_addr = PAGE_OFFSET;
-	unsigned long align_mask = sizeof(void *) - 1;
-
-	if (unlikely(addr < min_addr))
-		goto out;
-	if (unlikely(addr > (unsigned long)high_memory - size))
-		goto out;
-	if (unlikely(addr & align_mask))
-		goto out;
-	if (unlikely(!kern_addr_valid(addr)))
-		goto out;
-	if (unlikely(!kern_addr_valid(addr + size - 1)))
-		goto out;
-	return 1;
-out:
-	return 0;
-}
-
 /*
  * strndup_user - duplicate an existing string from user space
  * @s: The string to duplicate
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 8f62f17..312d728 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -167,36 +167,24 @@
 void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
 				int delta)
 {
-	struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset);
-
-	s8 *p = pcp->vm_stat_diff + item;
+	struct per_cpu_pageset __percpu *pcp = zone->pageset;
+	s8 __percpu *p = pcp->vm_stat_diff + item;
 	long x;
+	long t;
 
-	x = delta + *p;
+	x = delta + __this_cpu_read(*p);
 
-	if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) {
+	t = __this_cpu_read(pcp->stat_threshold);
+
+	if (unlikely(x > t || x < -t)) {
 		zone_page_state_add(x, zone, item);
 		x = 0;
 	}
-	*p = x;
+	__this_cpu_write(*p, x);
 }
 EXPORT_SYMBOL(__mod_zone_page_state);
 
 /*
- * For an unknown interrupt state
- */
-void mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
-					int delta)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	__mod_zone_page_state(zone, item, delta);
-	local_irq_restore(flags);
-}
-EXPORT_SYMBOL(mod_zone_page_state);
-
-/*
  * Optimized increment and decrement functions.
  *
  * These are only for a single page and therefore can take a struct page *
@@ -221,16 +209,17 @@
  */
 void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
 {
-	struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset);
-	s8 *p = pcp->vm_stat_diff + item;
+	struct per_cpu_pageset __percpu *pcp = zone->pageset;
+	s8 __percpu *p = pcp->vm_stat_diff + item;
+	s8 v, t;
 
-	(*p)++;
+	v = __this_cpu_inc_return(*p);
+	t = __this_cpu_read(pcp->stat_threshold);
+	if (unlikely(v > t)) {
+		s8 overstep = t >> 1;
 
-	if (unlikely(*p > pcp->stat_threshold)) {
-		int overstep = pcp->stat_threshold / 2;
-
-		zone_page_state_add(*p + overstep, zone, item);
-		*p = -overstep;
+		zone_page_state_add(v + overstep, zone, item);
+		__this_cpu_write(*p, -overstep);
 	}
 }
 
@@ -242,16 +231,17 @@
 
 void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
 {
-	struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset);
-	s8 *p = pcp->vm_stat_diff + item;
+	struct per_cpu_pageset __percpu *pcp = zone->pageset;
+	s8 __percpu *p = pcp->vm_stat_diff + item;
+	s8 v, t;
 
-	(*p)--;
+	v = __this_cpu_dec_return(*p);
+	t = __this_cpu_read(pcp->stat_threshold);
+	if (unlikely(v < - t)) {
+		s8 overstep = t >> 1;
 
-	if (unlikely(*p < - pcp->stat_threshold)) {
-		int overstep = pcp->stat_threshold / 2;
-
-		zone_page_state_add(*p - overstep, zone, item);
-		*p = overstep;
+		zone_page_state_add(v - overstep, zone, item);
+		__this_cpu_write(*p, overstep);
 	}
 }
 
@@ -261,6 +251,92 @@
 }
 EXPORT_SYMBOL(__dec_zone_page_state);
 
+#ifdef CONFIG_CMPXCHG_LOCAL
+/*
+ * If we have cmpxchg_local support then we do not need to incur the overhead
+ * that comes with local_irq_save/restore if we use this_cpu_cmpxchg.
+ *
+ * mod_state() modifies the zone counter state through atomic per cpu
+ * operations.
+ *
+ * Overstep mode specifies how overstep should handled:
+ *     0       No overstepping
+ *     1       Overstepping half of threshold
+ *     -1      Overstepping minus half of threshold
+*/
+static inline void mod_state(struct zone *zone,
+       enum zone_stat_item item, int delta, int overstep_mode)
+{
+	struct per_cpu_pageset __percpu *pcp = zone->pageset;
+	s8 __percpu *p = pcp->vm_stat_diff + item;
+	long o, n, t, z;
+
+	do {
+		z = 0;  /* overflow to zone counters */
+
+		/*
+		 * The fetching of the stat_threshold is racy. We may apply
+		 * a counter threshold to the wrong the cpu if we get
+		 * rescheduled while executing here. However, the following
+		 * will apply the threshold again and therefore bring the
+		 * counter under the threshold.
+		 */
+		t = this_cpu_read(pcp->stat_threshold);
+
+		o = this_cpu_read(*p);
+		n = delta + o;
+
+		if (n > t || n < -t) {
+			int os = overstep_mode * (t >> 1) ;
+
+			/* Overflow must be added to zone counters */
+			z = n + os;
+			n = -os;
+		}
+	} while (this_cpu_cmpxchg(*p, o, n) != o);
+
+	if (z)
+		zone_page_state_add(z, zone, item);
+}
+
+void mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
+					int delta)
+{
+	mod_state(zone, item, delta, 0);
+}
+EXPORT_SYMBOL(mod_zone_page_state);
+
+void inc_zone_state(struct zone *zone, enum zone_stat_item item)
+{
+	mod_state(zone, item, 1, 1);
+}
+
+void inc_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+	mod_state(page_zone(page), item, 1, 1);
+}
+EXPORT_SYMBOL(inc_zone_page_state);
+
+void dec_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+	mod_state(page_zone(page), item, -1, -1);
+}
+EXPORT_SYMBOL(dec_zone_page_state);
+#else
+/*
+ * Use interrupt disable to serialize counter updates
+ */
+void mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
+					int delta)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	__mod_zone_page_state(zone, item, delta);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(mod_zone_page_state);
+
 void inc_zone_state(struct zone *zone, enum zone_stat_item item)
 {
 	unsigned long flags;
@@ -291,6 +367,7 @@
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL(dec_zone_page_state);
+#endif
 
 /*
  * Update the zone counters for one cpu.
@@ -1033,7 +1110,7 @@
 		break;
 	case CPU_DOWN_PREPARE:
 	case CPU_DOWN_PREPARE_FROZEN:
-		cancel_rearming_delayed_work(&per_cpu(vmstat_work, cpu));
+		cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu));
 		per_cpu(vmstat_work, cpu).work.func = NULL;
 		break;
 	case CPU_DOWN_FAILED:
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 179e04b..38754fd 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1607,7 +1607,7 @@
 	struct lec_arp_table *entry;
 	int i;
 
-	cancel_rearming_delayed_work(&priv->lec_arp_work);
+	cancel_delayed_work_sync(&priv->lec_arp_work);
 
 	/*
 	 * Remove all entries
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 72d9b50..02dc2cb 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -923,7 +923,7 @@
 
 		skb_queue_purge(&npinfo->arp_tx);
 		skb_queue_purge(&npinfo->txq);
-		cancel_rearming_delayed_work(&npinfo->tx_work);
+		cancel_delayed_work_sync(&npinfo->tx_work);
 
 		/* clean after last, unfinished work */
 		__skb_queue_purge(&npinfo->txq);
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 6112a12..0c877a7 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -390,7 +390,7 @@
 	if (dst->link_poll_needed)
 		del_timer_sync(&dst->link_poll_timer);
 
-	flush_scheduled_work();
+	flush_work_sync(&dst->link_poll_work);
 
 	for (i = 0; i < dst->pd->nr_chips; i++) {
 		struct dsa_switch *ds = dst->ds[i];
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index f7db676..1ee5dab 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -36,6 +36,7 @@
 #define KMSG_COMPONENT "iucv"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
@@ -1804,6 +1805,7 @@
 	struct iucv_irq_data *p;
 	struct iucv_irq_list *work;
 
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_IUC]++;
 	p = iucv_irq_data[smp_processor_id()];
 	if (p->ippathid >= iucv_max_pathid) {
 		WARN_ON(p->ippathid >= iucv_max_pathid);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index c6f2936..22f7ad5 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3430,7 +3430,7 @@
 {
 	EnterFunction(2);
 	ip_vs_trash_cleanup();
-	cancel_rearming_delayed_work(&defense_work);
+	cancel_delayed_work_sync(&defense_work);
 	cancel_work_sync(&defense_work.work);
 	ip_vs_kill_estimator(&ip_vs_stats);
 	unregister_sysctl_table(sysctl_header);
diff --git a/net/socket.c b/net/socket.c
index c1663c0..ccc576a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -262,6 +262,7 @@
 }
 
 
+
 static void wq_free_rcu(struct rcu_head *head)
 {
 	struct socket_wq *wq = container_of(head, struct socket_wq, rcu);
@@ -360,14 +361,14 @@
 	if (unlikely(fd < 0))
 		return fd;
 
-	path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
+	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
 	if (unlikely(!path.dentry)) {
 		put_unused_fd(fd);
 		return -ENOMEM;
 	}
 	path.mnt = mntget(sock_mnt);
 
-	path.dentry->d_op = &sockfs_dentry_operations;
+	d_set_d_op(path.dentry, &sockfs_dentry_operations);
 	d_instantiate(path.dentry, SOCK_INODE(sock));
 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
 
@@ -2390,6 +2391,8 @@
 
 static int __init sock_init(void)
 {
+	int err;
+
 	/*
 	 *      Initialize sock SLAB cache.
 	 */
@@ -2406,8 +2409,15 @@
 	 */
 
 	init_inodecache();
-	register_filesystem(&sock_fs_type);
+
+	err = register_filesystem(&sock_fs_type);
+	if (err)
+		goto out_fs;
 	sock_mnt = kern_mount(&sock_fs_type);
+	if (IS_ERR(sock_mnt)) {
+		err = PTR_ERR(sock_mnt);
+		goto out_mount;
+	}
 
 	/* The real protocol initialization is performed in later initcalls.
 	 */
@@ -2420,7 +2430,13 @@
 	skb_timestamping_init();
 #endif
 
-	return 0;
+out:
+	return err;
+
+out_mount:
+	unregister_filesystem(&sock_fs_type);
+out_fs:
+	goto out;
 }
 
 core_initcall(sock_init);	/* early initcall */
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 10a17a3..09f01f4 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -162,9 +162,17 @@
 }
 
 static void
+rpc_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(rpc_inode_cachep, RPC_I(inode));
+}
+
+static void
 rpc_destroy_inode(struct inode *inode)
 {
-	kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
+	call_rcu(&inode->i_rcu, rpc_i_callback);
 }
 
 static int
@@ -430,7 +438,7 @@
 }
 EXPORT_SYMBOL_GPL(rpc_put_mount);
 
-static int rpc_delete_dentry(struct dentry *dentry)
+static int rpc_delete_dentry(const struct dentry *dentry)
 {
 	return 1;
 }
@@ -583,7 +591,7 @@
 		}
 	}
 	if (!dentry->d_inode)
-		dentry->d_op = &rpc_dentry_operations;
+		d_set_d_op(dentry, &rpc_dentry_operations);
 out_err:
 	return dentry;
 }
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index dfcab5a..96549df 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -770,7 +770,7 @@
 
 	dprintk("RPC:       xs_destroy xprt %p\n", xprt);
 
-	cancel_rearming_delayed_work(&transport->connect_worker);
+	cancel_delayed_work_sync(&transport->connect_worker);
 
 	xs_close(xprt);
 	xs_free_peer_addresses(xprt);
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 5ad25e1..4eb99ab 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -214,17 +214,22 @@
 # The empty.o file is created in the make process in order to determine
 #  the target endianness and word size. It is made before all other C
 #  files, including recordmcount.
-cmd_record_mcount = if [ $(@) != "scripts/mod/empty.o" ]; then			\
-			$(objtree)/scripts/recordmcount "$(@)";			\
-		    fi;
+sub_cmd_record_mcount =					\
+	if [ $(@) != "scripts/mod/empty.o" ]; then	\
+		$(objtree)/scripts/recordmcount "$(@)";	\
+	fi;
 else
-cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
 	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
 	"$(if $(CONFIG_64BIT),64,32)" \
 	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
 	"$(LD)" "$(NM)" "$(RM)" "$(MV)" \
 	"$(if $(part-of-module),1,0)" "$(@)";
 endif
+cmd_record_mcount = 						\
+	if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then	\
+		$(sub_cmd_record_mcount)			\
+	fi;
 endif
 
 define rule_cc_o_c
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index b9d9aa1..5f77dcb 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -140,6 +140,20 @@
 		}
 		if (current_entry->prompt && current_entry != &rootmenu)
 			prop_warn(prop, "prompt redefined");
+
+		/* Apply all upper menus' visibilities to actual prompts. */
+		if(type == P_PROMPT) {
+			struct menu *menu = current_entry;
+
+			while ((menu = menu->parent) != NULL) {
+				if (!menu->visibility)
+					continue;
+				prop->visible.expr
+					= expr_alloc_and(prop->visible.expr,
+							 menu->visibility);
+			}
+		}
+
 		current_entry->prompt = prop;
 	}
 	prop->text = prompt;
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 39580a5..9f85012 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -155,6 +155,8 @@
 # '@parameter' - name of a parameter
 # '%CONST' - name of a constant.
 
+## init lots of data
+
 my $errors = 0;
 my $warnings = 0;
 my $anon_struct_union = 0;
@@ -218,21 +220,14 @@
 			$type_param, "\$1" );
 my $blankline_list = "";
 
-sub usage {
-    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
-    print "         [ -no-doc-sections ]\n";
-    print "         [ -function funcname [ -function funcname ...] ]\n";
-    print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
-    print "         c source file(s) > outputfile\n";
-    print "         -v : verbose output, more warnings & other info listed\n";
-    exit 1;
-}
-
 # read arguments
 if ($#ARGV == -1) {
     usage();
 }
 
+my $kernelversion;
+my $dohighlight = "";
+
 my $verbose = 0;
 my $output_mode = "man";
 my $no_doc_sections = 0;
@@ -245,7 +240,7 @@
 		'November', 'December')[(localtime)[4]] .
   " " . ((localtime)[5]+1900);
 
-# Essentially these are globals
+# Essentially these are globals.
 # They probably want to be tidied up, made more localised or something.
 # CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
 # could cause "use of undefined value" or other bugs.
@@ -353,6 +348,18 @@
     }
 }
 
+# continue execution near EOF;
+
+sub usage {
+    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
+    print "         [ -no-doc-sections ]\n";
+    print "         [ -function funcname [ -function funcname ...] ]\n";
+    print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
+    print "         c source file(s) > outputfile\n";
+    print "         -v : verbose output, more warnings & other info listed\n";
+    exit 1;
+}
+
 # get kernel version from env
 sub get_kernel_version() {
     my $version = 'unknown kernel version';
@@ -362,15 +369,6 @@
     }
     return $version;
 }
-my $kernelversion = get_kernel_version();
-
-# generate a sequence of code that will splice in highlighting information
-# using the s// operator.
-my $dohighlight = "";
-foreach my $pattern (keys %highlights) {
-#   print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
-    $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
-}
 
 ##
 # dumps section contents to arrays/hashes intended for that purpose.
@@ -1851,34 +1849,6 @@
 		       });
 }
 
-sub process_file($);
-
-# Read the file that maps relative names to absolute names for
-# separate source and object directories and for shadow trees.
-if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
-	my ($relname, $absname);
-	while(<SOURCE_MAP>) {
-		chop();
-		($relname, $absname) = (split())[0..1];
-		$relname =~ s:^/+::;
-		$source_map{$relname} = $absname;
-	}
-	close(SOURCE_MAP);
-}
-
-foreach (@ARGV) {
-    chomp;
-    process_file($_);
-}
-if ($verbose && $errors) {
-  print STDERR "$errors errors\n";
-}
-if ($verbose && $warnings) {
-  print STDERR "$warnings warnings\n";
-}
-
-exit($errors);
-
 sub reset_state {
     $function = "";
     %constants = ();
@@ -2285,3 +2255,39 @@
 	}
     }
 }
+
+
+$kernelversion = get_kernel_version();
+
+# generate a sequence of code that will splice in highlighting information
+# using the s// operator.
+foreach my $pattern (keys %highlights) {
+#   print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
+    $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
+}
+
+# Read the file that maps relative names to absolute names for
+# separate source and object directories and for shadow trees.
+if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
+	my ($relname, $absname);
+	while(<SOURCE_MAP>) {
+		chop();
+		($relname, $absname) = (split())[0..1];
+		$relname =~ s:^/+::;
+		$source_map{$relname} = $absname;
+	}
+	close(SOURCE_MAP);
+}
+
+foreach (@ARGV) {
+    chomp;
+    process_file($_);
+}
+if ($verbose && $errors) {
+  print STDERR "$errors errors\n";
+}
+if ($verbose && $warnings) {
+  print STDERR "$warnings warnings\n";
+}
+
+exit($errors);
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index f2f32ee..038b3d1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -38,6 +38,7 @@
 static char gpfx;	/* prefix for global symbol name (sometimes '_') */
 static struct stat sb;	/* Remember .st_size, etc. */
 static jmp_buf jmpenv;	/* setjmp/longjmp per-file error escape */
+static const char *altmcount;	/* alternate mcount symbol name */
 
 /* setjmp() return values */
 enum {
@@ -299,7 +300,9 @@
 		fail_file();
 	} break;
 	case EM_386:	 reltype = R_386_32;                   break;
-	case EM_ARM:	 reltype = R_ARM_ABS32;                break;
+	case EM_ARM:	 reltype = R_ARM_ABS32;
+			 altmcount = "__gnu_mcount_nc";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_MIPS:	 /* reltype: e_class    */ gpfx = '_'; break;
 	case EM_PPC:	 reltype = R_PPC_ADDR32;   gpfx = '_'; break;
@@ -357,7 +360,7 @@
 int
 main(int argc, char const *argv[])
 {
-	const char ftrace[] = "kernel/trace/ftrace.o";
+	const char ftrace[] = "/ftrace.o";
 	int ftrace_size = sizeof(ftrace) - 1;
 	int n_error = 0;  /* gcc-4.3.0 false positive complaint */
 
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 3966717..baf187b 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -275,11 +275,12 @@
 			Elf_Sym const *const symp =
 				&sym0[Elf_r_sym(relp)];
 			char const *symname = &str0[w(symp->st_name)];
+			char const *mcount = '_' == gpfx ? "_mcount" : "mcount";
 
 			if ('.' == symname[0])
 				++symname;  /* ppc64 hack */
-			if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
-					symname))
+			if (0 == strcmp(mcount, symname) ||
+			    (altmcount && 0 == strcmp(altmcount, symname)))
 				mcountsym = Elf_r_sym(relp);
 		}
 
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index aef8c0a..d661afb 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -253,6 +253,8 @@
 	result = security_filter_rule_init(entry->lsm[lsm_rule].type,
 					   Audit_equal, args,
 					   &entry->lsm[lsm_rule].rule);
+	if (!entry->lsm[lsm_rule].rule)
+		return -EINVAL;
 	return result;
 }
 
diff --git a/security/security.c b/security/security.c
index e5fb07a..739e403 100644
--- a/security/security.c
+++ b/security/security.c
@@ -513,6 +513,15 @@
 	return security_ops->inode_permission(inode, mask);
 }
 
+int security_inode_exec_permission(struct inode *inode, unsigned int flags)
+{
+	if (unlikely(IS_PRIVATE(inode)))
+		return 0;
+	if (flags)
+		return -ECHILD;
+	return security_ops->inode_permission(inode, MAY_EXEC);
+}
+
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	if (unlikely(IS_PRIVATE(dentry->d_inode)))
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 073fd5b..43deac2 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1145,24 +1145,28 @@
 {
 	struct list_head *node;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&de->d_lock);
 	node = de->d_subdirs.next;
 	while (node != &de->d_subdirs) {
 		struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+
+		spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
 		list_del_init(node);
 
 		if (d->d_inode) {
-			d = dget_locked(d);
-			spin_unlock(&dcache_lock);
+			dget_dlock(d);
+			spin_unlock(&de->d_lock);
+			spin_unlock(&d->d_lock);
 			d_delete(d);
 			simple_unlink(de->d_inode, d);
 			dput(d);
-			spin_lock(&dcache_lock);
-		}
+			spin_lock(&de->d_lock);
+		} else
+			spin_unlock(&d->d_lock);
 		node = de->d_subdirs.next;
 	}
 
-	spin_unlock(&dcache_lock);
+	spin_unlock(&de->d_lock);
 }
 
 #define BOOL_DIR_NAME "booleans"
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 1d0bf8f..d1e05b0 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include "common.h"
+#include "../../fs/internal.h"
 
 /**
  * tomoyo_encode: Convert binary string to ascii string.
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 46c0d03..fcb14a09 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -87,7 +87,7 @@
 	int             i, n;
 
 	for (i = 0; i < num_mixer_volumes; i++) {
-		if (strcmp(name, mixer_vols[i].name) == 0) {
+		if (strncmp(name, mixer_vols[i].name, 32) == 0) {
 			if (present)
 				mixer_vols[i].num = i;
 			return mixer_vols[i].levels;
@@ -99,7 +99,7 @@
 	}
 	n = num_mixer_volumes++;
 
-	strcpy(mixer_vols[n].name, name);
+	strncpy(mixer_vols[n].name, name, 32);
 
 	if (present)
 		mixer_vols[n].num = n;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index b030c8e..a1c4008 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2300,6 +2300,7 @@
 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index d63e287..6447dbb 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -40,7 +40,6 @@
 };
 
 struct max98088_priv {
-       u8 reg_cache[M98088_REG_CNT];
        enum max98088_type devtype;
        void *control_data;
        struct max98088_pdata *pdata;
@@ -1588,7 +1587,7 @@
 
 static void max98088_sync_cache(struct snd_soc_codec *codec)
 {
-       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int i;
 
        if (!codec->cache_sync)
@@ -1599,14 +1598,14 @@
        /* write back cached values if they're writeable and
         * different from the hardware default.
         */
-       for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) {
+       for (i = 1; i < codec->driver->reg_cache_size; i++) {
                if (!max98088_access[i].writable)
                        continue;
 
-               if (max98088->reg_cache[i] == max98088_reg[i])
+               if (reg_cache[i] == max98088_reg[i])
                        continue;
 
-               snd_soc_write(codec, i, max98088->reg_cache[i]);
+               snd_soc_write(codec, i, reg_cache[i]);
        }
 
        codec->cache_sync = 0;
@@ -1951,7 +1950,6 @@
        int ret = 0;
 
        codec->cache_sync = 1;
-       memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
 
        ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
        if (ret != 0) {
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 9a433a5..deca79e 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -41,7 +41,6 @@
 /* codec private data */
 struct wm8523_priv {
 	enum snd_soc_control_type control_type;
-	u16 reg_cache[WM8523_REGISTER_COUNT];
 	struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
 	unsigned int sysclk;
 	unsigned int rate_constraint_list[WM8523_NUM_RATES];
@@ -314,6 +313,7 @@
 				 enum snd_soc_bias_level level)
 {
 	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+	u16 *reg_cache = codec->reg_cache;
 	int ret, i;
 
 	switch (level) {
@@ -344,7 +344,7 @@
 			/* Sync back default/cached values */
 			for (i = WM8523_AIF_CTRL1;
 			     i < WM8523_MAX_REGISTER; i++)
-				snd_soc_write(codec, i, wm8523->reg_cache[i]);
+				snd_soc_write(codec, i, reg_cache[i]);
 
 
 			msleep(100);
@@ -414,6 +414,7 @@
 static int wm8523_probe(struct snd_soc_codec *codec)
 {
 	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+	u16 *reg_cache = codec->reg_cache;
 	int ret, i;
 
 	codec->hw_write = (hw_write_t)i2c_master_send;
@@ -470,8 +471,8 @@
 	}
 
 	/* Change some default settings - latch VU and enable ZC */
-	wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
-	wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
+	reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
+	reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
 
 	wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 90e31e9..aea60ef 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -41,7 +41,6 @@
 /* codec private data */
 struct wm8741_priv {
 	enum snd_soc_control_type control_type;
-	u16 reg_cache[WM8741_REGISTER_COUNT];
 	struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
 	unsigned int sysclk;
 	struct snd_pcm_hw_constraint_list *sysclk_constraints;
@@ -422,6 +421,7 @@
 static int wm8741_probe(struct snd_soc_codec *codec)
 {
 	struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
+	u16 *reg_cache = codec->reg_cache;
 	int ret = 0;
 
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
@@ -437,10 +437,10 @@
 	}
 
 	/* Change some default settings - latch VU */
-	wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
-	wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
-	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
-	wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
+	reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
+	reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
+	reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
+	reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
 
 	snd_soc_add_controls(codec, wm8741_snd_controls,
 			     ARRAY_SIZE(wm8741_snd_controls));
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 8f679a1..87caae5 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -65,22 +65,22 @@
  * are using 2 wire for device control, so we cache them instead.
  */
 static const u16 wm8753_reg[] = {
-	0x0008, 0x0000, 0x000a, 0x000a,
-	0x0033, 0x0000, 0x0007, 0x00ff,
-	0x00ff, 0x000f, 0x000f, 0x007b,
-	0x0000, 0x0032, 0x0000, 0x00c3,
-	0x00c3, 0x00c0, 0x0000, 0x0000,
+	0x0000, 0x0008, 0x0000, 0x000a,
+	0x000a, 0x0033, 0x0000, 0x0007,
+	0x00ff, 0x00ff, 0x000f, 0x000f,
+	0x007b, 0x0000, 0x0032, 0x0000,
+	0x00c3, 0x00c3, 0x00c0, 0x0000,
 	0x0000, 0x0000, 0x0000, 0x0000,
 	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0055,
-	0x0005, 0x0050, 0x0055, 0x0050,
-	0x0055, 0x0050, 0x0055, 0x0079,
+	0x0000, 0x0000, 0x0000, 0x0000,
+	0x0055, 0x0005, 0x0050, 0x0055,
+	0x0050, 0x0055, 0x0050, 0x0055,
 	0x0079, 0x0079, 0x0079, 0x0079,
-	0x0000, 0x0000, 0x0000, 0x0000,
-	0x0097, 0x0097, 0x0000, 0x0004,
-	0x0000, 0x0083, 0x0024, 0x01ba,
-	0x0000, 0x0083, 0x0024, 0x01ba,
-	0x0000, 0x0000, 0x0000
+	0x0079, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0097, 0x0097, 0x0000,
+	0x0004, 0x0000, 0x0083, 0x0024,
+	0x01ba, 0x0000, 0x0083, 0x0024,
+	0x01ba, 0x0000, 0x0000, 0x0000
 };
 
 /* codec private data */
@@ -88,57 +88,10 @@
 	enum snd_soc_control_type control_type;
 	unsigned int sysclk;
 	unsigned int pcmclk;
-	u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
 	int dai_func;
 };
 
-/*
- * read wm8753 register cache
- */
-static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
-	unsigned int reg)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
-		return -1;
-	return cache[reg - 1];
-}
-
-/*
- * write wm8753 register cache
- */
-static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
-	unsigned int reg, unsigned int value)
-{
-	u16 *cache = codec->reg_cache;
-	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
-		return;
-	cache[reg - 1] = value;
-}
-
-/*
- * write to the WM8753 register space
- */
-static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
-	unsigned int value)
-{
-	u8 data[2];
-
-	/* data is
-	 *   D15..D9 WM8753 register offset
-	 *   D8...D0 register data
-	 */
-	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-	data[1] = value & 0x00ff;
-
-	wm8753_write_reg_cache(codec, reg, value);
-	if (codec->hw_write(codec->control_data, data, 2) == 2)
-		return 0;
-	else
-		return -EIO;
-}
-
-#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
+#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
 
 /*
  * WM8753 Controls
@@ -218,7 +171,7 @@
 	struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+	int mode = snd_soc_read(codec, WM8753_IOCTL);
 
 	ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
 	return 0;
@@ -228,7 +181,7 @@
 	struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+	int mode = snd_soc_read(codec, WM8753_IOCTL);
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
 	if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
@@ -738,17 +691,17 @@
 	if (pll_id == WM8753_PLL1) {
 		offset = 0;
 		enable = 0x10;
-		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef;
+		reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef;
 	} else {
 		offset = 4;
 		enable = 0x8;
-		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7;
+		reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7;
 	}
 
 	if (!freq_in || !freq_out) {
 		/* disable PLL  */
-		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
-		wm8753_write(codec, WM8753_CLOCK, reg);
+		snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
+		snd_soc_write(codec, WM8753_CLOCK, reg);
 		return 0;
 	} else {
 		u16 value = 0;
@@ -759,20 +712,20 @@
 		/* set up N and K PLL divisor ratios */
 		/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
 		value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18);
-		wm8753_write(codec, WM8753_PLL1CTL2 + offset, value);
+		snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);
 
 		/* bits 8:0 = PLL_K[17:9] */
 		value = (pll_div.k & 0x03fe00) >> 9;
-		wm8753_write(codec, WM8753_PLL1CTL3 + offset, value);
+		snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);
 
 		/* bits 8:0 = PLL_K[8:0] */
 		value = pll_div.k & 0x0001ff;
-		wm8753_write(codec, WM8753_PLL1CTL4 + offset, value);
+		snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);
 
 		/* set PLL as input and enable */
-		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
+		snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
 			(pll_div.div2 << 3));
-		wm8753_write(codec, WM8753_CLOCK, reg | enable);
+		snd_soc_write(codec, WM8753_CLOCK, reg | enable);
 	}
 	return 0;
 }
@@ -879,7 +832,7 @@
 		unsigned int fmt)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
-	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec;
+	u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;
 
 	/* interface format */
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -901,7 +854,7 @@
 		return -EINVAL;
 	}
 
-	wm8753_write(codec, WM8753_PCM, voice);
+	snd_soc_write(codec, WM8753_PCM, voice);
 	return 0;
 }
 
@@ -922,8 +875,8 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
-	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
-	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
+	u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3;
+	u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;
 
 	/* bit size */
 	switch (params_format(params)) {
@@ -943,9 +896,9 @@
 	/* sample rate */
 	if (params_rate(params) * 384 == wm8753->pcmclk)
 		srate |= 0x80;
-	wm8753_write(codec, WM8753_SRATE1, srate);
+	snd_soc_write(codec, WM8753_SRATE1, srate);
 
-	wm8753_write(codec, WM8753_PCM, voice);
+	snd_soc_write(codec, WM8753_PCM, voice);
 	return 0;
 }
 
@@ -958,8 +911,8 @@
 	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 voice, ioctl;
 
-	voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f;
-	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d;
+	voice = snd_soc_read(codec, WM8753_PCM) & 0x011f;
+	ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d;
 
 	/* set master/slave audio interface */
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1013,8 +966,8 @@
 		return -EINVAL;
 	}
 
-	wm8753_write(codec, WM8753_PCM, voice);
-	wm8753_write(codec, WM8753_IOCTL, ioctl);
+	snd_soc_write(codec, WM8753_PCM, voice);
+	snd_soc_write(codec, WM8753_IOCTL, ioctl);
 	return 0;
 }
 
@@ -1026,16 +979,16 @@
 
 	switch (div_id) {
 	case WM8753_PCMDIV:
-		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f;
-		wm8753_write(codec, WM8753_CLOCK, reg | div);
+		reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f;
+		snd_soc_write(codec, WM8753_CLOCK, reg | div);
 		break;
 	case WM8753_BCLKDIV:
-		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7;
-		wm8753_write(codec, WM8753_SRATE2, reg | div);
+		reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7;
+		snd_soc_write(codec, WM8753_SRATE2, reg | div);
 		break;
 	case WM8753_VXCLKDIV:
-		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f;
-		wm8753_write(codec, WM8753_SRATE2, reg | div);
+		reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f;
+		snd_soc_write(codec, WM8753_SRATE2, reg | div);
 		break;
 	default:
 		return -EINVAL;
@@ -1050,7 +1003,7 @@
 		unsigned int fmt)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
-	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0;
+	u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;
 
 	/* interface format */
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1072,7 +1025,7 @@
 		return -EINVAL;
 	}
 
-	wm8753_write(codec, WM8753_HIFI, hifi);
+	snd_soc_write(codec, WM8753_HIFI, hifi);
 	return 0;
 }
 
@@ -1085,8 +1038,8 @@
 	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 ioctl, hifi;
 
-	hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f;
-	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae;
+	hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f;
+	ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae;
 
 	/* set master/slave audio interface */
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1140,8 +1093,8 @@
 		return -EINVAL;
 	}
 
-	wm8753_write(codec, WM8753_HIFI, hifi);
-	wm8753_write(codec, WM8753_IOCTL, ioctl);
+	snd_soc_write(codec, WM8753_HIFI, hifi);
+	snd_soc_write(codec, WM8753_IOCTL, ioctl);
 	return 0;
 }
 
@@ -1162,8 +1115,8 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
-	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
-	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
+	u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0;
+	u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;
 	int coeff;
 
 	/* is digital filter coefficient valid ? */
@@ -1172,7 +1125,7 @@
 		printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
 		return coeff;
 	}
-	wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
+	snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
 		coeff_div[coeff].usb);
 
 	/* bit size */
@@ -1190,7 +1143,7 @@
 		break;
 	}
 
-	wm8753_write(codec, WM8753_HIFI, hifi);
+	snd_soc_write(codec, WM8753_HIFI, hifi);
 	return 0;
 }
 
@@ -1201,8 +1154,8 @@
 	u16 clock;
 
 	/* set clk source as pcmclk */
-	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
-	wm8753_write(codec, WM8753_CLOCK, clock);
+	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+	snd_soc_write(codec, WM8753_CLOCK, clock);
 
 	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
 		return -EINVAL;
@@ -1224,8 +1177,8 @@
 	u16 clock;
 
 	/* set clk source as pcmclk */
-	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
-	wm8753_write(codec, WM8753_CLOCK, clock);
+	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+	snd_soc_write(codec, WM8753_CLOCK, clock);
 
 	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
 		return -EINVAL;
@@ -1239,8 +1192,8 @@
 	u16 clock;
 
 	/* set clk source as mclk */
-	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
-	wm8753_write(codec, WM8753_CLOCK, clock | 0x4);
+	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+	snd_soc_write(codec, WM8753_CLOCK, clock | 0x4);
 
 	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
 		return -EINVAL;
@@ -1252,19 +1205,19 @@
 static int wm8753_mute(struct snd_soc_dai *dai, int mute)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
+	u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7;
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
 	/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
 	 * make sure we check if they are not both active when we mute */
 	if (mute && wm8753->dai_func == 1) {
 		if (!codec->active)
-			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+			snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
 	} else {
 		if (mute)
-			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+			snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
 		else
-			wm8753_write(codec, WM8753_DAC, mute_reg);
+			snd_soc_write(codec, WM8753_DAC, mute_reg);
 	}
 
 	return 0;
@@ -1273,23 +1226,23 @@
 static int wm8753_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
+	u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		/* set vmid to 50k and unmute dac */
-		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
+		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		/* set vmid to 5k for quick power up */
-		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
+		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
 		break;
 	case SND_SOC_BIAS_STANDBY:
 		/* mute dac and set vmid to 500k, enable VREF */
-		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
+		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
 		break;
 	case SND_SOC_BIAS_OFF:
-		wm8753_write(codec, WM8753_PWR1, 0x0001);
+		snd_soc_write(codec, WM8753_PWR1, 0x0001);
 		break;
 	}
 	codec->bias_level = level;
@@ -1477,7 +1430,7 @@
 		else
 			dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
 	}
-	wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func);
+	snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func);
 }
 
 static void wm8753_work(struct work_struct *work)
@@ -1495,22 +1448,19 @@
 
 static int wm8753_resume(struct snd_soc_codec *codec)
 {
+	u16 *reg_cache = codec->reg_cache;
 	int i;
-	u8 data[2];
-	u16 *cache = codec->reg_cache;
 
 	/* Sync reg_cache with the hardware */
-	for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
-		if (i + 1 == WM8753_RESET)
+	for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
+		if (i == WM8753_RESET)
 			continue;
 
 		/* No point in writing hardware default values back */
-		if (cache[i] == wm8753_reg[i])
+		if (reg_cache[i] == wm8753_reg[i])
 			continue;
 
-		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
-		data[1] = cache[i] & 0x00ff;
-		codec->hw_write(codec->control_data, data, 2);
+		snd_soc_write(codec, i, reg_cache[i]);
 	}
 
 	wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1548,7 +1498,7 @@
 static int wm8753_probe(struct snd_soc_codec *codec)
 {
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
-	int ret = 0, reg;
+	int ret;
 
 	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
 
@@ -1573,26 +1523,16 @@
 			      msecs_to_jiffies(caps_charge));
 
 	/* set the update bits */
-	reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
-	wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
-	wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LADC);
-	wm8753_write(codec, WM8753_LADC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_RADC);
-	wm8753_write(codec, WM8753_RADC, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
-	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
-	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
-	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
-	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
-	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
-	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
-	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
+	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
+	snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
 
 	snd_soc_add_controls(codec, wm8753_snd_controls,
 			     ARRAY_SIZE(wm8753_snd_controls));
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9001cc4..1ec12ef 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -50,8 +50,6 @@
 /* codec private data */
 struct wm8904_priv {
 
-	u16 reg_cache[WM8904_MAX_REGISTER + 1];
-
 	enum wm8904_type devtype;
 	void *control_data;
 
@@ -2094,7 +2092,7 @@
 
 static void wm8904_sync_cache(struct snd_soc_codec *codec)
 {
-	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
+	u16 *reg_cache = codec->reg_cache;
 	int i;
 
 	if (!codec->cache_sync)
@@ -2105,14 +2103,14 @@
 	/* Sync back cached values if they're different from the
 	 * hardware default.
 	 */
-	for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) {
+	for (i = 1; i < codec->driver->reg_cache_size; i++) {
 		if (!wm8904_access[i].writable)
 			continue;
 
-		if (wm8904->reg_cache[i] == wm8904_reg[i])
+		if (reg_cache[i] == wm8904_reg[i])
 			continue;
 
-		snd_soc_write(codec, i, wm8904->reg_cache[i]);
+		snd_soc_write(codec, i, reg_cache[i]);
 	}
 
 	codec->cache_sync = 0;
@@ -2371,6 +2369,7 @@
 {
 	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 	struct wm8904_pdata *pdata = wm8904->pdata;
+	u16 *reg_cache = codec->reg_cache;
 	int ret, i;
 
 	codec->cache_sync = 1;
@@ -2437,19 +2436,19 @@
 	}
 
 	/* Change some default settings - latch VU and enable ZC */
-	wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
-	wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
-	wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
-	wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
-	wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
+	reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
+	reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
+	reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
+	reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
+	reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
 		WM8904_HPOUTLZC;
-	wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
+	reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
 		WM8904_HPOUTRZC;
-	wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
+	reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
 		WM8904_LINEOUTLZC;
-	wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
+	reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
 		WM8904_LINEOUTRZC;
-	wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
+	reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
 
 	/* Apply configuration from the platform data. */
 	if (wm8904->pdata) {
@@ -2457,23 +2456,23 @@
 			if (!pdata->gpio_cfg[i])
 				continue;
 
-			wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i]
+			reg_cache[WM8904_GPIO_CONTROL_1 + i]
 				= pdata->gpio_cfg[i] & 0xffff;
 		}
 
 		/* Zero is the default value for these anyway */
 		for (i = 0; i < WM8904_MIC_REGS; i++)
-			wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
+			reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
 				= pdata->mic_cfg[i];
 	}
 
 	/* Set Class W by default - this will be managed by the Class
 	 * G widget at runtime where bypass paths are available.
 	 */
-	wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
+	reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
 
 	/* Use normal bias source */
-	wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
+	reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
 
 	wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 2cb16f8..23086e2 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -768,6 +768,7 @@
 
 	i2c_set_clientdata(i2c, wm8940);
 	wm8940->control_data = i2c;
+	wm8940->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8940, &wm8940_dai, 1);
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 9cbab8e..2ac35b0 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -42,8 +42,6 @@
 struct wm8955_priv {
 	enum snd_soc_control_type control_type;
 
-	u16 reg_cache[WM8955_MAX_REGISTER + 1];
-
 	unsigned int mclk_rate;
 
 	int deemph;
@@ -768,6 +766,7 @@
 				 enum snd_soc_bias_level level)
 {
 	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+	u16 *reg_cache = codec->reg_cache;
 	int ret, i;
 
 	switch (level) {
@@ -800,14 +799,14 @@
 			/* Sync back cached values if they're
 			 * different from the hardware default.
 			 */
-			for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) {
+			for (i = 0; i < codec->driver->reg_cache_size; i++) {
 				if (i == WM8955_RESET)
 					continue;
 
-				if (wm8955->reg_cache[i] == wm8955_reg[i])
+				if (reg_cache[i] == wm8955_reg[i])
 					continue;
 
-				snd_soc_write(codec, i, wm8955->reg_cache[i]);
+				snd_soc_write(codec, i, reg_cache[i]);
 			}
 
 			/* Enable VREF and VMID */
@@ -902,6 +901,7 @@
 {
 	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 	struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
+	u16 *reg_cache = codec->reg_cache;
 	int ret, i;
 
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
@@ -934,25 +934,25 @@
 	}
 
 	/* Change some default settings - latch VU and enable ZC */
-	wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
-	wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
-	wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
-	wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
-	wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
-	wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
-	wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
+	reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
+	reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
+	reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
+	reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
+	reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
+	reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
+	reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
 
 	/* Also enable adaptive bass boost by default */
-	wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
+	reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
 
 	/* Set platform data values */
 	if (pdata) {
 		if (pdata->out2_speaker)
-			wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
+			reg_cache[WM8955_ADDITIONAL_CONTROL_2]
 				|= WM8955_ROUT2INV;
 
 		if (pdata->monoin_diff)
-			wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
+			reg_cache[WM8955_MONO_OUT_MIX_1]
 				|= WM8955_DMEN;
 	}
 
@@ -1003,6 +1003,7 @@
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8955);
+	wm8955->control_type = SND_SOC_I2C;
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm8955, &wm8955_dai, 1);
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 21986c4..ff6ff2f 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1013,6 +1013,7 @@
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm8960);
+	wm8960->control_type = SND_SOC_I2C;
 	wm8960->control_data = i2c;
 
 	ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 1304ca9..7c421cc 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -52,8 +52,6 @@
 struct wm8962_priv {
 	struct snd_soc_codec *codec;
 
-	u16 reg_cache[WM8962_MAX_REGISTER + 1];
-
 	int sysclk;
 	int sysclk_rate;
 
@@ -1991,8 +1989,7 @@
 			    struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	u16 *reg_cache = wm8962->reg_cache;
+	u16 *reg_cache = codec->reg_cache;
 	int ret;
 
 	/* Apply the update (if any) */
@@ -2020,8 +2017,7 @@
 			    struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	u16 *reg_cache = wm8962->reg_cache;
+	u16 *reg_cache = codec->reg_cache;
 	int ret;
 
 	/* Apply the update (if any) */
@@ -2329,8 +2325,7 @@
 			 struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	u16 *reg_cache = wm8962->reg_cache;
+	u16 *reg_cache = codec->reg_cache;
 	int reg;
 
 	switch (w->shift) {
@@ -2719,7 +2714,7 @@
 
 static void wm8962_sync_cache(struct snd_soc_codec *codec)
 {
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+	u16 *reg_cache = codec->reg_cache;
 	int i;
 
 	if (!codec->cache_sync)
@@ -2732,13 +2727,13 @@
 	/* Sync back cached values if they're different from the
 	 * hardware default.
 	 */
-	for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+	for (i = 1; i < codec->driver->reg_cache_size; i++) {
 		if (i == WM8962_SOFTWARE_RESET)
 			continue;
-		if (wm8962->reg_cache[i] == wm8962_reg[i])
+		if (reg_cache[i] == wm8962_reg[i])
 			continue;
 
-		snd_soc_write(codec, i, wm8962->reg_cache[i]);
+		snd_soc_write(codec, i, reg_cache[i]);
 	}
 
 	codec->cache_sync = 0;
@@ -3406,12 +3401,11 @@
 #ifdef CONFIG_PM
 static int wm8962_resume(struct snd_soc_codec *codec)
 {
-	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
 	u16 *reg_cache = codec->reg_cache;
 	int i;
 
 	/* Restore the registers */
-	for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+	for (i = 1; i < codec->driver->reg_cache_size; i++) {
 		switch (i) {
 		case WM8962_SOFTWARE_RESET:
 			continue;
@@ -3705,6 +3699,7 @@
 	struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
 	struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
 					      dev);
+	u16 *reg_cache = codec->reg_cache;
 	int i, trigger, irq_pol;
 
 	wm8962->codec = codec;
@@ -3804,7 +3799,7 @@
 
 		/* Put the speakers into mono mode? */
 		if (pdata->spk_mono)
-			wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2]
+			reg_cache[WM8962_CLASS_D_CONTROL_2]
 				|= WM8962_SPK_MONO;
 
 		/* Micbias setup, detection enable and detection
@@ -3819,16 +3814,16 @@
 	}
 
 	/* Latch volume update bits */
-	wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
-	wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
-	wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
-	wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;	
-	wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
-	wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
-	wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
-	wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
-	wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
-	wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
+	reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
+	reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
+	reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
+	reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
+	reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
+	reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
+	reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
+	reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
+	reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
+	reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
 
 	wm8962_add_widgets(codec);
 
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 63f6dbf..9f18db6 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -718,6 +718,7 @@
 	if (wm8971 == NULL)
 		return -ENOMEM;
 
+	wm8971->control_type = SND_SOC_I2C;
 	i2c_set_clientdata(i2c, wm8971);
 
 	ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index ecc7c37..a486670 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1335,6 +1335,7 @@
 		return -ENOMEM;
 
 	i2c_set_clientdata(i2c, wm9081);
+	wm9081->control_type = SND_SOC_I2C;
 	wm9081->control_data = i2c;
 
 	ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 99c046b..6e5f64f 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -141,7 +141,6 @@
 /* This struct is used to save the context */
 struct wm9090_priv {
 	struct mutex mutex;
-	u16 reg_cache[WM9090_MAX_REGISTER + 1];
 	struct wm9090_platform_data pdata;
 	void *control_data;
 };
@@ -552,6 +551,7 @@
 static int wm9090_probe(struct snd_soc_codec *codec)
 {
 	struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
+	u16 *reg_cache = codec->reg_cache;
 	int ret;
 
 	codec->control_data = wm9090->control_data;
@@ -576,22 +576,22 @@
 	/* Configure some defaults; they will be written out when we
 	 * bring the bias up.
 	 */
-	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
+	reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
 		| WM9090_IN1A_ZC;
-	wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
+	reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
 		| WM9090_IN1B_ZC;
-	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
+	reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
 		| WM9090_IN2A_ZC;
-	wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
+	reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
 		| WM9090_IN2B_ZC;
-	wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
+	reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
 		WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
-	wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
+	reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
 		WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
-	wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
+	reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
 		WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
 
-	wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
+	reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
 
 	wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index b439eee..8ad93ee 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/pxa2xx_ssp.h>
 
 #include <asm/irq.h>
 
@@ -33,7 +34,6 @@
 #include <mach/hardware.h>
 #include <mach/dma.h>
 #include <mach/audio.h>
-#include <plat/ssp.h>
 
 #include "../../arm/pxa2xx-pcm.h"
 #include "pxa-ssp.h"
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index b2c6330..6f5a4986 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -24,12 +24,47 @@
 --input=::
         Input file name. (default: perf.data)
 
+-d::
+--dsos=<dso[,dso...]>::
+        Only consider symbols in these dsos.
+-s::
+--symbol=<symbol>::
+        Symbol to annotate.
+
+-f::
+--force::
+        Don't complain, do it.
+
+-v::
+--verbose::
+        Be more verbose. (Show symbol address, etc)
+
+-D::
+--dump-raw-trace::
+        Dump raw trace in ASCII.
+
+-k::
+--vmlinux=<file>::
+        vmlinux pathname.
+
+-m::
+--modules::
+        Load module symbols. WARNING: use only with -k and LIVE kernel.
+
+-l::
+--print-line::
+        Print matching source lines (may be slow).
+
+-P::
+--full-paths::
+        Don't shorten the displayed pathnames.
+
 --stdio:: Use the stdio interface.
 
 --tui:: Use the TUI interface Use of --tui requires a tty, if one is not
 	present, as when piping to other commands, the stdio interface is
 	used. This interfaces starts by centering on the line with more
-	samples, TAB/UNTAB cycles thru the lines with more samples.
+	samples, TAB/UNTAB cycles through the lines with more samples.
 
 SEE ALSO
 --------
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
index 01b642c..5eaac6f 100644
--- a/tools/perf/Documentation/perf-buildid-list.txt
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -18,6 +18,9 @@
 
 OPTIONS
 -------
+-H::
+--with-hits::
+        Show only DSOs with hits.
 -i::
 --input=::
         Input file name. (default: perf.data)
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 20d97d8..74d7481 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -19,6 +19,18 @@
 
 OPTIONS
 -------
+-M::
+--displacement::
+        Show position displacement relative to baseline.
+
+-D::
+--dump-raw-trace::
+        Dump raw trace in ASCII.
+
+-m::
+--modules::
+        Load module symbols. WARNING: use only with -k and LIVE kernel
+
 -d::
 --dsos=::
 	Only consider symbols in these dsos. CSV that understands
@@ -42,7 +54,7 @@
 --field-separator=::
 
 	Use a special separator character and don't pad with spaces, replacing
-	all occurances of this separator in symbol names (and other output)
+	all occurrences of this separator in symbol names (and other output)
 	with a '.' character, that thus it's the only non valid separator.
 
 -v::
@@ -50,6 +62,13 @@
 	Be verbose, for instance, show the raw counts in addition to the
 	diff.
 
+-f::
+--force::
+       Don't complain, do it.
+
+--symfs=<directory>::
+        Look for files with symbols relative to this directory.
+
 SEE ALSO
 --------
 linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index d004e19..dd84cb2 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -22,7 +22,7 @@
   a performance counter profile of guest os in realtime
   of an arbitrary workload.
 
-  'perf kvm record <command>' to record the performance couinter profile
+  'perf kvm record <command>' to record the performance counter profile
   of an arbitrary workload and save it into a perf data file. If both
   --host and --guest are input, the perf data file name is perf.data.kvm.
   If there is  no --host but --guest, the file name is perf.data.guest.
@@ -40,6 +40,12 @@
 
 OPTIONS
 -------
+-i::
+--input=::
+        Input file name.
+-o::
+--output::
+        Output file name.
 --host=::
         Collect host side performance profile.
 --guest=::
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index b317102..921de25 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -24,6 +24,21 @@
 
   'perf lock report' reports statistical data.
 
+OPTIONS
+-------
+
+-i::
+--input=<file>::
+        Input file name.
+
+-v::
+--verbose::
+        Be more verbose (show symbol address, etc).
+
+-D::
+--dump-raw-trace::
+        Dump raw trace in ASCII.
+
 SEE ALSO
 --------
 linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 62de1b7..86b797a 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -115,9 +115,9 @@
 
 LINE SYNTAX
 -----------
-Line range is descripted by following syntax.
+Line range is described by following syntax.
 
- "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]"
+ "FUNC[:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]"
 
 FUNC specifies the function name of showing lines. 'RLN' is the start line
 number from function entry line, and 'RLN2' is the end line number. As same as
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index a91f9f9..52462ae 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -39,15 +39,24 @@
           be passed as follows: '\mem:addr[:[r][w][x]]'.
           If you want to profile read-write accesses in 0x1000, just set
           'mem:0x1000:rw'.
+
+--filter=<filter>::
+        Event filter.
+
 -a::
-        System-wide collection.
+--all-cpus::
+        System-wide collection from all CPUs.
 
 -l::
         Scale counter values.
 
 -p::
 --pid=::
-	Record events on existing pid.
+	Record events on existing process ID.
+
+-t::
+--tid=::
+        Record events on existing thread ID.
 
 -r::
 --realtime=::
@@ -99,6 +108,11 @@
 --data::
 	Sample addresses.
 
+-T::
+--timestamp::
+	Sample timestamps. Use it with 'perf report -D' to see the timestamps,
+	for instance.
+
 -n::
 --no-samples::
 	Don't sample.
@@ -109,8 +123,8 @@
 
 -C::
 --cpu::
-Collect samples only on the list of cpus provided. Multiple CPUs can be provided as a
-comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
+Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a
+comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
 In per-thread mode with inheritance mode on (default), samples are captured only when
 the thread executes on the designated CPUs. Default is to monitor all CPUs.
 
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 12052c9..8ba03d6 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -20,6 +20,11 @@
 -i::
 --input=::
         Input file name. (default: perf.data)
+
+-v::
+--verbose::
+        Be more verbose. (show symbol address, etc)
+
 -d::
 --dsos=::
 	Only consider symbols in these dsos. CSV that understands
@@ -27,6 +32,10 @@
 -n::
 --show-nr-samples::
 	Show the number of samples for each symbol
+
+--showcpuutilization::
+        Show sample percentage for different cpu modes.
+
 -T::
 --threads::
 	Show per-thread event counters
@@ -39,12 +48,24 @@
 	Only consider these symbols. CSV that understands
 	file://filename entries.
 
+-U::
+--hide-unresolved::
+        Only display entries resolved to a symbol.
+
 -s::
 --sort=::
 	Sort by key(s): pid, comm, dso, symbol, parent.
 
+-p::
+--parent=<regex>::
+        regex filter to identify parent, see: '--sort parent'
+
+-x::
+--exclude-other::
+        Only display entries with parent-match.
+
 -w::
---field-width=::
+--column-widths=<width[,width...]>::
 	Force each column width to the provided list, for large terminal
 	readability.
 
@@ -52,19 +73,26 @@
 --field-separator=::
 
 	Use a special separator character and don't pad with spaces, replacing
-	all occurances of this separator in symbol names (and other output)
+	all occurrences of this separator in symbol names (and other output)
 	with a '.' character, that thus it's the only non valid separator.
 
+-D::
+--dump-raw-trace::
+        Dump raw trace in ASCII.
+
 -g [type,min]::
 --call-graph::
-        Display callchains using type and min percent threshold.
+        Display call chains using type and min percent threshold.
 	type can be either:
-	- flat: single column, linear exposure of callchains.
+	- flat: single column, linear exposure of call chains.
 	- graph: use a graph tree, displaying absolute overhead rates.
 	- fractal: like graph, but displays relative rates. Each branch of
 		 the tree is considered as a new profiled object. +
 	Default: fractal,0.5.
 
+--pretty=<key>::
+        Pretty printing style.  key: normal, raw
+
 --stdio:: Use the stdio interface.
 
 --tui:: Use the TUI interface, that is integrated with annotate and allows
@@ -72,6 +100,25 @@
 	requires a tty, if one is not present, as when piping to other
 	commands, the stdio interface is used.
 
+-k::
+--vmlinux=<file>::
+        vmlinux pathname
+
+--kallsyms=<file>::
+        kallsyms pathname
+
+-m::
+--modules::
+        Load module symbols. WARNING: This should only be used with -k and
+        a LIVE kernel.
+
+-f::
+--force::
+        Don't complain, do it.
+
+--symfs=<directory>::
+        Look for files with symbols relative to this directory.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 8417644..46822d5 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -8,11 +8,11 @@
 SYNOPSIS
 --------
 [verse]
-'perf sched' {record|latency|replay|trace}
+'perf sched' {record|latency|map|replay|trace}
 
 DESCRIPTION
 -----------
-There are four variants of perf sched:
+There are five variants of perf sched:
 
   'perf sched record <command>' to record the scheduling events
   of an arbitrary workload.
@@ -30,8 +30,22 @@
   of the workload as it occurred when it was recorded - and can repeat
   it a number of times, measuring its performance.)
 
+  'perf sched map' to print a textual context-switching outline of
+  workload captured via perf sched record.  Columns stand for
+  individual CPUs, and the two-letter shortcuts stand for tasks that
+  are running on a CPU. A '*' denotes the CPU that had the event, and
+  a dot signals an idle CPU.
+
 OPTIONS
 -------
+-i::
+--input=<file>::
+        Input file name. (default: perf.data)
+
+-v::
+--verbose::
+        Be more verbose. (show symbol address, etc)
+
 -D::
 --dump-raw-trace=::
         Display verbose dump of the sched data.
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
new file mode 100644
index 0000000..5bb41e5
--- /dev/null
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -0,0 +1,217 @@
+perf-script-perl(1)
+==================
+
+NAME
+----
+perf-script-perl - Process trace data with a Perl script
+
+SYNOPSIS
+--------
+[verse]
+'perf script' [-s [Perl]:script[.pl] ]
+
+DESCRIPTION
+-----------
+
+This perf script option is used to process perf script data using perf's
+built-in Perl interpreter.  It reads and processes the input file and
+displays the results of the trace analysis implemented in the given
+Perl script, if any.
+
+STARTER SCRIPTS
+---------------
+
+You can avoid reading the rest of this document by running 'perf script
+-g perl' in the same directory as an existing perf.data trace file.
+That will generate a starter script containing a handler for each of
+the event types in the trace file; it simply prints every available
+field for each event in the trace file.
+
+You can also look at the existing scripts in
+~/libexec/perf-core/scripts/perl for typical examples showing how to
+do basic things like aggregate event data, print results, etc.  Also,
+the check-perf-script.pl script, while not interesting for its results,
+attempts to exercise all of the main scripting features.
+
+EVENT HANDLERS
+--------------
+
+When perf script is invoked using a trace script, a user-defined
+'handler function' is called for each event in the trace.  If there's
+no handler function defined for a given event type, the event is
+ignored (or passed to a 'trace_handled' function, see below) and the
+next event is processed.
+
+Most of the event's field values are passed as arguments to the
+handler function; some of the less common ones aren't - those are
+available as calls back into the perf executable (see below).
+
+As an example, the following perf record command can be used to record
+all sched_wakeup events in the system:
+
+ # perf record -a -e sched:sched_wakeup
+
+Traces meant to be processed using a script should be recorded with
+the above option: -a to enable system-wide collection.
+
+The format file for the sched_wakep event defines the following fields
+(see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format):
+
+----
+ format:
+        field:unsigned short common_type;
+        field:unsigned char common_flags;
+        field:unsigned char common_preempt_count;
+        field:int common_pid;
+        field:int common_lock_depth;
+
+        field:char comm[TASK_COMM_LEN];
+        field:pid_t pid;
+        field:int prio;
+        field:int success;
+        field:int target_cpu;
+----
+
+The handler function for this event would be defined as:
+
+----
+sub sched::sched_wakeup
+{
+   my ($event_name, $context, $common_cpu, $common_secs,
+       $common_nsecs, $common_pid, $common_comm,
+       $comm, $pid, $prio, $success, $target_cpu) = @_;
+}
+----
+
+The handler function takes the form subsystem::event_name.
+
+The $common_* arguments in the handler's argument list are the set of
+arguments passed to all event handlers; some of the fields correspond
+to the common_* fields in the format file, but some are synthesized,
+and some of the common_* fields aren't common enough to to be passed
+to every event as arguments but are available as library functions.
+
+Here's a brief description of each of the invariant event args:
+
+ $event_name 	  	    the name of the event as text
+ $context		    an opaque 'cookie' used in calls back into perf
+ $common_cpu		    the cpu the event occurred on
+ $common_secs		    the secs portion of the event timestamp
+ $common_nsecs		    the nsecs portion of the event timestamp
+ $common_pid		    the pid of the current task
+ $common_comm		    the name of the current process
+
+All of the remaining fields in the event's format file have
+counterparts as handler function arguments of the same name, as can be
+seen in the example above.
+
+The above provides the basics needed to directly access every field of
+every event in a trace, which covers 90% of what you need to know to
+write a useful trace script.  The sections below cover the rest.
+
+SCRIPT LAYOUT
+-------------
+
+Every perf script Perl script should start by setting up a Perl module
+search path and 'use'ing a few support modules (see module
+descriptions below):
+
+----
+ use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/perf-script-Util/lib";
+ use lib "./perf-script-Util/lib";
+ use Perf::Trace::Core;
+ use Perf::Trace::Context;
+ use Perf::Trace::Util;
+----
+
+The rest of the script can contain handler functions and support
+functions in any order.
+
+Aside from the event handler functions discussed above, every script
+can implement a set of optional functions:
+
+*trace_begin*, if defined, is called before any event is processed and
+gives scripts a chance to do setup tasks:
+
+----
+ sub trace_begin
+ {
+ }
+----
+
+*trace_end*, if defined, is called after all events have been
+ processed and gives scripts a chance to do end-of-script tasks, such
+ as display results:
+
+----
+sub trace_end
+{
+}
+----
+
+*trace_unhandled*, if defined, is called after for any event that
+ doesn't have a handler explicitly defined for it.  The standard set
+ of common arguments are passed into it:
+
+----
+sub trace_unhandled
+{
+    my ($event_name, $context, $common_cpu, $common_secs,
+        $common_nsecs, $common_pid, $common_comm) = @_;
+}
+----
+
+The remaining sections provide descriptions of each of the available
+built-in perf script Perl modules and their associated functions.
+
+AVAILABLE MODULES AND FUNCTIONS
+-------------------------------
+
+The following sections describe the functions and variables available
+via the various Perf::Trace::* Perl modules.  To use the functions and
+variables from the given module, add the corresponding 'use
+Perf::Trace::XXX' line to your perf script script.
+
+Perf::Trace::Core Module
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+These functions provide some essential functions to user scripts.
+
+The *flag_str* and *symbol_str* functions provide human-readable
+strings for flag and symbolic fields.  These correspond to the strings
+and values parsed from the 'print fmt' fields of the event format
+files:
+
+  flag_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the flag field $field_name of event $event_name
+  symbol_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the symbolic field $field_name of event $event_name
+
+Perf::Trace::Context Module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some of the 'common' fields in the event format file aren't all that
+common, but need to be made accessible to user scripts nonetheless.
+
+Perf::Trace::Context defines a set of functions that can be used to
+access this data in the context of the current event.  Each of these
+functions expects a $context variable, which is the same as the
+$context variable passed into every event handler as the second
+argument.
+
+ common_pc($context) - returns common_preempt count for the current event
+ common_flags($context) - returns common_flags for the current event
+ common_lock_depth($context) - returns common_lock_depth for the current event
+
+Perf::Trace::Util Module
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Various utility functions for use with perf script:
+
+  nsecs($secs, $nsecs) - returns total nsecs given secs/nsecs pair
+  nsecs_secs($nsecs) - returns whole secs portion given nsecs
+  nsecs_nsecs($nsecs) - returns nsecs remainder given nsecs
+  nsecs_str($nsecs) - returns printable string in the form secs.nsecs
+  avg($total, $n) - returns average given a sum and a total number of values
+
+SEE ALSO
+--------
+linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
new file mode 100644
index 0000000..36b3827
--- /dev/null
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -0,0 +1,623 @@
+perf-script-python(1)
+====================
+
+NAME
+----
+perf-script-python - Process trace data with a Python script
+
+SYNOPSIS
+--------
+[verse]
+'perf script' [-s [Python]:script[.py] ]
+
+DESCRIPTION
+-----------
+
+This perf script option is used to process perf script data using perf's
+built-in Python interpreter.  It reads and processes the input file and
+displays the results of the trace analysis implemented in the given
+Python script, if any.
+
+A QUICK EXAMPLE
+---------------
+
+This section shows the process, start to finish, of creating a working
+Python script that aggregates and extracts useful information from a
+raw perf script stream.  You can avoid reading the rest of this
+document if an example is enough for you; the rest of the document
+provides more details on each step and lists the library functions
+available to script writers.
+
+This example actually details the steps that were used to create the
+'syscall-counts' script you see when you list the available perf script
+scripts via 'perf script -l'.  As such, this script also shows how to
+integrate your script into the list of general-purpose 'perf script'
+scripts listed by that command.
+
+The syscall-counts script is a simple script, but demonstrates all the
+basic ideas necessary to create a useful script.  Here's an example
+of its output (syscall names are not yet supported, they will appear
+as numbers):
+
+----
+syscall events:
+
+event                                          count
+----------------------------------------  -----------
+sys_write                                     455067
+sys_getdents                                    4072
+sys_close                                       3037
+sys_swapoff                                     1769
+sys_read                                         923
+sys_sched_setparam                               826
+sys_open                                         331
+sys_newfstat                                     326
+sys_mmap                                         217
+sys_munmap                                       216
+sys_futex                                        141
+sys_select                                       102
+sys_poll                                          84
+sys_setitimer                                     12
+sys_writev                                         8
+15                                                 8
+sys_lseek                                          7
+sys_rt_sigprocmask                                 6
+sys_wait4                                          3
+sys_ioctl                                          3
+sys_set_robust_list                                1
+sys_exit                                           1
+56                                                 1
+sys_access                                         1
+----
+
+Basically our task is to keep a per-syscall tally that gets updated
+every time a system call occurs in the system.  Our script will do
+that, but first we need to record the data that will be processed by
+that script.  Theoretically, there are a couple of ways we could do
+that:
+
+- we could enable every event under the tracing/events/syscalls
+  directory, but this is over 600 syscalls, well beyond the number
+  allowable by perf.  These individual syscall events will however be
+  useful if we want to later use the guidance we get from the
+  general-purpose scripts to drill down and get more detail about
+  individual syscalls of interest.
+
+- we can enable the sys_enter and/or sys_exit syscalls found under
+  tracing/events/raw_syscalls.  These are called for all syscalls; the
+  'id' field can be used to distinguish between individual syscall
+  numbers.
+
+For this script, we only need to know that a syscall was entered; we
+don't care how it exited, so we'll use 'perf record' to record only
+the sys_enter events:
+
+----
+# perf record -a -e raw_syscalls:sys_enter
+
+^C[ perf record: Woken up 1 times to write data ]
+[ perf record: Captured and wrote 56.545 MB perf.data (~2470503 samples) ]
+----
+
+The options basically say to collect data for every syscall event
+system-wide and multiplex the per-cpu output into a single stream.
+That single stream will be recorded in a file in the current directory
+called perf.data.
+
+Once we have a perf.data file containing our data, we can use the -g
+'perf script' option to generate a Python script that will contain a
+callback handler for each event type found in the perf.data trace
+stream (for more details, see the STARTER SCRIPTS section).
+
+----
+# perf script -g python
+generated Python script: perf-script.py
+
+The output file created also in the current directory is named
+perf-script.py.  Here's the file in its entirety:
+
+# perf script event handlers, generated by perf script -g python
+# Licensed under the terms of the GNU GPL License version 2
+
+# The common_* event handler fields are the most useful fields common to
+# all events.  They don't necessarily correspond to the 'common_*' fields
+# in the format files.  Those fields not available as handler params can
+# be retrieved using Python functions of the form common_*(context).
+# See the perf-script-python Documentation for the list of available functions.
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+	'/scripts/python/perf-script-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from Core import *
+
+def trace_begin():
+	print "in trace_begin"
+
+def trace_end():
+	print "in trace_end"
+
+def raw_syscalls__sys_enter(event_name, context, common_cpu,
+	common_secs, common_nsecs, common_pid, common_comm,
+	id, args):
+		print_header(event_name, common_cpu, common_secs, common_nsecs,
+			common_pid, common_comm)
+
+		print "id=%d, args=%s\n" % \
+		(id, args),
+
+def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
+		common_pid, common_comm):
+		print_header(event_name, common_cpu, common_secs, common_nsecs,
+		common_pid, common_comm)
+
+def print_header(event_name, cpu, secs, nsecs, pid, comm):
+	print "%-20s %5u %05u.%09u %8u %-20s " % \
+	(event_name, cpu, secs, nsecs, pid, comm),
+----
+
+At the top is a comment block followed by some import statements and a
+path append which every perf script script should include.
+
+Following that are a couple generated functions, trace_begin() and
+trace_end(), which are called at the beginning and the end of the
+script respectively (for more details, see the SCRIPT_LAYOUT section
+below).
+
+Following those are the 'event handler' functions generated one for
+every event in the 'perf record' output.  The handler functions take
+the form subsystem__event_name, and contain named parameters, one for
+each field in the event; in this case, there's only one event,
+raw_syscalls__sys_enter().  (see the EVENT HANDLERS section below for
+more info on event handlers).
+
+The final couple of functions are, like the begin and end functions,
+generated for every script.  The first, trace_unhandled(), is called
+every time the script finds an event in the perf.data file that
+doesn't correspond to any event handler in the script.  This could
+mean either that the record step recorded event types that it wasn't
+really interested in, or the script was run against a trace file that
+doesn't correspond to the script.
+
+The script generated by -g option simply prints a line for each
+event found in the trace stream i.e. it basically just dumps the event
+and its parameter values to stdout.  The print_header() function is
+simply a utility function used for that purpose.  Let's rename the
+script and run it to see the default output:
+
+----
+# mv perf-script.py syscall-counts.py
+# perf script -s syscall-counts.py
+
+raw_syscalls__sys_enter     1 00840.847582083     7506 perf                  id=1, args=
+raw_syscalls__sys_enter     1 00840.847595764     7506 perf                  id=1, args=
+raw_syscalls__sys_enter     1 00840.847620860     7506 perf                  id=1, args=
+raw_syscalls__sys_enter     1 00840.847710478     6533 npviewer.bin          id=78, args=
+raw_syscalls__sys_enter     1 00840.847719204     6533 npviewer.bin          id=142, args=
+raw_syscalls__sys_enter     1 00840.847755445     6533 npviewer.bin          id=3, args=
+raw_syscalls__sys_enter     1 00840.847775601     6533 npviewer.bin          id=3, args=
+raw_syscalls__sys_enter     1 00840.847781820     6533 npviewer.bin          id=3, args=
+.
+.
+.
+----
+
+Of course, for this script, we're not interested in printing every
+trace event, but rather aggregating it in a useful way.  So we'll get
+rid of everything to do with printing as well as the trace_begin() and
+trace_unhandled() functions, which we won't be using.  That leaves us
+with this minimalistic skeleton:
+
+----
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+	'/scripts/python/perf-script-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from Core import *
+
+def trace_end():
+	print "in trace_end"
+
+def raw_syscalls__sys_enter(event_name, context, common_cpu,
+	common_secs, common_nsecs, common_pid, common_comm,
+	id, args):
+----
+
+In trace_end(), we'll simply print the results, but first we need to
+generate some results to print.  To do that we need to have our
+sys_enter() handler do the necessary tallying until all events have
+been counted.  A hash table indexed by syscall id is a good way to
+store that information; every time the sys_enter() handler is called,
+we simply increment a count associated with that hash entry indexed by
+that syscall id:
+
+----
+  syscalls = autodict()
+
+  try:
+    syscalls[id] += 1
+  except TypeError:
+    syscalls[id] = 1
+----
+
+The syscalls 'autodict' object is a special kind of Python dictionary
+(implemented in Core.py) that implements Perl's 'autovivifying' hashes
+in Python i.e. with autovivifying hashes, you can assign nested hash
+values without having to go to the trouble of creating intermediate
+levels if they don't exist e.g syscalls[comm][pid][id] = 1 will create
+the intermediate hash levels and finally assign the value 1 to the
+hash entry for 'id' (because the value being assigned isn't a hash
+object itself, the initial value is assigned in the TypeError
+exception.  Well, there may be a better way to do this in Python but
+that's what works for now).
+
+Putting that code into the raw_syscalls__sys_enter() handler, we
+effectively end up with a single-level dictionary keyed on syscall id
+and having the counts we've tallied as values.
+
+The print_syscall_totals() function iterates over the entries in the
+dictionary and displays a line for each entry containing the syscall
+name (the dictonary keys contain the syscall ids, which are passed to
+the Util function syscall_name(), which translates the raw syscall
+numbers to the corresponding syscall name strings).  The output is
+displayed after all the events in the trace have been processed, by
+calling the print_syscall_totals() function from the trace_end()
+handler called at the end of script processing.
+
+The final script producing the output shown above is shown in its
+entirety below (syscall_name() helper is not yet available, you can
+only deal with id's for now):
+
+----
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+	'/scripts/python/perf-script-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from Core import *
+from Util import *
+
+syscalls = autodict()
+
+def trace_end():
+	print_syscall_totals()
+
+def raw_syscalls__sys_enter(event_name, context, common_cpu,
+	common_secs, common_nsecs, common_pid, common_comm,
+	id, args):
+	try:
+		syscalls[id] += 1
+	except TypeError:
+		syscalls[id] = 1
+
+def print_syscall_totals():
+    if for_comm is not None:
+	    print "\nsyscall events for %s:\n\n" % (for_comm),
+    else:
+	    print "\nsyscall events:\n\n",
+
+    print "%-40s  %10s\n" % ("event", "count"),
+    print "%-40s  %10s\n" % ("----------------------------------------", \
+                                 "-----------"),
+
+    for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \
+				  reverse = True):
+	    print "%-40s  %10d\n" % (syscall_name(id), val),
+----
+
+The script can be run just as before:
+
+  # perf script -s syscall-counts.py
+
+So those are the essential steps in writing and running a script.  The
+process can be generalized to any tracepoint or set of tracepoints
+you're interested in - basically find the tracepoint(s) you're
+interested in by looking at the list of available events shown by
+'perf list' and/or look in /sys/kernel/debug/tracing events for
+detailed event and field info, record the corresponding trace data
+using 'perf record', passing it the list of interesting events,
+generate a skeleton script using 'perf script -g python' and modify the
+code to aggregate and display it for your particular needs.
+
+After you've done that you may end up with a general-purpose script
+that you want to keep around and have available for future use.  By
+writing a couple of very simple shell scripts and putting them in the
+right place, you can have your script listed alongside the other
+scripts listed by the 'perf script -l' command e.g.:
+
+----
+root@tropicana:~# perf script -l
+List of available trace scripts:
+  workqueue-stats                      workqueue stats (ins/exe/create/destroy)
+  wakeup-latency                       system-wide min/max/avg wakeup latency
+  rw-by-file <comm>                    r/w activity for a program, by file
+  rw-by-pid                            system-wide r/w activity
+----
+
+A nice side effect of doing this is that you also then capture the
+probably lengthy 'perf record' command needed to record the events for
+the script.
+
+To have the script appear as a 'built-in' script, you write two simple
+scripts, one for recording and one for 'reporting'.
+
+The 'record' script is a shell script with the same base name as your
+script, but with -record appended.  The shell script should be put
+into the perf/scripts/python/bin directory in the kernel source tree.
+In that script, you write the 'perf record' command-line needed for
+your script:
+
+----
+# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-record
+
+#!/bin/bash
+perf record -a -e raw_syscalls:sys_enter
+----
+
+The 'report' script is also a shell script with the same base name as
+your script, but with -report appended.  It should also be located in
+the perf/scripts/python/bin directory.  In that script, you write the
+'perf script -s' command-line needed for running your script:
+
+----
+# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report
+
+#!/bin/bash
+# description: system-wide syscall counts
+perf script -s ~/libexec/perf-core/scripts/python/syscall-counts.py
+----
+
+Note that the location of the Python script given in the shell script
+is in the libexec/perf-core/scripts/python directory - this is where
+the script will be copied by 'make install' when you install perf.
+For the installation to install your script there, your script needs
+to be located in the perf/scripts/python directory in the kernel
+source tree:
+
+----
+# ls -al kernel-source/tools/perf/scripts/python
+
+root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python
+total 32
+drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
+drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
+drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin
+-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-script.py
+drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 perf-script-Util
+-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py
+----
+
+Once you've done that (don't forget to do a new 'make install',
+otherwise your script won't show up at run-time), 'perf script -l'
+should show a new entry for your script:
+
+----
+root@tropicana:~# perf script -l
+List of available trace scripts:
+  workqueue-stats                      workqueue stats (ins/exe/create/destroy)
+  wakeup-latency                       system-wide min/max/avg wakeup latency
+  rw-by-file <comm>                    r/w activity for a program, by file
+  rw-by-pid                            system-wide r/w activity
+  syscall-counts                       system-wide syscall counts
+----
+
+You can now perform the record step via 'perf script record':
+
+  # perf script record syscall-counts
+
+and display the output using 'perf script report':
+
+  # perf script report syscall-counts
+
+STARTER SCRIPTS
+---------------
+
+You can quickly get started writing a script for a particular set of
+trace data by generating a skeleton script using 'perf script -g
+python' in the same directory as an existing perf.data trace file.
+That will generate a starter script containing a handler for each of
+the event types in the trace file; it simply prints every available
+field for each event in the trace file.
+
+You can also look at the existing scripts in
+~/libexec/perf-core/scripts/python for typical examples showing how to
+do basic things like aggregate event data, print results, etc.  Also,
+the check-perf-script.py script, while not interesting for its results,
+attempts to exercise all of the main scripting features.
+
+EVENT HANDLERS
+--------------
+
+When perf script is invoked using a trace script, a user-defined
+'handler function' is called for each event in the trace.  If there's
+no handler function defined for a given event type, the event is
+ignored (or passed to a 'trace_handled' function, see below) and the
+next event is processed.
+
+Most of the event's field values are passed as arguments to the
+handler function; some of the less common ones aren't - those are
+available as calls back into the perf executable (see below).
+
+As an example, the following perf record command can be used to record
+all sched_wakeup events in the system:
+
+ # perf record -a -e sched:sched_wakeup
+
+Traces meant to be processed using a script should be recorded with
+the above option: -a to enable system-wide collection.
+
+The format file for the sched_wakep event defines the following fields
+(see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format):
+
+----
+ format:
+        field:unsigned short common_type;
+        field:unsigned char common_flags;
+        field:unsigned char common_preempt_count;
+        field:int common_pid;
+        field:int common_lock_depth;
+
+        field:char comm[TASK_COMM_LEN];
+        field:pid_t pid;
+        field:int prio;
+        field:int success;
+        field:int target_cpu;
+----
+
+The handler function for this event would be defined as:
+
+----
+def sched__sched_wakeup(event_name, context, common_cpu, common_secs,
+       common_nsecs, common_pid, common_comm,
+       comm, pid, prio, success, target_cpu):
+       pass
+----
+
+The handler function takes the form subsystem__event_name.
+
+The common_* arguments in the handler's argument list are the set of
+arguments passed to all event handlers; some of the fields correspond
+to the common_* fields in the format file, but some are synthesized,
+and some of the common_* fields aren't common enough to to be passed
+to every event as arguments but are available as library functions.
+
+Here's a brief description of each of the invariant event args:
+
+ event_name 	  	    the name of the event as text
+ context		    an opaque 'cookie' used in calls back into perf
+ common_cpu		    the cpu the event occurred on
+ common_secs		    the secs portion of the event timestamp
+ common_nsecs		    the nsecs portion of the event timestamp
+ common_pid		    the pid of the current task
+ common_comm		    the name of the current process
+
+All of the remaining fields in the event's format file have
+counterparts as handler function arguments of the same name, as can be
+seen in the example above.
+
+The above provides the basics needed to directly access every field of
+every event in a trace, which covers 90% of what you need to know to
+write a useful trace script.  The sections below cover the rest.
+
+SCRIPT LAYOUT
+-------------
+
+Every perf script Python script should start by setting up a Python
+module search path and 'import'ing a few support modules (see module
+descriptions below):
+
+----
+ import os
+ import sys
+
+ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+	      '/scripts/python/perf-script-Util/lib/Perf/Trace')
+
+ from perf_trace_context import *
+ from Core import *
+----
+
+The rest of the script can contain handler functions and support
+functions in any order.
+
+Aside from the event handler functions discussed above, every script
+can implement a set of optional functions:
+
+*trace_begin*, if defined, is called before any event is processed and
+gives scripts a chance to do setup tasks:
+
+----
+def trace_begin:
+    pass
+----
+
+*trace_end*, if defined, is called after all events have been
+ processed and gives scripts a chance to do end-of-script tasks, such
+ as display results:
+
+----
+def trace_end:
+    pass
+----
+
+*trace_unhandled*, if defined, is called after for any event that
+ doesn't have a handler explicitly defined for it.  The standard set
+ of common arguments are passed into it:
+
+----
+def trace_unhandled(event_name, context, common_cpu, common_secs,
+        common_nsecs, common_pid, common_comm):
+    pass
+----
+
+The remaining sections provide descriptions of each of the available
+built-in perf script Python modules and their associated functions.
+
+AVAILABLE MODULES AND FUNCTIONS
+-------------------------------
+
+The following sections describe the functions and variables available
+via the various perf script Python modules.  To use the functions and
+variables from the given module, add the corresponding 'from XXXX
+import' line to your perf script script.
+
+Core.py Module
+~~~~~~~~~~~~~~
+
+These functions provide some essential functions to user scripts.
+
+The *flag_str* and *symbol_str* functions provide human-readable
+strings for flag and symbolic fields.  These correspond to the strings
+and values parsed from the 'print fmt' fields of the event format
+files:
+
+  flag_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the flag field field_name of event event_name
+  symbol_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the symbolic field field_name of event event_name
+
+The *autodict* function returns a special kind of Python
+dictionary that implements Perl's 'autovivifying' hashes in Python
+i.e. with autovivifying hashes, you can assign nested hash values
+without having to go to the trouble of creating intermediate levels if
+they don't exist.
+
+  autodict() - returns an autovivifying dictionary instance
+
+
+perf_trace_context Module
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some of the 'common' fields in the event format file aren't all that
+common, but need to be made accessible to user scripts nonetheless.
+
+perf_trace_context defines a set of functions that can be used to
+access this data in the context of the current event.  Each of these
+functions expects a context variable, which is the same as the
+context variable passed into every event handler as the second
+argument.
+
+ common_pc(context) - returns common_preempt count for the current event
+ common_flags(context) - returns common_flags for the current event
+ common_lock_depth(context) - returns common_lock_depth for the current event
+
+Util.py Module
+~~~~~~~~~~~~~~
+
+Various utility functions for use with perf script:
+
+  nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair
+  nsecs_secs(nsecs) - returns whole secs portion given nsecs
+  nsecs_nsecs(nsecs) - returns nsecs remainder given nsecs
+  nsecs_str(nsecs) - returns printable string in the form secs.nsecs
+  avg(total, n) - returns average given a sum and a total number of values
+
+SEE ALSO
+--------
+linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
new file mode 100644
index 0000000..29ad942
--- /dev/null
+++ b/tools/perf/Documentation/perf-script.txt
@@ -0,0 +1,118 @@
+perf-script(1)
+=============
+
+NAME
+----
+perf-script - Read perf.data (created by perf record) and display trace output
+
+SYNOPSIS
+--------
+[verse]
+'perf script' [<options>]
+'perf script' [<options>] record <script> [<record-options>] <command>
+'perf script' [<options>] report <script> [script-args]
+'perf script' [<options>] <script> <required-script-args> [<record-options>] <command>
+'perf script' [<options>] <top-script> [script-args]
+
+DESCRIPTION
+-----------
+This command reads the input file and displays the trace recorded.
+
+There are several variants of perf script:
+
+  'perf script' to see a detailed trace of the workload that was
+  recorded.
+
+  You can also run a set of pre-canned scripts that aggregate and
+  summarize the raw trace data in various ways (the list of scripts is
+  available via 'perf script -l').  The following variants allow you to
+  record and run those scripts:
+
+  'perf script record <script> <command>' to record the events required
+  for 'perf script report'.  <script> is the name displayed in the
+  output of 'perf script --list' i.e. the actual script name minus any
+  language extension.  If <command> is not specified, the events are
+  recorded using the -a (system-wide) 'perf record' option.
+
+  'perf script report <script> [args]' to run and display the results
+  of <script>.  <script> is the name displayed in the output of 'perf
+  trace --list' i.e. the actual script name minus any language
+  extension.  The perf.data output from a previous run of 'perf script
+  record <script>' is used and should be present for this command to
+  succeed.  [args] refers to the (mainly optional) args expected by
+  the script.
+
+  'perf script <script> <required-script-args> <command>' to both
+  record the events required for <script> and to run the <script>
+  using 'live-mode' i.e. without writing anything to disk.  <script>
+  is the name displayed in the output of 'perf script --list' i.e. the
+  actual script name minus any language extension.  If <command> is
+  not specified, the events are recorded using the -a (system-wide)
+  'perf record' option.  If <script> has any required args, they
+  should be specified before <command>.  This mode doesn't allow for
+  optional script args to be specified; if optional script args are
+  desired, they can be specified using separate 'perf script record'
+  and 'perf script report' commands, with the stdout of the record step
+  piped to the stdin of the report script, using the '-o -' and '-i -'
+  options of the corresponding commands.
+
+  'perf script <top-script>' to both record the events required for
+  <top-script> and to run the <top-script> using 'live-mode'
+  i.e. without writing anything to disk.  <top-script> is the name
+  displayed in the output of 'perf script --list' i.e. the actual
+  script name minus any language extension; a <top-script> is defined
+  as any script name ending with the string 'top'.
+
+  [<record-options>] can be passed to the record steps of 'perf script
+  record' and 'live-mode' variants; this isn't possible however for
+  <top-script> 'live-mode' or 'perf script report' variants.
+
+  See the 'SEE ALSO' section for links to language-specific
+  information on how to write and run your own trace scripts.
+
+OPTIONS
+-------
+<command>...::
+	Any command you can specify in a shell.
+
+-D::
+--dump-raw-script=::
+        Display verbose dump of the trace data.
+
+-L::
+--Latency=::
+        Show latency attributes (irqs/preemption disabled, etc).
+
+-l::
+--list=::
+        Display a list of available trace scripts.
+
+-s ['lang']::
+--script=::
+        Process trace data with the given script ([lang]:script[.ext]).
+	If the string 'lang' is specified in place of a script name, a
+        list of supported languages will be displayed instead.
+
+-g::
+--gen-script=::
+        Generate perf-script.[ext] starter script for given language,
+        using current perf.data.
+
+-a::
+        Force system-wide collection.  Scripts run without a <command>
+        normally use -a by default, while scripts run with a <command>
+        normally don't - this option allows the latter to be run in
+        system-wide mode.
+
+-i::
+--input=::
+        Input file name.
+
+-d::
+--debug-mode::
+        Do various checks like samples ordering and lost events.
+
+SEE ALSO
+--------
+linkperf:perf-record[1], linkperf:perf-script-perl[1],
+linkperf:perf-script-python[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 4b3a2d4..b6da7af 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -8,8 +8,8 @@
 SYNOPSIS
 --------
 [verse]
-'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] <command>
-'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] -- <command> [<options>]
+'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
+'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
 
 DESCRIPTION
 -----------
@@ -35,24 +35,54 @@
         child tasks do not inherit counters
 -p::
 --pid=<pid>::
-        stat events on existing pid
+        stat events on existing process id
+
+-t::
+--tid=<tid>::
+        stat events on existing thread id
+
 
 -a::
-        system-wide collection
+--all-cpus::
+        system-wide collection from all CPUs
 
 -c::
-        scale counter values
+--scale::
+	scale/normalize counter values
+
+-r::
+--repeat=<n>::
+	repeat command and print average + stddev (max: 100)
 
 -B::
+--big-num::
         print large numbers with thousands' separators according to locale
 
 -C::
 --cpu=::
-Count only on the list of cpus provided. Multiple CPUs can be provided as a
-comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
+Count only on the list of CPUs provided. Multiple CPUs can be provided as a
+comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
 In per-thread mode, this option is ignored. The -a option is still necessary
 to activate system-wide monitoring. Default is to count on all CPUs.
 
+-A::
+--no-aggr::
+Do not aggregate counts across all monitored CPUs in system-wide mode (-a).
+This option is only valid in system-wide mode.
+
+-n::
+--null::
+        null run - don't start any counters
+
+-v::
+--verbose::
+        be more verbose (show counter open errors, etc)
+
+-x SEP::
+--field-separator SEP::
+print counts using a CSV-style output to make it easy to import directly into
+spreadsheets. Columns are separated by the string specified in SEP.
+
 EXAMPLES
 --------
 
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index 1c4b5f5..2c3b462 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -12,7 +12,7 @@
 
 DESCRIPTION
 -----------
-This command does assorted sanity tests, initially thru linked routines but
+This command does assorted sanity tests, initially through linked routines but
 also will look for a directory with more tests in the form of scripts.
 
 OPTIONS
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 4b17883..d7b79e2 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -38,6 +38,8 @@
 --process::
         Select the processes to display, by name or PID
 
+--symfs=<directory>::
+        Look for files with symbols relative to this directory.
 
 SEE ALSO
 --------
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 1f96876..f6eb1cd 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -12,7 +12,7 @@
 
 DESCRIPTION
 -----------
-This command generates and displays a performance counter profile in realtime.
+This command generates and displays a performance counter profile in real time.
 
 
 OPTIONS
@@ -27,8 +27,8 @@
 
 -C <cpu-list>::
 --cpu=<cpu>::
-Monitor only on the list of cpus provided. Multiple CPUs can be provided as a
-comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
+Monitor only on the list of CPUs provided. Multiple CPUs can be provided as a
+comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
 Default is to monitor all CPUS.
 
 -d <seconds>::
@@ -50,6 +50,10 @@
 --count-filter=<count>::
 	Only display functions with more events than this.
 
+-g::
+--group::
+        Put the counters into a counter group.
+
 -F <freq>::
 --freq=<freq>::
 	Profile at this frequency.
@@ -68,7 +72,11 @@
 
 -p <pid>::
 --pid=<pid>::
-	Profile events on existing pid.
+	Profile events on existing Process ID.
+
+-t <tid>::
+--tid=<tid>::
+        Profile events on existing thread ID.
 
 -r <priority>::
 --realtime=<priority>::
@@ -78,6 +86,18 @@
 --sym-annotate=<symbol>::
         Annotate this symbol.
 
+-K::
+--hide_kernel_symbols::
+        Hide kernel symbols.
+
+-U::
+--hide_user_symbols::
+        Hide user symbols.
+
+-D::
+--dump-symtab::
+        Dump the symbol table used for profiling.
+
 -v::
 --verbose::
 	Be more verbose (show counter open errors, etc).
diff --git a/tools/perf/Documentation/perf-trace-perl.txt b/tools/perf/Documentation/perf-trace-perl.txt
deleted file mode 100644
index ee6525e..0000000
--- a/tools/perf/Documentation/perf-trace-perl.txt
+++ /dev/null
@@ -1,217 +0,0 @@
-perf-trace-perl(1)
-==================
-
-NAME
-----
-perf-trace-perl - Process trace data with a Perl script
-
-SYNOPSIS
---------
-[verse]
-'perf trace' [-s [Perl]:script[.pl] ]
-
-DESCRIPTION
------------
-
-This perf trace option is used to process perf trace data using perf's
-built-in Perl interpreter.  It reads and processes the input file and
-displays the results of the trace analysis implemented in the given
-Perl script, if any.
-
-STARTER SCRIPTS
----------------
-
-You can avoid reading the rest of this document by running 'perf trace
--g perl' in the same directory as an existing perf.data trace file.
-That will generate a starter script containing a handler for each of
-the event types in the trace file; it simply prints every available
-field for each event in the trace file.
-
-You can also look at the existing scripts in
-~/libexec/perf-core/scripts/perl for typical examples showing how to
-do basic things like aggregate event data, print results, etc.  Also,
-the check-perf-trace.pl script, while not interesting for its results,
-attempts to exercise all of the main scripting features.
-
-EVENT HANDLERS
---------------
-
-When perf trace is invoked using a trace script, a user-defined
-'handler function' is called for each event in the trace.  If there's
-no handler function defined for a given event type, the event is
-ignored (or passed to a 'trace_handled' function, see below) and the
-next event is processed.
-
-Most of the event's field values are passed as arguments to the
-handler function; some of the less common ones aren't - those are
-available as calls back into the perf executable (see below).
-
-As an example, the following perf record command can be used to record
-all sched_wakeup events in the system:
-
- # perf record -a -e sched:sched_wakeup
-
-Traces meant to be processed using a script should be recorded with
-the above option: -a to enable system-wide collection.
-
-The format file for the sched_wakep event defines the following fields
-(see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format):
-
-----
- format:
-        field:unsigned short common_type;
-        field:unsigned char common_flags;
-        field:unsigned char common_preempt_count;
-        field:int common_pid;
-        field:int common_lock_depth;
-
-        field:char comm[TASK_COMM_LEN];
-        field:pid_t pid;
-        field:int prio;
-        field:int success;
-        field:int target_cpu;
-----
-
-The handler function for this event would be defined as:
-
-----
-sub sched::sched_wakeup
-{
-   my ($event_name, $context, $common_cpu, $common_secs,
-       $common_nsecs, $common_pid, $common_comm,
-       $comm, $pid, $prio, $success, $target_cpu) = @_;
-}
-----
-
-The handler function takes the form subsystem::event_name.
-
-The $common_* arguments in the handler's argument list are the set of
-arguments passed to all event handlers; some of the fields correspond
-to the common_* fields in the format file, but some are synthesized,
-and some of the common_* fields aren't common enough to to be passed
-to every event as arguments but are available as library functions.
-
-Here's a brief description of each of the invariant event args:
-
- $event_name 	  	    the name of the event as text
- $context		    an opaque 'cookie' used in calls back into perf
- $common_cpu		    the cpu the event occurred on
- $common_secs		    the secs portion of the event timestamp
- $common_nsecs		    the nsecs portion of the event timestamp
- $common_pid		    the pid of the current task
- $common_comm		    the name of the current process
-
-All of the remaining fields in the event's format file have
-counterparts as handler function arguments of the same name, as can be
-seen in the example above.
-
-The above provides the basics needed to directly access every field of
-every event in a trace, which covers 90% of what you need to know to
-write a useful trace script.  The sections below cover the rest.
-
-SCRIPT LAYOUT
--------------
-
-Every perf trace Perl script should start by setting up a Perl module
-search path and 'use'ing a few support modules (see module
-descriptions below):
-
-----
- use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
- use lib "./Perf-Trace-Util/lib";
- use Perf::Trace::Core;
- use Perf::Trace::Context;
- use Perf::Trace::Util;
-----
-
-The rest of the script can contain handler functions and support
-functions in any order.
-
-Aside from the event handler functions discussed above, every script
-can implement a set of optional functions:
-
-*trace_begin*, if defined, is called before any event is processed and
-gives scripts a chance to do setup tasks:
-
-----
- sub trace_begin
- {
- }
-----
-
-*trace_end*, if defined, is called after all events have been
- processed and gives scripts a chance to do end-of-script tasks, such
- as display results:
-
-----
-sub trace_end
-{
-}
-----
-
-*trace_unhandled*, if defined, is called after for any event that
- doesn't have a handler explicitly defined for it.  The standard set
- of common arguments are passed into it:
-
-----
-sub trace_unhandled
-{
-    my ($event_name, $context, $common_cpu, $common_secs,
-        $common_nsecs, $common_pid, $common_comm) = @_;
-}
-----
-
-The remaining sections provide descriptions of each of the available
-built-in perf trace Perl modules and their associated functions.
-
-AVAILABLE MODULES AND FUNCTIONS
--------------------------------
-
-The following sections describe the functions and variables available
-via the various Perf::Trace::* Perl modules.  To use the functions and
-variables from the given module, add the corresponding 'use
-Perf::Trace::XXX' line to your perf trace script.
-
-Perf::Trace::Core Module
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-These functions provide some essential functions to user scripts.
-
-The *flag_str* and *symbol_str* functions provide human-readable
-strings for flag and symbolic fields.  These correspond to the strings
-and values parsed from the 'print fmt' fields of the event format
-files:
-
-  flag_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the flag field $field_name of event $event_name
-  symbol_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the symbolic field $field_name of event $event_name
-
-Perf::Trace::Context Module
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Some of the 'common' fields in the event format file aren't all that
-common, but need to be made accessible to user scripts nonetheless.
-
-Perf::Trace::Context defines a set of functions that can be used to
-access this data in the context of the current event.  Each of these
-functions expects a $context variable, which is the same as the
-$context variable passed into every event handler as the second
-argument.
-
- common_pc($context) - returns common_preempt count for the current event
- common_flags($context) - returns common_flags for the current event
- common_lock_depth($context) - returns common_lock_depth for the current event
-
-Perf::Trace::Util Module
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Various utility functions for use with perf trace:
-
-  nsecs($secs, $nsecs) - returns total nsecs given secs/nsecs pair
-  nsecs_secs($nsecs) - returns whole secs portion given nsecs
-  nsecs_nsecs($nsecs) - returns nsecs remainder given nsecs
-  nsecs_str($nsecs) - returns printable string in the form secs.nsecs
-  avg($total, $n) - returns average given a sum and a total number of values
-
-SEE ALSO
---------
-linkperf:perf-trace[1]
diff --git a/tools/perf/Documentation/perf-trace-python.txt b/tools/perf/Documentation/perf-trace-python.txt
deleted file mode 100644
index 693be80..0000000
--- a/tools/perf/Documentation/perf-trace-python.txt
+++ /dev/null
@@ -1,623 +0,0 @@
-perf-trace-python(1)
-====================
-
-NAME
-----
-perf-trace-python - Process trace data with a Python script
-
-SYNOPSIS
---------
-[verse]
-'perf trace' [-s [Python]:script[.py] ]
-
-DESCRIPTION
------------
-
-This perf trace option is used to process perf trace data using perf's
-built-in Python interpreter.  It reads and processes the input file and
-displays the results of the trace analysis implemented in the given
-Python script, if any.
-
-A QUICK EXAMPLE
----------------
-
-This section shows the process, start to finish, of creating a working
-Python script that aggregates and extracts useful information from a
-raw perf trace stream.  You can avoid reading the rest of this
-document if an example is enough for you; the rest of the document
-provides more details on each step and lists the library functions
-available to script writers.
-
-This example actually details the steps that were used to create the
-'syscall-counts' script you see when you list the available perf trace
-scripts via 'perf trace -l'.  As such, this script also shows how to
-integrate your script into the list of general-purpose 'perf trace'
-scripts listed by that command.
-
-The syscall-counts script is a simple script, but demonstrates all the
-basic ideas necessary to create a useful script.  Here's an example
-of its output (syscall names are not yet supported, they will appear
-as numbers):
-
-----
-syscall events:
-
-event                                          count
-----------------------------------------  -----------
-sys_write                                     455067
-sys_getdents                                    4072
-sys_close                                       3037
-sys_swapoff                                     1769
-sys_read                                         923
-sys_sched_setparam                               826
-sys_open                                         331
-sys_newfstat                                     326
-sys_mmap                                         217
-sys_munmap                                       216
-sys_futex                                        141
-sys_select                                       102
-sys_poll                                          84
-sys_setitimer                                     12
-sys_writev                                         8
-15                                                 8
-sys_lseek                                          7
-sys_rt_sigprocmask                                 6
-sys_wait4                                          3
-sys_ioctl                                          3
-sys_set_robust_list                                1
-sys_exit                                           1
-56                                                 1
-sys_access                                         1
-----
-
-Basically our task is to keep a per-syscall tally that gets updated
-every time a system call occurs in the system.  Our script will do
-that, but first we need to record the data that will be processed by
-that script.  Theoretically, there are a couple of ways we could do
-that:
-
-- we could enable every event under the tracing/events/syscalls
-  directory, but this is over 600 syscalls, well beyond the number
-  allowable by perf.  These individual syscall events will however be
-  useful if we want to later use the guidance we get from the
-  general-purpose scripts to drill down and get more detail about
-  individual syscalls of interest.
-
-- we can enable the sys_enter and/or sys_exit syscalls found under
-  tracing/events/raw_syscalls.  These are called for all syscalls; the
-  'id' field can be used to distinguish between individual syscall
-  numbers.
-
-For this script, we only need to know that a syscall was entered; we
-don't care how it exited, so we'll use 'perf record' to record only
-the sys_enter events:
-
-----
-# perf record -a -e raw_syscalls:sys_enter
-
-^C[ perf record: Woken up 1 times to write data ]
-[ perf record: Captured and wrote 56.545 MB perf.data (~2470503 samples) ]
-----
-
-The options basically say to collect data for every syscall event
-system-wide and multiplex the per-cpu output into a single stream.
-That single stream will be recorded in a file in the current directory
-called perf.data.
-
-Once we have a perf.data file containing our data, we can use the -g
-'perf trace' option to generate a Python script that will contain a
-callback handler for each event type found in the perf.data trace
-stream (for more details, see the STARTER SCRIPTS section).
-
-----
-# perf trace -g python
-generated Python script: perf-trace.py
-
-The output file created also in the current directory is named
-perf-trace.py.  Here's the file in its entirety:
-
-# perf trace event handlers, generated by perf trace -g python
-# Licensed under the terms of the GNU GPL License version 2
-
-# The common_* event handler fields are the most useful fields common to
-# all events.  They don't necessarily correspond to the 'common_*' fields
-# in the format files.  Those fields not available as handler params can
-# be retrieved using Python functions of the form common_*(context).
-# See the perf-trace-python Documentation for the list of available functions.
-
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
-	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-
-def trace_begin():
-	print "in trace_begin"
-
-def trace_end():
-	print "in trace_end"
-
-def raw_syscalls__sys_enter(event_name, context, common_cpu,
-	common_secs, common_nsecs, common_pid, common_comm,
-	id, args):
-		print_header(event_name, common_cpu, common_secs, common_nsecs,
-			common_pid, common_comm)
-
-		print "id=%d, args=%s\n" % \
-		(id, args),
-
-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
-		common_pid, common_comm):
-		print_header(event_name, common_cpu, common_secs, common_nsecs,
-		common_pid, common_comm)
-
-def print_header(event_name, cpu, secs, nsecs, pid, comm):
-	print "%-20s %5u %05u.%09u %8u %-20s " % \
-	(event_name, cpu, secs, nsecs, pid, comm),
-----
-
-At the top is a comment block followed by some import statements and a
-path append which every perf trace script should include.
-
-Following that are a couple generated functions, trace_begin() and
-trace_end(), which are called at the beginning and the end of the
-script respectively (for more details, see the SCRIPT_LAYOUT section
-below).
-
-Following those are the 'event handler' functions generated one for
-every event in the 'perf record' output.  The handler functions take
-the form subsystem__event_name, and contain named parameters, one for
-each field in the event; in this case, there's only one event,
-raw_syscalls__sys_enter().  (see the EVENT HANDLERS section below for
-more info on event handlers).
-
-The final couple of functions are, like the begin and end functions,
-generated for every script.  The first, trace_unhandled(), is called
-every time the script finds an event in the perf.data file that
-doesn't correspond to any event handler in the script.  This could
-mean either that the record step recorded event types that it wasn't
-really interested in, or the script was run against a trace file that
-doesn't correspond to the script.
-
-The script generated by -g option simply prints a line for each
-event found in the trace stream i.e. it basically just dumps the event
-and its parameter values to stdout.  The print_header() function is
-simply a utility function used for that purpose.  Let's rename the
-script and run it to see the default output:
-
-----
-# mv perf-trace.py syscall-counts.py
-# perf trace -s syscall-counts.py
-
-raw_syscalls__sys_enter     1 00840.847582083     7506 perf                  id=1, args=
-raw_syscalls__sys_enter     1 00840.847595764     7506 perf                  id=1, args=
-raw_syscalls__sys_enter     1 00840.847620860     7506 perf                  id=1, args=
-raw_syscalls__sys_enter     1 00840.847710478     6533 npviewer.bin          id=78, args=
-raw_syscalls__sys_enter     1 00840.847719204     6533 npviewer.bin          id=142, args=
-raw_syscalls__sys_enter     1 00840.847755445     6533 npviewer.bin          id=3, args=
-raw_syscalls__sys_enter     1 00840.847775601     6533 npviewer.bin          id=3, args=
-raw_syscalls__sys_enter     1 00840.847781820     6533 npviewer.bin          id=3, args=
-.
-.
-.
-----
-
-Of course, for this script, we're not interested in printing every
-trace event, but rather aggregating it in a useful way.  So we'll get
-rid of everything to do with printing as well as the trace_begin() and
-trace_unhandled() functions, which we won't be using.  That leaves us
-with this minimalistic skeleton:
-
-----
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
-	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-
-def trace_end():
-	print "in trace_end"
-
-def raw_syscalls__sys_enter(event_name, context, common_cpu,
-	common_secs, common_nsecs, common_pid, common_comm,
-	id, args):
-----
-
-In trace_end(), we'll simply print the results, but first we need to
-generate some results to print.  To do that we need to have our
-sys_enter() handler do the necessary tallying until all events have
-been counted.  A hash table indexed by syscall id is a good way to
-store that information; every time the sys_enter() handler is called,
-we simply increment a count associated with that hash entry indexed by
-that syscall id:
-
-----
-  syscalls = autodict()
-
-  try:
-    syscalls[id] += 1
-  except TypeError:
-    syscalls[id] = 1
-----
-
-The syscalls 'autodict' object is a special kind of Python dictionary
-(implemented in Core.py) that implements Perl's 'autovivifying' hashes
-in Python i.e. with autovivifying hashes, you can assign nested hash
-values without having to go to the trouble of creating intermediate
-levels if they don't exist e.g syscalls[comm][pid][id] = 1 will create
-the intermediate hash levels and finally assign the value 1 to the
-hash entry for 'id' (because the value being assigned isn't a hash
-object itself, the initial value is assigned in the TypeError
-exception.  Well, there may be a better way to do this in Python but
-that's what works for now).
-
-Putting that code into the raw_syscalls__sys_enter() handler, we
-effectively end up with a single-level dictionary keyed on syscall id
-and having the counts we've tallied as values.
-
-The print_syscall_totals() function iterates over the entries in the
-dictionary and displays a line for each entry containing the syscall
-name (the dictonary keys contain the syscall ids, which are passed to
-the Util function syscall_name(), which translates the raw syscall
-numbers to the corresponding syscall name strings).  The output is
-displayed after all the events in the trace have been processed, by
-calling the print_syscall_totals() function from the trace_end()
-handler called at the end of script processing.
-
-The final script producing the output shown above is shown in its
-entirety below (syscall_name() helper is not yet available, you can
-only deal with id's for now):
-
-----
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
-	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import *
-
-syscalls = autodict()
-
-def trace_end():
-	print_syscall_totals()
-
-def raw_syscalls__sys_enter(event_name, context, common_cpu,
-	common_secs, common_nsecs, common_pid, common_comm,
-	id, args):
-	try:
-		syscalls[id] += 1
-	except TypeError:
-		syscalls[id] = 1
-
-def print_syscall_totals():
-    if for_comm is not None:
-	    print "\nsyscall events for %s:\n\n" % (for_comm),
-    else:
-	    print "\nsyscall events:\n\n",
-
-    print "%-40s  %10s\n" % ("event", "count"),
-    print "%-40s  %10s\n" % ("----------------------------------------", \
-                                 "-----------"),
-
-    for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \
-				  reverse = True):
-	    print "%-40s  %10d\n" % (syscall_name(id), val),
-----
-
-The script can be run just as before:
-
-  # perf trace -s syscall-counts.py
-
-So those are the essential steps in writing and running a script.  The
-process can be generalized to any tracepoint or set of tracepoints
-you're interested in - basically find the tracepoint(s) you're
-interested in by looking at the list of available events shown by
-'perf list' and/or look in /sys/kernel/debug/tracing events for
-detailed event and field info, record the corresponding trace data
-using 'perf record', passing it the list of interesting events,
-generate a skeleton script using 'perf trace -g python' and modify the
-code to aggregate and display it for your particular needs.
-
-After you've done that you may end up with a general-purpose script
-that you want to keep around and have available for future use.  By
-writing a couple of very simple shell scripts and putting them in the
-right place, you can have your script listed alongside the other
-scripts listed by the 'perf trace -l' command e.g.:
-
-----
-root@tropicana:~# perf trace -l
-List of available trace scripts:
-  workqueue-stats                      workqueue stats (ins/exe/create/destroy)
-  wakeup-latency                       system-wide min/max/avg wakeup latency
-  rw-by-file <comm>                    r/w activity for a program, by file
-  rw-by-pid                            system-wide r/w activity
-----
-
-A nice side effect of doing this is that you also then capture the
-probably lengthy 'perf record' command needed to record the events for
-the script.
-
-To have the script appear as a 'built-in' script, you write two simple
-scripts, one for recording and one for 'reporting'.
-
-The 'record' script is a shell script with the same base name as your
-script, but with -record appended.  The shell script should be put
-into the perf/scripts/python/bin directory in the kernel source tree.
-In that script, you write the 'perf record' command-line needed for
-your script:
-
-----
-# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-record
-
-#!/bin/bash
-perf record -a -e raw_syscalls:sys_enter
-----
-
-The 'report' script is also a shell script with the same base name as
-your script, but with -report appended.  It should also be located in
-the perf/scripts/python/bin directory.  In that script, you write the
-'perf trace -s' command-line needed for running your script:
-
-----
-# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report
-
-#!/bin/bash
-# description: system-wide syscall counts
-perf trace -s ~/libexec/perf-core/scripts/python/syscall-counts.py
-----
-
-Note that the location of the Python script given in the shell script
-is in the libexec/perf-core/scripts/python directory - this is where
-the script will be copied by 'make install' when you install perf.
-For the installation to install your script there, your script needs
-to be located in the perf/scripts/python directory in the kernel
-source tree:
-
-----
-# ls -al kernel-source/tools/perf/scripts/python
-
-root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python
-total 32
-drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
-drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
-drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin
--rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-trace.py
-drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util
--rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py
-----
-
-Once you've done that (don't forget to do a new 'make install',
-otherwise your script won't show up at run-time), 'perf trace -l'
-should show a new entry for your script:
-
-----
-root@tropicana:~# perf trace -l
-List of available trace scripts:
-  workqueue-stats                      workqueue stats (ins/exe/create/destroy)
-  wakeup-latency                       system-wide min/max/avg wakeup latency
-  rw-by-file <comm>                    r/w activity for a program, by file
-  rw-by-pid                            system-wide r/w activity
-  syscall-counts                       system-wide syscall counts
-----
-
-You can now perform the record step via 'perf trace record':
-
-  # perf trace record syscall-counts
-
-and display the output using 'perf trace report':
-
-  # perf trace report syscall-counts
-
-STARTER SCRIPTS
----------------
-
-You can quickly get started writing a script for a particular set of
-trace data by generating a skeleton script using 'perf trace -g
-python' in the same directory as an existing perf.data trace file.
-That will generate a starter script containing a handler for each of
-the event types in the trace file; it simply prints every available
-field for each event in the trace file.
-
-You can also look at the existing scripts in
-~/libexec/perf-core/scripts/python for typical examples showing how to
-do basic things like aggregate event data, print results, etc.  Also,
-the check-perf-trace.py script, while not interesting for its results,
-attempts to exercise all of the main scripting features.
-
-EVENT HANDLERS
---------------
-
-When perf trace is invoked using a trace script, a user-defined
-'handler function' is called for each event in the trace.  If there's
-no handler function defined for a given event type, the event is
-ignored (or passed to a 'trace_handled' function, see below) and the
-next event is processed.
-
-Most of the event's field values are passed as arguments to the
-handler function; some of the less common ones aren't - those are
-available as calls back into the perf executable (see below).
-
-As an example, the following perf record command can be used to record
-all sched_wakeup events in the system:
-
- # perf record -a -e sched:sched_wakeup
-
-Traces meant to be processed using a script should be recorded with
-the above option: -a to enable system-wide collection.
-
-The format file for the sched_wakep event defines the following fields
-(see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format):
-
-----
- format:
-        field:unsigned short common_type;
-        field:unsigned char common_flags;
-        field:unsigned char common_preempt_count;
-        field:int common_pid;
-        field:int common_lock_depth;
-
-        field:char comm[TASK_COMM_LEN];
-        field:pid_t pid;
-        field:int prio;
-        field:int success;
-        field:int target_cpu;
-----
-
-The handler function for this event would be defined as:
-
-----
-def sched__sched_wakeup(event_name, context, common_cpu, common_secs,
-       common_nsecs, common_pid, common_comm,
-       comm, pid, prio, success, target_cpu):
-       pass
-----
-
-The handler function takes the form subsystem__event_name.
-
-The common_* arguments in the handler's argument list are the set of
-arguments passed to all event handlers; some of the fields correspond
-to the common_* fields in the format file, but some are synthesized,
-and some of the common_* fields aren't common enough to to be passed
-to every event as arguments but are available as library functions.
-
-Here's a brief description of each of the invariant event args:
-
- event_name 	  	    the name of the event as text
- context		    an opaque 'cookie' used in calls back into perf
- common_cpu		    the cpu the event occurred on
- common_secs		    the secs portion of the event timestamp
- common_nsecs		    the nsecs portion of the event timestamp
- common_pid		    the pid of the current task
- common_comm		    the name of the current process
-
-All of the remaining fields in the event's format file have
-counterparts as handler function arguments of the same name, as can be
-seen in the example above.
-
-The above provides the basics needed to directly access every field of
-every event in a trace, which covers 90% of what you need to know to
-write a useful trace script.  The sections below cover the rest.
-
-SCRIPT LAYOUT
--------------
-
-Every perf trace Python script should start by setting up a Python
-module search path and 'import'ing a few support modules (see module
-descriptions below):
-
-----
- import os
- import sys
-
- sys.path.append(os.environ['PERF_EXEC_PATH'] + \
-	      '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
- from perf_trace_context import *
- from Core import *
-----
-
-The rest of the script can contain handler functions and support
-functions in any order.
-
-Aside from the event handler functions discussed above, every script
-can implement a set of optional functions:
-
-*trace_begin*, if defined, is called before any event is processed and
-gives scripts a chance to do setup tasks:
-
-----
-def trace_begin:
-    pass
-----
-
-*trace_end*, if defined, is called after all events have been
- processed and gives scripts a chance to do end-of-script tasks, such
- as display results:
-
-----
-def trace_end:
-    pass
-----
-
-*trace_unhandled*, if defined, is called after for any event that
- doesn't have a handler explicitly defined for it.  The standard set
- of common arguments are passed into it:
-
-----
-def trace_unhandled(event_name, context, common_cpu, common_secs,
-        common_nsecs, common_pid, common_comm):
-    pass
-----
-
-The remaining sections provide descriptions of each of the available
-built-in perf trace Python modules and their associated functions.
-
-AVAILABLE MODULES AND FUNCTIONS
--------------------------------
-
-The following sections describe the functions and variables available
-via the various perf trace Python modules.  To use the functions and
-variables from the given module, add the corresponding 'from XXXX
-import' line to your perf trace script.
-
-Core.py Module
-~~~~~~~~~~~~~~
-
-These functions provide some essential functions to user scripts.
-
-The *flag_str* and *symbol_str* functions provide human-readable
-strings for flag and symbolic fields.  These correspond to the strings
-and values parsed from the 'print fmt' fields of the event format
-files:
-
-  flag_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the flag field field_name of event event_name
-  symbol_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the symbolic field field_name of event event_name
-
-The *autodict* function returns a special kind of Python
-dictionary that implements Perl's 'autovivifying' hashes in Python
-i.e. with autovivifying hashes, you can assign nested hash values
-without having to go to the trouble of creating intermediate levels if
-they don't exist.
-
-  autodict() - returns an autovivifying dictionary instance
-
-
-perf_trace_context Module
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Some of the 'common' fields in the event format file aren't all that
-common, but need to be made accessible to user scripts nonetheless.
-
-perf_trace_context defines a set of functions that can be used to
-access this data in the context of the current event.  Each of these
-functions expects a context variable, which is the same as the
-context variable passed into every event handler as the second
-argument.
-
- common_pc(context) - returns common_preempt count for the current event
- common_flags(context) - returns common_flags for the current event
- common_lock_depth(context) - returns common_lock_depth for the current event
-
-Util.py Module
-~~~~~~~~~~~~~~
-
-Various utility functions for use with perf trace:
-
-  nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair
-  nsecs_secs(nsecs) - returns whole secs portion given nsecs
-  nsecs_nsecs(nsecs) - returns nsecs remainder given nsecs
-  nsecs_str(nsecs) - returns printable string in the form secs.nsecs
-  avg(total, n) - returns average given a sum and a total number of values
-
-SEE ALSO
---------
-linkperf:perf-trace[1]
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
deleted file mode 100644
index 26aff6b..0000000
--- a/tools/perf/Documentation/perf-trace.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-perf-trace(1)
-=============
-
-NAME
-----
-perf-trace - Read perf.data (created by perf record) and display trace output
-
-SYNOPSIS
---------
-[verse]
-'perf trace' [<options>]
-'perf trace' [<options>] record <script> [<record-options>] <command>
-'perf trace' [<options>] report <script> [script-args]
-'perf trace' [<options>] <script> <required-script-args> [<record-options>] <command>
-'perf trace' [<options>] <top-script> [script-args]
-
-DESCRIPTION
------------
-This command reads the input file and displays the trace recorded.
-
-There are several variants of perf trace:
-
-  'perf trace' to see a detailed trace of the workload that was
-  recorded.
-
-  You can also run a set of pre-canned scripts that aggregate and
-  summarize the raw trace data in various ways (the list of scripts is
-  available via 'perf trace -l').  The following variants allow you to
-  record and run those scripts:
-
-  'perf trace record <script> <command>' to record the events required
-  for 'perf trace report'.  <script> is the name displayed in the
-  output of 'perf trace --list' i.e. the actual script name minus any
-  language extension.  If <command> is not specified, the events are
-  recorded using the -a (system-wide) 'perf record' option.
-
-  'perf trace report <script> [args]' to run and display the results
-  of <script>.  <script> is the name displayed in the output of 'perf
-  trace --list' i.e. the actual script name minus any language
-  extension.  The perf.data output from a previous run of 'perf trace
-  record <script>' is used and should be present for this command to
-  succeed.  [args] refers to the (mainly optional) args expected by
-  the script.
-
-  'perf trace <script> <required-script-args> <command>' to both
-  record the events required for <script> and to run the <script>
-  using 'live-mode' i.e. without writing anything to disk.  <script>
-  is the name displayed in the output of 'perf trace --list' i.e. the
-  actual script name minus any language extension.  If <command> is
-  not specified, the events are recorded using the -a (system-wide)
-  'perf record' option.  If <script> has any required args, they
-  should be specified before <command>.  This mode doesn't allow for
-  optional script args to be specified; if optional script args are
-  desired, they can be specified using separate 'perf trace record'
-  and 'perf trace report' commands, with the stdout of the record step
-  piped to the stdin of the report script, using the '-o -' and '-i -'
-  options of the corresponding commands.
-
-  'perf trace <top-script>' to both record the events required for
-  <top-script> and to run the <top-script> using 'live-mode'
-  i.e. without writing anything to disk.  <top-script> is the name
-  displayed in the output of 'perf trace --list' i.e. the actual
-  script name minus any language extension; a <top-script> is defined
-  as any script name ending with the string 'top'.
-
-  [<record-options>] can be passed to the record steps of 'perf trace
-  record' and 'live-mode' variants; this isn't possible however for
-  <top-script> 'live-mode' or 'perf trace report' variants.
-
-  See the 'SEE ALSO' section for links to language-specific
-  information on how to write and run your own trace scripts.
-
-OPTIONS
--------
-<command>...::
-	Any command you can specify in a shell.
-
--D::
---dump-raw-trace=::
-        Display verbose dump of the trace data.
-
--L::
---Latency=::
-        Show latency attributes (irqs/preemption disabled, etc).
-
--l::
---list=::
-        Display a list of available trace scripts.
-
--s ['lang']::
---script=::
-        Process trace data with the given script ([lang]:script[.ext]).
-	If the string 'lang' is specified in place of a script name, a
-        list of supported languages will be displayed instead.
-
--g::
---gen-script=::
-        Generate perf-trace.[ext] starter script for given language,
-        using current perf.data.
-
--a::
-        Force system-wide collection.  Scripts run without a <command>
-        normally use -a by default, while scripts run with a <command>
-        normally don't - this option allows the latter to be run in
-        system-wide mode.
-
-
-SEE ALSO
---------
-linkperf:perf-record[1], linkperf:perf-trace-perl[1],
-linkperf:perf-trace-python[1]
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8c7fc0c..c12659d 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -7,6 +7,7 @@
 lib/rbtree.c
 include/linux/swab.h
 arch/*/include/asm/unistd*.h
+arch/*/lib/memcpy*.S
 include/linux/poison.h
 include/linux/magic.h
 include/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index d1db0f6..1b9b13e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -185,7 +185,10 @@
         ARCH := x86
 endif
 ifeq ($(ARCH),x86_64)
+	RAW_ARCH := x86_64
         ARCH := x86
+	ARCH_CFLAGS := -DARCH_X86_64
+	ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
 endif
 
 # CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -375,6 +378,7 @@
 LIB_H += util/include/linux/rbtree.h
 LIB_H += util/include/linux/string.h
 LIB_H += util/include/linux/types.h
+LIB_H += util/include/linux/linkage.h
 LIB_H += util/include/asm/asm-offsets.h
 LIB_H += util/include/asm/bug.h
 LIB_H += util/include/asm/byteorder.h
@@ -383,6 +387,8 @@
 LIB_H += util/include/asm/system.h
 LIB_H += util/include/asm/uaccess.h
 LIB_H += util/include/dwarf-regs.h
+LIB_H += util/include/asm/dwarf2.h
+LIB_H += util/include/asm/cpufeature.h
 LIB_H += perf.h
 LIB_H += util/cache.h
 LIB_H += util/callchain.h
@@ -390,6 +396,7 @@
 LIB_H += util/debug.h
 LIB_H += util/debugfs.h
 LIB_H += util/event.h
+LIB_H += util/evsel.h
 LIB_H += util/exec_cmd.h
 LIB_H += util/types.h
 LIB_H += util/levenshtein.h
@@ -398,6 +405,7 @@
 LIB_H += util/parse-events.h
 LIB_H += util/quote.h
 LIB_H += util/util.h
+LIB_H += util/xyarray.h
 LIB_H += util/header.h
 LIB_H += util/help.h
 LIB_H += util/session.h
@@ -417,6 +425,7 @@
 LIB_H += util/probe-event.h
 LIB_H += util/pstack.h
 LIB_H += util/cpumap.h
+LIB_H += $(ARCH_INCLUDE)
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -426,6 +435,7 @@
 LIB_OBJS += $(OUTPUT)util/debugfs.o
 LIB_OBJS += $(OUTPUT)util/environment.o
 LIB_OBJS += $(OUTPUT)util/event.o
+LIB_OBJS += $(OUTPUT)util/evsel.o
 LIB_OBJS += $(OUTPUT)util/exec_cmd.o
 LIB_OBJS += $(OUTPUT)util/help.o
 LIB_OBJS += $(OUTPUT)util/levenshtein.o
@@ -463,6 +473,7 @@
 LIB_OBJS += $(OUTPUT)util/hist.o
 LIB_OBJS += $(OUTPUT)util/probe-event.o
 LIB_OBJS += $(OUTPUT)util/util.o
+LIB_OBJS += $(OUTPUT)util/xyarray.o
 LIB_OBJS += $(OUTPUT)util/cpumap.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
@@ -472,6 +483,9 @@
 # Benchmark modules
 BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
 BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
+ifeq ($(RAW_ARCH),x86_64)
+BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
+endif
 BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
@@ -485,7 +499,7 @@
 BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
 BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
 BUILTIN_OBJS += $(OUTPUT)builtin-top.o
-BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
+BUILTIN_OBJS += $(OUTPUT)builtin-script.o
 BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
 BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
 BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
@@ -507,7 +521,7 @@
 -include config.mak
 
 ifndef NO_DWARF
-FLAGS_DWARF=$(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
+FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
 	msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
 	NO_DWARF := 1
@@ -554,7 +568,7 @@
 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
 	msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
 else
-	BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT
+	BASIC_CFLAGS += -DDWARF_SUPPORT
 	EXTLIBS += -lelf -ldw
 	LIB_OBJS += $(OUTPUT)util/probe-finder.o
 endif # PERF_HAVE_DWARF_REGS
@@ -891,13 +905,14 @@
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
 
-LIBS = $(PERFLIBS) $(EXTLIBS)
+LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS)
 
 BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
 	$(COMPAT_CFLAGS)
 LIB_OBJS += $(COMPAT_OBJS)
 
 ALL_CFLAGS += $(BASIC_CFLAGS)
+ALL_CFLAGS += $(ARCH_CFLAGS)
 ALL_LDFLAGS += $(BASIC_LDFLAGS)
 
 export TAR INSTALL DESTDIR SHELL_PATH
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile
new file mode 100644
index 0000000..15130b50
--- /dev/null
+++ b/tools/perf/arch/s390/Makefile
@@ -0,0 +1,4 @@
+ifndef NO_DWARF
+PERF_HAVE_DWARF_REGS := 1
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
+endif
diff --git a/tools/perf/arch/s390/util/dwarf-regs.c b/tools/perf/arch/s390/util/dwarf-regs.c
new file mode 100644
index 0000000..e19653e
--- /dev/null
+++ b/tools/perf/arch/s390/util/dwarf-regs.c
@@ -0,0 +1,22 @@
+/*
+ * Mapping of DWARF debug register numbers into register names.
+ *
+ *    Copyright IBM Corp. 2010
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+#include <libio.h>
+#include <dwarf-regs.h>
+
+#define NUM_GPRS 16
+
+static const char *gpr_names[NUM_GPRS] = {
+	"%r0", "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
+	"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
+};
+
+const char *get_arch_regstr(unsigned int n)
+{
+	return (n >= NUM_GPRS) ? NULL : gpr_names[n];
+}
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
new file mode 100644
index 0000000..a72e36c
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -0,0 +1,12 @@
+
+#ifdef ARCH_X86_64
+
+#define MEMCPY_FN(fn, name, desc)		\
+	extern void *fn(void *, const void *, size_t);
+
+#include "mem-memcpy-x86-64-asm-def.h"
+
+#undef MEMCPY_FN
+
+#endif
+
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
new file mode 100644
index 0000000..d588b87
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -0,0 +1,4 @@
+
+MEMCPY_FN(__memcpy,
+	"x86-64-unrolled",
+	"unrolled memcpy() in arch/x86/lib/memcpy_64.S")
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
new file mode 100644
index 0000000..a57b66e
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -0,0 +1,2 @@
+
+#include "../../../arch/x86/lib/memcpy_64.S"
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 38dae74..db82021 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -12,6 +12,7 @@
 #include "../util/parse-options.h"
 #include "../util/header.h"
 #include "bench.h"
+#include "mem-memcpy-arch.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -23,8 +24,10 @@
 
 static const char	*length_str	= "1MB";
 static const char	*routine	= "default";
-static bool		use_clock	= false;
+static bool		use_clock;
 static int		clock_fd;
+static bool		only_prefault;
+static bool		no_prefault;
 
 static const struct option options[] = {
 	OPT_STRING('l', "length", &length_str, "1MB",
@@ -34,19 +37,33 @@
 		    "Specify routine to copy"),
 	OPT_BOOLEAN('c', "clock", &use_clock,
 		    "Use CPU clock for measuring"),
+	OPT_BOOLEAN('o', "only-prefault", &only_prefault,
+		    "Show only the result with page faults before memcpy()"),
+	OPT_BOOLEAN('n', "no-prefault", &no_prefault,
+		    "Show only the result without page faults before memcpy()"),
 	OPT_END()
 };
 
+typedef void *(*memcpy_t)(void *, const void *, size_t);
+
 struct routine {
 	const char *name;
 	const char *desc;
-	void * (*fn)(void *dst, const void *src, size_t len);
+	memcpy_t fn;
 };
 
 struct routine routines[] = {
 	{ "default",
 	  "Default memcpy() provided by glibc",
 	  memcpy },
+#ifdef ARCH_X86_64
+
+#define MEMCPY_FN(fn, name, desc) { name, desc, fn },
+#include "mem-memcpy-x86-64-asm-def.h"
+#undef MEMCPY_FN
+
+#endif
+
 	{ NULL,
 	  NULL,
 	  NULL   }
@@ -89,29 +106,98 @@
 		(double)ts->tv_usec / (double)1000000;
 }
 
+static void alloc_mem(void **dst, void **src, size_t length)
+{
+	*dst = zalloc(length);
+	if (!dst)
+		die("memory allocation failed - maybe length is too large?\n");
+
+	*src = zalloc(length);
+	if (!src)
+		die("memory allocation failed - maybe length is too large?\n");
+}
+
+static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
+{
+	u64 clock_start = 0ULL, clock_end = 0ULL;
+	void *src = NULL, *dst = NULL;
+
+	alloc_mem(&src, &dst, len);
+
+	if (prefault)
+		fn(dst, src, len);
+
+	clock_start = get_clock();
+	fn(dst, src, len);
+	clock_end = get_clock();
+
+	free(src);
+	free(dst);
+	return clock_end - clock_start;
+}
+
+static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
+{
+	struct timeval tv_start, tv_end, tv_diff;
+	void *src = NULL, *dst = NULL;
+
+	alloc_mem(&src, &dst, len);
+
+	if (prefault)
+		fn(dst, src, len);
+
+	BUG_ON(gettimeofday(&tv_start, NULL));
+	fn(dst, src, len);
+	BUG_ON(gettimeofday(&tv_end, NULL));
+
+	timersub(&tv_end, &tv_start, &tv_diff);
+
+	free(src);
+	free(dst);
+	return (double)((double)len / timeval2double(&tv_diff));
+}
+
+#define pf (no_prefault ? 0 : 1)
+
+#define print_bps(x) do {					\
+		if (x < K)					\
+			printf(" %14lf B/Sec", x);		\
+		else if (x < K * K)				\
+			printf(" %14lfd KB/Sec", x / K);	\
+		else if (x < K * K * K)				\
+			printf(" %14lf MB/Sec", x / K / K);	\
+		else						\
+			printf(" %14lf GB/Sec", x / K / K / K); \
+	} while (0)
+
 int bench_mem_memcpy(int argc, const char **argv,
 		     const char *prefix __used)
 {
 	int i;
-	void *dst, *src;
-	size_t length;
-	double bps = 0.0;
-	struct timeval tv_start, tv_end, tv_diff;
-	u64 clock_start, clock_end, clock_diff;
+	size_t len;
+	double result_bps[2];
+	u64 result_clock[2];
 
-	clock_start = clock_end = clock_diff = 0ULL;
 	argc = parse_options(argc, argv, options,
 			     bench_mem_memcpy_usage, 0);
 
-	tv_diff.tv_sec = 0;
-	tv_diff.tv_usec = 0;
-	length = (size_t)perf_atoll((char *)length_str);
+	if (use_clock)
+		init_clock();
 
-	if ((s64)length <= 0) {
+	len = (size_t)perf_atoll((char *)length_str);
+
+	result_clock[0] = result_clock[1] = 0ULL;
+	result_bps[0] = result_bps[1] = 0.0;
+
+	if ((s64)len <= 0) {
 		fprintf(stderr, "Invalid length:%s\n", length_str);
 		return 1;
 	}
 
+	/* same to without specifying either of prefault and no-prefault */
+	if (only_prefault && no_prefault)
+		only_prefault = no_prefault = false;
+
 	for (i = 0; routines[i].name; i++) {
 		if (!strcmp(routines[i].name, routine))
 			break;
@@ -126,61 +212,80 @@
 		return 1;
 	}
 
-	dst = zalloc(length);
-	if (!dst)
-		die("memory allocation failed - maybe length is too large?\n");
+	if (bench_format == BENCH_FORMAT_DEFAULT)
+		printf("# Copying %s Bytes ...\n\n", length_str);
 
-	src = zalloc(length);
-	if (!src)
-		die("memory allocation failed - maybe length is too large?\n");
-
-	if (bench_format == BENCH_FORMAT_DEFAULT) {
-		printf("# Copying %s Bytes from %p to %p ...\n\n",
-		       length_str, src, dst);
-	}
-
-	if (use_clock) {
-		init_clock();
-		clock_start = get_clock();
+	if (!only_prefault && !no_prefault) {
+		/* show both of results */
+		if (use_clock) {
+			result_clock[0] =
+				do_memcpy_clock(routines[i].fn, len, false);
+			result_clock[1] =
+				do_memcpy_clock(routines[i].fn, len, true);
+		} else {
+			result_bps[0] =
+				do_memcpy_gettimeofday(routines[i].fn,
+						len, false);
+			result_bps[1] =
+				do_memcpy_gettimeofday(routines[i].fn,
+						len, true);
+		}
 	} else {
-		BUG_ON(gettimeofday(&tv_start, NULL));
-	}
-
-	routines[i].fn(dst, src, length);
-
-	if (use_clock) {
-		clock_end = get_clock();
-		clock_diff = clock_end - clock_start;
-	} else {
-		BUG_ON(gettimeofday(&tv_end, NULL));
-		timersub(&tv_end, &tv_start, &tv_diff);
-		bps = (double)((double)length / timeval2double(&tv_diff));
+		if (use_clock) {
+			result_clock[pf] =
+				do_memcpy_clock(routines[i].fn,
+						len, only_prefault);
+		} else {
+			result_bps[pf] =
+				do_memcpy_gettimeofday(routines[i].fn,
+						len, only_prefault);
+		}
 	}
 
 	switch (bench_format) {
 	case BENCH_FORMAT_DEFAULT:
-		if (use_clock) {
-			printf(" %14lf Clock/Byte\n",
-			       (double)clock_diff / (double)length);
-		} else {
-			if (bps < K)
-				printf(" %14lf B/Sec\n", bps);
-			else if (bps < K * K)
-				printf(" %14lfd KB/Sec\n", bps / 1024);
-			else if (bps < K * K * K)
-				printf(" %14lf MB/Sec\n", bps / 1024 / 1024);
-			else {
-				printf(" %14lf GB/Sec\n",
-				       bps / 1024 / 1024 / 1024);
+		if (!only_prefault && !no_prefault) {
+			if (use_clock) {
+				printf(" %14lf Clock/Byte\n",
+					(double)result_clock[0]
+					/ (double)len);
+				printf(" %14lf Clock/Byte (with prefault)\n",
+					(double)result_clock[1]
+					/ (double)len);
+			} else {
+				print_bps(result_bps[0]);
+				printf("\n");
+				print_bps(result_bps[1]);
+				printf(" (with prefault)\n");
 			}
+		} else {
+			if (use_clock) {
+				printf(" %14lf Clock/Byte",
+					(double)result_clock[pf]
+					/ (double)len);
+			} else
+				print_bps(result_bps[pf]);
+
+			printf("%s\n", only_prefault ? " (with prefault)" : "");
 		}
 		break;
 	case BENCH_FORMAT_SIMPLE:
-		if (use_clock) {
-			printf("%14lf\n",
-			       (double)clock_diff / (double)length);
-		} else
-			printf("%lf\n", bps);
+		if (!only_prefault && !no_prefault) {
+			if (use_clock) {
+				printf("%lf %lf\n",
+					(double)result_clock[0] / (double)len,
+					(double)result_clock[1] / (double)len);
+			} else {
+				printf("%lf %lf\n",
+					result_bps[0], result_bps[1]);
+			}
+		} else {
+			if (use_clock) {
+				printf("%lf\n", (double)result_clock[pf]
+					/ (double)len);
+			} else
+				printf("%lf\n", result_bps[pf]);
+		}
 		break;
 	default:
 		/* reaching this means there's some disaster: */
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6d5604d8d..c056cdc 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -58,12 +58,12 @@
 	return hist_entry__inc_addr_samples(he, al->addr);
 }
 
-static int process_sample_event(event_t *event, struct perf_session *session)
+static int process_sample_event(event_t *event, struct sample_data *sample,
+				struct perf_session *session)
 {
 	struct addr_location al;
-	struct sample_data data;
 
-	if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) {
+	if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
 			   event->header.type);
 		return -1;
@@ -375,6 +375,8 @@
 	.mmap	= event__process_mmap,
 	.comm	= event__process_comm,
 	.fork	= event__process_task,
+	.ordered_samples = true,
+	.ordering_requires_timestamps = true,
 };
 
 static int __cmd_annotate(void)
@@ -382,7 +384,7 @@
 	int ret;
 	struct perf_session *session;
 
-	session = perf_session__new(input_name, O_RDONLY, force, false);
+	session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index c49837d..5af32ae 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -38,7 +38,8 @@
 {
 	struct perf_session *session;
 
-	session = perf_session__new(input_name, O_RDONLY, force, false);
+	session = perf_session__new(input_name, O_RDONLY, force, false,
+				    &build_id__mark_dso_hit_ops);
 	if (session == NULL)
 		return -1;
 
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index fca1d44..3153e49 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,12 +30,13 @@
 	return -ENOMEM;
 }
 
-static int diff__process_sample_event(event_t *event, struct perf_session *session)
+static int diff__process_sample_event(event_t *event,
+				      struct sample_data *sample,
+				      struct perf_session *session)
 {
 	struct addr_location al;
-	struct sample_data data = { .period = 1, };
 
-	if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) {
+	if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
 			   event->header.type);
 		return -1;
@@ -44,12 +45,12 @@
 	if (al.filtered || al.sym == NULL)
 		return 0;
 
-	if (hists__add_entry(&session->hists, &al, data.period)) {
+	if (hists__add_entry(&session->hists, &al, sample->period)) {
 		pr_warning("problem incrementing symbol period, skipping event\n");
 		return -1;
 	}
 
-	session->hists.stats.total_period += data.period;
+	session->hists.stats.total_period += sample->period;
 	return 0;
 }
 
@@ -60,6 +61,8 @@
 	.exit	= event__process_task,
 	.fork	= event__process_task,
 	.lost	= event__process_lost,
+	.ordered_samples = true,
+	.ordering_requires_timestamps = true,
 };
 
 static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
@@ -141,8 +144,8 @@
 	int ret, i;
 	struct perf_session *session[2];
 
-	session[0] = perf_session__new(input_old, O_RDONLY, force, false);
-	session[1] = perf_session__new(input_new, O_RDONLY, force, false);
+	session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops);
+	session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops);
 	if (session[0] == NULL || session[1] == NULL)
 		return -ENOMEM;
 
@@ -173,7 +176,7 @@
 static const struct option options[] = {
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show symbol address, etc)"),
-	OPT_BOOLEAN('m', "displacement", &show_displacement,
+	OPT_BOOLEAN('M', "displacement", &show_displacement,
 		    "Show position displacement relative to baseline"),
 	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
 		    "dump raw trace in ASCII"),
@@ -191,6 +194,8 @@
 	OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
 		   "separator for columns, no spaces will be added between "
 		   "columns '.' is reserved."),
+	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
+		    "Look for files with symbols relative to this directory"),
 	OPT_END()
 };
 
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8e3e47b..0c78ffa 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,8 +16,8 @@
 static char		const *input_name = "-";
 static bool		inject_build_ids;
 
-static int event__repipe(event_t *event __used,
-			 struct perf_session *session __used)
+static int event__repipe_synth(event_t *event,
+			       struct perf_session *session __used)
 {
 	uint32_t size;
 	void *buf = event;
@@ -36,22 +36,30 @@
 	return 0;
 }
 
-static int event__repipe_mmap(event_t *self, struct perf_session *session)
+static int event__repipe(event_t *event, struct sample_data *sample __used,
+			 struct perf_session *session)
+{
+	return event__repipe_synth(event, session);
+}
+
+static int event__repipe_mmap(event_t *self, struct sample_data *sample,
+			      struct perf_session *session)
 {
 	int err;
 
-	err = event__process_mmap(self, session);
-	event__repipe(self, session);
+	err = event__process_mmap(self, sample, session);
+	event__repipe(self, sample, session);
 
 	return err;
 }
 
-static int event__repipe_task(event_t *self, struct perf_session *session)
+static int event__repipe_task(event_t *self, struct sample_data *sample,
+			      struct perf_session *session)
 {
 	int err;
 
-	err = event__process_task(self, session);
-	event__repipe(self, session);
+	err = event__process_task(self, sample, session);
+	event__repipe(self, sample, session);
 
 	return err;
 }
@@ -61,7 +69,7 @@
 {
 	int err;
 
-	event__repipe(self, session);
+	event__repipe_synth(self, session);
 	err = event__process_tracing_data(self, session);
 
 	return err;
@@ -111,7 +119,8 @@
 	return 0;
 }
 
-static int event__inject_buildid(event_t *event, struct perf_session *session)
+static int event__inject_buildid(event_t *event, struct sample_data *sample,
+				 struct perf_session *session)
 {
 	struct addr_location al;
 	struct thread *thread;
@@ -146,7 +155,7 @@
 	}
 
 repipe:
-	event__repipe(event, session);
+	event__repipe(event, sample, session);
 	return 0;
 }
 
@@ -160,10 +169,10 @@
 	.read		= event__repipe,
 	.throttle	= event__repipe,
 	.unthrottle	= event__repipe,
-	.attr		= event__repipe,
-	.event_type 	= event__repipe,
-	.tracing_data 	= event__repipe,
-	.build_id 	= event__repipe,
+	.attr		= event__repipe_synth,
+	.event_type 	= event__repipe_synth,
+	.tracing_data 	= event__repipe_synth,
+	.build_id 	= event__repipe_synth,
 };
 
 extern volatile int session_done;
@@ -187,7 +196,7 @@
 		inject_ops.tracing_data	= event__repipe_tracing_data;
 	}
 
-	session = perf_session__new(input_name, O_RDONLY, false, true);
+	session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 31f60a2..def7ddc 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -304,22 +304,11 @@
 	}
 }
 
-static int process_sample_event(event_t *event, struct perf_session *session)
+static int process_sample_event(event_t *event, struct sample_data *sample,
+				struct perf_session *session)
 {
-	struct sample_data data;
-	struct thread *thread;
+	struct thread *thread = perf_session__findnew(session, event->ip.pid);
 
-	memset(&data, 0, sizeof(data));
-	data.time = -1;
-	data.cpu = -1;
-	data.period = 1;
-
-	event__parse_sample(event, session->sample_type, &data);
-
-	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
-		    data.pid, data.tid, data.ip, data.period);
-
-	thread = perf_session__findnew(session, event->ip.pid);
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
 			 event->header.type);
@@ -328,8 +317,8 @@
 
 	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-	process_raw_event(event, data.raw_data, data.cpu,
-			  data.time, thread);
+	process_raw_event(event, sample->raw_data, sample->cpu,
+			  sample->time, thread);
 
 	return 0;
 }
@@ -492,7 +481,8 @@
 static int __cmd_kmem(void)
 {
 	int err = -EINVAL;
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
+	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
+							 0, false, &event_ops);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -747,6 +737,9 @@
 	rec_argc = ARRAY_SIZE(record_args) + argc - 1;
 	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
+	if (rec_argv == NULL)
+		return -ENOMEM;
+
 	for (i = 0; i < ARRAY_SIZE(record_args); i++)
 		rec_argv[i] = strdup(record_args[i]);
 
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 821c158..b9c6e54 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -834,22 +834,18 @@
 		die("Unknown type of information\n");
 }
 
-static int process_sample_event(event_t *self, struct perf_session *s)
+static int process_sample_event(event_t *self, struct sample_data *sample,
+				struct perf_session *s)
 {
-	struct sample_data data;
-	struct thread *thread;
+	struct thread *thread = perf_session__findnew(s, sample->tid);
 
-	bzero(&data, sizeof(data));
-	event__parse_sample(self, s->sample_type, &data);
-
-	thread = perf_session__findnew(s, data.tid);
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
 			self->header.type);
 		return -1;
 	}
 
-	process_raw_event(data.raw_data, data.cpu, data.time, thread);
+	process_raw_event(sample->raw_data, sample->cpu, sample->time, thread);
 
 	return 0;
 }
@@ -862,7 +858,7 @@
 
 static int read_events(void)
 {
-	session = perf_session__new(input_name, O_RDONLY, 0, false);
+	session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
 	if (!session)
 		die("Initializing perf session failed\n");
 
@@ -947,6 +943,9 @@
 	rec_argc = ARRAY_SIZE(record_args) + argc - 1;
 	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
+	if (rec_argv == NULL)
+		return -ENOMEM;
+
 	for (i = 0; i < ARRAY_SIZE(record_args); i++)
 		rec_argv[i] = strdup(record_args[i]);
 
@@ -982,9 +981,9 @@
 				usage_with_options(report_usage, report_options);
 		}
 		__cmd_report();
-	} else if (!strcmp(argv[0], "trace")) {
-		/* Aliased to 'perf trace' */
-		return cmd_trace(argc, argv, prefix);
+	} else if (!strcmp(argv[0], "script")) {
+		/* Aliased to 'perf script' */
+		return cmd_script(argc, argv, prefix);
 	} else if (!strcmp(argv[0], "info")) {
 		if (argc) {
 			argc = parse_options(argc, argv,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 564491f..7bc0490 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -18,6 +18,7 @@
 
 #include "util/header.h"
 #include "util/event.h"
+#include "util/evsel.h"
 #include "util/debug.h"
 #include "util/session.h"
 #include "util/symbol.h"
@@ -27,17 +28,18 @@
 #include <sched.h>
 #include <sys/mman.h>
 
+#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+
 enum write_mode_t {
 	WRITE_FORCE,
 	WRITE_APPEND
 };
 
-static int			*fd[MAX_NR_CPUS][MAX_COUNTERS];
-
 static u64			user_interval			= ULLONG_MAX;
 static u64			default_interval		=      0;
+static u64			sample_type;
 
-static int			nr_cpus				=      0;
+static struct cpu_map		*cpus;
 static unsigned int		page_size;
 static unsigned int		mmap_pages			=    128;
 static unsigned int		user_freq 			= UINT_MAX;
@@ -48,11 +50,11 @@
 static int			group				=      0;
 static int			realtime_prio			=      0;
 static bool			raw_samples			=  false;
+static bool			sample_id_all_avail		=   true;
 static bool			system_wide			=  false;
 static pid_t			target_pid			=     -1;
 static pid_t			target_tid			=     -1;
-static pid_t			*all_tids			=      NULL;
-static int			thread_num			=      0;
+static struct thread_map	*threads;
 static pid_t			child_pid			=     -1;
 static bool			no_inherit			=  false;
 static enum write_mode_t	write_mode			= WRITE_FORCE;
@@ -60,7 +62,9 @@
 static bool			inherit_stat			=  false;
 static bool			no_samples			=  false;
 static bool			sample_address			=  false;
+static bool			sample_time			=  false;
 static bool			no_buildid			=  false;
+static bool			no_buildid_cache		=  false;
 
 static long			samples				=      0;
 static u64			bytes_written			=      0;
@@ -77,7 +81,6 @@
 static const char		*cpu_list;
 
 struct mmap_data {
-	int			counter;
 	void			*base;
 	unsigned int		mask;
 	unsigned int		prev;
@@ -128,6 +131,7 @@
 }
 
 static int process_synthesized_event(event_t *event,
+				     struct sample_data *sample __used,
 				     struct perf_session *self __used)
 {
 	write_output(event, event->header.size);
@@ -224,12 +228,12 @@
 	return h_attr;
 }
 
-static void create_counter(int counter, int cpu)
+static void create_counter(struct perf_evsel *evsel, int cpu)
 {
-	char *filter = filters[counter];
-	struct perf_event_attr *attr = attrs + counter;
+	char *filter = evsel->filter;
+	struct perf_event_attr *attr = &evsel->attr;
 	struct perf_header_attr *h_attr;
-	int track = !counter; /* only the first counter needs these */
+	int track = !evsel->idx; /* only the first counter needs these */
 	int thread_index;
 	int ret;
 	struct {
@@ -238,6 +242,19 @@
 		u64 time_running;
 		u64 id;
 	} read_data;
+	/*
+ 	 * Check if parse_single_tracepoint_event has already asked for
+ 	 * PERF_SAMPLE_TIME.
+ 	 *
+	 * XXX this is kludgy but short term fix for problems introduced by
+	 * eac23d1c that broke 'perf script' by having different sample_types
+	 * when using multiple tracepoint events when we use a perf binary
+	 * that tries to use sample_id_all on an older kernel.
+ 	 *
+ 	 * We need to move counter creation to perf_session, support
+ 	 * different sample_types, etc.
+ 	 */
+	bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
 
 	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
 				  PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -280,6 +297,10 @@
 	if (system_wide)
 		attr->sample_type	|= PERF_SAMPLE_CPU;
 
+	if (sample_id_all_avail &&
+	    (sample_time || system_wide || !no_inherit || cpu_list))
+		attr->sample_type	|= PERF_SAMPLE_TIME;
+
 	if (raw_samples) {
 		attr->sample_type	|= PERF_SAMPLE_TIME;
 		attr->sample_type	|= PERF_SAMPLE_RAW;
@@ -293,13 +314,14 @@
 		attr->disabled = 1;
 		attr->enable_on_exec = 1;
 	}
+retry_sample_id:
+	attr->sample_id_all = sample_id_all_avail ? 1 : 0;
 
-	for (thread_index = 0; thread_index < thread_num; thread_index++) {
+	for (thread_index = 0; thread_index < threads->nr; thread_index++) {
 try_again:
-		fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr,
-				all_tids[thread_index], cpu, group_fd, 0);
+		FD(evsel, nr_cpu, thread_index) = sys_perf_event_open(attr, threads->map[thread_index], cpu, group_fd, 0);
 
-		if (fd[nr_cpu][counter][thread_index] < 0) {
+		if (FD(evsel, nr_cpu, thread_index) < 0) {
 			int err = errno;
 
 			if (err == EPERM || err == EACCES)
@@ -309,6 +331,15 @@
 			else if (err ==  ENODEV && cpu_list) {
 				die("No such device - did you specify"
 					" an out-of-range profile CPU?\n");
+			} else if (err == EINVAL && sample_id_all_avail) {
+				/*
+				 * Old kernel, no attr->sample_id_type_all field
+				 */
+				sample_id_all_avail = false;
+				if (!sample_time && !raw_samples && !time_needed)
+					attr->sample_type &= ~PERF_SAMPLE_TIME;
+
+				goto retry_sample_id;
 			}
 
 			/*
@@ -326,8 +357,8 @@
 				goto try_again;
 			}
 			printf("\n");
-			error("perfcounter syscall returned with %d (%s)\n",
-					fd[nr_cpu][counter][thread_index], strerror(err));
+			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
+			      FD(evsel, nr_cpu, thread_index), strerror(err));
 
 #if defined(__i386__) || defined(__x86_64__)
 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
@@ -341,7 +372,7 @@
 			exit(-1);
 		}
 
-		h_attr = get_header_attr(attr, counter);
+		h_attr = get_header_attr(attr, evsel->idx);
 		if (h_attr == NULL)
 			die("nomem\n");
 
@@ -352,7 +383,7 @@
 			}
 		}
 
-		if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) {
+		if (read(FD(evsel, nr_cpu, thread_index), &read_data, sizeof(read_data)) == -1) {
 			perror("Unable to read perf file descriptor");
 			exit(-1);
 		}
@@ -362,43 +393,44 @@
 			exit(-1);
 		}
 
-		assert(fd[nr_cpu][counter][thread_index] >= 0);
-		fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK);
+		assert(FD(evsel, nr_cpu, thread_index) >= 0);
+		fcntl(FD(evsel, nr_cpu, thread_index), F_SETFL, O_NONBLOCK);
 
 		/*
 		 * First counter acts as the group leader:
 		 */
 		if (group && group_fd == -1)
-			group_fd = fd[nr_cpu][counter][thread_index];
+			group_fd = FD(evsel, nr_cpu, thread_index);
 
-		if (counter || thread_index) {
-			ret = ioctl(fd[nr_cpu][counter][thread_index],
-					PERF_EVENT_IOC_SET_OUTPUT,
-					fd[nr_cpu][0][0]);
+		if (evsel->idx || thread_index) {
+			struct perf_evsel *first;
+			first = list_entry(evsel_list.next, struct perf_evsel, node);
+			ret = ioctl(FD(evsel, nr_cpu, thread_index),
+				    PERF_EVENT_IOC_SET_OUTPUT,
+				    FD(first, nr_cpu, 0));
 			if (ret) {
 				error("failed to set output: %d (%s)\n", errno,
 						strerror(errno));
 				exit(-1);
 			}
 		} else {
-			mmap_array[nr_cpu].counter = counter;
 			mmap_array[nr_cpu].prev = 0;
 			mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
 			mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
-				PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0);
+				PROT_READ | PROT_WRITE, MAP_SHARED, FD(evsel, nr_cpu, thread_index), 0);
 			if (mmap_array[nr_cpu].base == MAP_FAILED) {
 				error("failed to mmap with %d (%s)\n", errno, strerror(errno));
 				exit(-1);
 			}
 
-			event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index];
+			event_array[nr_poll].fd = FD(evsel, nr_cpu, thread_index);
 			event_array[nr_poll].events = POLLIN;
 			nr_poll++;
 		}
 
 		if (filter != NULL) {
-			ret = ioctl(fd[nr_cpu][counter][thread_index],
-					PERF_EVENT_IOC_SET_FILTER, filter);
+			ret = ioctl(FD(evsel, nr_cpu, thread_index),
+				    PERF_EVENT_IOC_SET_FILTER, filter);
 			if (ret) {
 				error("failed to set filter with %d (%s)\n", errno,
 						strerror(errno));
@@ -406,15 +438,19 @@
 			}
 		}
 	}
+
+	if (!sample_type)
+		sample_type = attr->sample_type;
 }
 
 static void open_counters(int cpu)
 {
-	int counter;
+	struct perf_evsel *pos;
 
 	group_fd = -1;
-	for (counter = 0; counter < nr_counters; counter++)
-		create_counter(counter, cpu);
+
+	list_for_each_entry(pos, &evsel_list, node)
+		create_counter(pos, cpu);
 
 	nr_cpu++;
 }
@@ -437,7 +473,8 @@
 	if (!pipe_output) {
 		session->header.data_size += bytes_written;
 
-		process_buildids();
+		if (!no_buildid)
+			process_buildids();
 		perf_header__write(&session->header, output, true);
 		perf_session__delete(session);
 		symbol__exit();
@@ -500,7 +537,7 @@
 
 static int __cmd_record(int argc, const char **argv)
 {
-	int i, counter;
+	int i;
 	struct stat st;
 	int flags;
 	int err;
@@ -552,19 +589,22 @@
 	}
 
 	session = perf_session__new(output_name, O_WRONLY,
-				    write_mode == WRITE_FORCE, false);
+				    write_mode == WRITE_FORCE, false, NULL);
 	if (session == NULL) {
 		pr_err("Not enough memory for reading perf file header\n");
 		return -1;
 	}
 
+	if (!no_buildid)
+		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
+
 	if (!file_new) {
 		err = perf_header__read(session, output);
 		if (err < 0)
 			goto out_delete_session;
 	}
 
-	if (have_tracepoints(attrs, nr_counters))
+	if (have_tracepoints(&evsel_list))
 		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
 
 	/*
@@ -612,7 +652,7 @@
 		}
 
 		if (!system_wide && target_tid == -1 && target_pid == -1)
-			all_tids[0] = child_pid;
+			threads->map[0] = child_pid;
 
 		close(child_ready_pipe[1]);
 		close(go_pipe[0]);
@@ -626,19 +666,15 @@
 		close(child_ready_pipe[0]);
 	}
 
-	nr_cpus = read_cpu_map(cpu_list);
-	if (nr_cpus < 1) {
-		perror("failed to collect number of CPUs");
-		return -1;
-	}
-
 	if (!system_wide && no_inherit && !cpu_list) {
 		open_counters(-1);
 	} else {
-		for (i = 0; i < nr_cpus; i++)
-			open_counters(cpumap[i]);
+		for (i = 0; i < cpus->nr; i++)
+			open_counters(cpus->map[i]);
 	}
 
+	perf_session__set_sample_type(session, sample_type);
+
 	if (pipe_output) {
 		err = perf_header__write_pipe(output);
 		if (err < 0)
@@ -651,6 +687,8 @@
 
 	post_processing_offset = lseek(output, 0, SEEK_CUR);
 
+	perf_session__set_sample_id_all(session, sample_id_all_avail);
+
 	if (pipe_output) {
 		err = event__synthesize_attrs(&session->header,
 					      process_synthesized_event,
@@ -667,7 +705,7 @@
 			return err;
 		}
 
-		if (have_tracepoints(attrs, nr_counters)) {
+		if (have_tracepoints(&evsel_list)) {
 			/*
 			 * FIXME err <= 0 here actually means that
 			 * there were no tracepoints so its not really
@@ -676,8 +714,7 @@
 			 * return this more properly and also
 			 * propagate errors that now are calling die()
 			 */
-			err = event__synthesize_tracing_data(output, attrs,
-							     nr_counters,
+			err = event__synthesize_tracing_data(output, &evsel_list,
 							     process_synthesized_event,
 							     session);
 			if (err <= 0) {
@@ -751,13 +788,13 @@
 
 		if (done) {
 			for (i = 0; i < nr_cpu; i++) {
-				for (counter = 0;
-					counter < nr_counters;
-					counter++) {
+				struct perf_evsel *pos;
+
+				list_for_each_entry(pos, &evsel_list, node) {
 					for (thread = 0;
-						thread < thread_num;
+						thread < threads->nr;
 						thread++)
-						ioctl(fd[i][counter][thread],
+						ioctl(FD(pos, i, thread),
 							PERF_EVENT_IOC_DISABLE);
 				}
 			}
@@ -831,16 +868,20 @@
 		    "per thread counts"),
 	OPT_BOOLEAN('d', "data", &sample_address,
 		    "Sample addresses"),
+	OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
 	OPT_BOOLEAN('n', "no-samples", &no_samples,
 		    "don't sample"),
-	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid,
+	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
 		    "do not update the buildid cache"),
+	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
+		    "do not collect buildids in perf.data"),
 	OPT_END()
 };
 
 int cmd_record(int argc, const char **argv, const char *prefix __used)
 {
-	int i, j, err = -ENOMEM;
+	int err = -ENOMEM;
+	struct perf_evsel *pos;
 
 	argc = parse_options(argc, argv, record_options, record_usage,
 			    PARSE_OPT_STOP_AT_NON_OPTION);
@@ -859,41 +900,36 @@
 	}
 
 	symbol__init();
-	if (no_buildid)
+
+	if (no_buildid_cache || no_buildid)
 		disable_buildid_cache();
 
-	if (!nr_counters) {
-		nr_counters	= 1;
-		attrs[0].type	= PERF_TYPE_HARDWARE;
-		attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
+	if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) {
+		pr_err("Not enough memory for event selector list\n");
+		goto out_symbol_exit;
 	}
 
-	if (target_pid != -1) {
+	if (target_pid != -1)
 		target_tid = target_pid;
-		thread_num = find_all_tid(target_pid, &all_tids);
-		if (thread_num <= 0) {
-			fprintf(stderr, "Can't find all threads of pid %d\n",
-					target_pid);
-			usage_with_options(record_usage, record_options);
-		}
-	} else {
-		all_tids=malloc(sizeof(pid_t));
-		if (!all_tids)
-			goto out_symbol_exit;
 
-		all_tids[0] = target_tid;
-		thread_num = 1;
+	threads = thread_map__new(target_pid, target_tid);
+	if (threads == NULL) {
+		pr_err("Problems finding threads of monitor\n");
+		usage_with_options(record_usage, record_options);
 	}
 
-	for (i = 0; i < MAX_NR_CPUS; i++) {
-		for (j = 0; j < MAX_COUNTERS; j++) {
-			fd[i][j] = malloc(sizeof(int)*thread_num);
-			if (!fd[i][j])
-				goto out_free_fd;
-		}
+	cpus = cpu_map__new(cpu_list);
+	if (cpus == NULL) {
+		perror("failed to parse CPUs map");
+		return -1;
 	}
-	event_array = malloc(
-		sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
+
+	list_for_each_entry(pos, &evsel_list, node) {
+		if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
+			goto out_free_fd;
+	}
+	event_array = malloc((sizeof(struct pollfd) * MAX_NR_CPUS *
+			      MAX_COUNTERS * threads->nr));
 	if (!event_array)
 		goto out_free_fd;
 
@@ -920,12 +956,8 @@
 out_free_event_array:
 	free(event_array);
 out_free_fd:
-	for (i = 0; i < MAX_NR_CPUS; i++) {
-		for (j = 0; j < MAX_COUNTERS; j++)
-			free(fd[i][j]);
-	}
-	free(all_tids);
-	all_tids = NULL;
+	thread_map__delete(threads);
+	threads = NULL;
 out_symbol_exit:
 	symbol__exit();
 	return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5de405d..75183a4 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -150,13 +150,13 @@
 	return 0;
 }
 
-static int process_sample_event(event_t *event, struct perf_session *session)
+static int process_sample_event(event_t *event, struct sample_data *sample,
+				struct perf_session *session)
 {
-	struct sample_data data = { .period = 1, };
 	struct addr_location al;
 	struct perf_event_attr *attr;
 
-	if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) {
+	if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
 		fprintf(stderr, "problem processing %d event, skipping it.\n",
 			event->header.type);
 		return -1;
@@ -165,14 +165,14 @@
 	if (al.filtered || (hide_unresolved && al.sym == NULL))
 		return 0;
 
-	if (perf_session__add_hist_entry(session, &al, &data)) {
+	if (perf_session__add_hist_entry(session, &al, sample)) {
 		pr_debug("problem incrementing symbol period, skipping event\n");
 		return -1;
 	}
 
-	attr = perf_header__find_attr(data.id, &session->header);
+	attr = perf_header__find_attr(sample->id, &session->header);
 
-	if (add_event_total(session, &data, attr)) {
+	if (add_event_total(session, sample, attr)) {
 		pr_debug("problem adding event period\n");
 		return -1;
 	}
@@ -180,7 +180,8 @@
 	return 0;
 }
 
-static int process_read_event(event_t *event, struct perf_session *session __used)
+static int process_read_event(event_t *event, struct sample_data *sample __used,
+			      struct perf_session *session __used)
 {
 	struct perf_event_attr *attr;
 
@@ -243,6 +244,8 @@
 	.event_type = event__process_event_type,
 	.tracing_data = event__process_tracing_data,
 	.build_id = event__process_build_id,
+	.ordered_samples = true,
+	.ordering_requires_timestamps = true,
 };
 
 extern volatile int session_done;
@@ -307,7 +310,7 @@
 
 	signal(SIGINT, sig_handler);
 
-	session = perf_session__new(input_name, O_RDONLY, force, false);
+	session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -442,6 +445,8 @@
 		    "dump raw trace in ASCII"),
 	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 		   "file", "vmlinux pathname"),
+	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
+		   "file", "kallsyms pathname"),
 	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
 	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
 		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
@@ -478,6 +483,8 @@
 		   "columns '.' is reserved."),
 	OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved,
 		    "Only display entries resolved to a symbol"),
+	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
+		    "Look for files with symbols relative to this directory"),
 	OPT_END()
 };
 
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 55f3b5d..7a4ebeb 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1606,25 +1606,15 @@
 		process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
 }
 
-static int process_sample_event(event_t *event, struct perf_session *session)
+static int process_sample_event(event_t *event, struct sample_data *sample,
+				struct perf_session *session)
 {
-	struct sample_data data;
 	struct thread *thread;
 
 	if (!(session->sample_type & PERF_SAMPLE_RAW))
 		return 0;
 
-	memset(&data, 0, sizeof(data));
-	data.time = -1;
-	data.cpu = -1;
-	data.period = -1;
-
-	event__parse_sample(event, session->sample_type, &data);
-
-	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
-		    data.pid, data.tid, data.ip, data.period);
-
-	thread = perf_session__findnew(session, data.pid);
+	thread = perf_session__findnew(session, sample->pid);
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
 			 event->header.type);
@@ -1633,10 +1623,11 @@
 
 	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-	if (profile_cpu != -1 && profile_cpu != (int)data.cpu)
+	if (profile_cpu != -1 && profile_cpu != (int)sample->cpu)
 		return 0;
 
-	process_raw_event(event, session, data.raw_data, data.cpu, data.time, thread);
+	process_raw_event(event, session, sample->raw_data, sample->cpu,
+			  sample->time, thread);
 
 	return 0;
 }
@@ -1652,7 +1643,8 @@
 static int read_events(void)
 {
 	int err = -EINVAL;
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
+	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
+							 0, false, &event_ops);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -1869,6 +1861,9 @@
 	rec_argc = ARRAY_SIZE(record_args) + argc - 1;
 	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
+	if (rec_argv)
+		return -ENOMEM;
+
 	for (i = 0; i < ARRAY_SIZE(record_args); i++)
 		rec_argv[i] = strdup(record_args[i]);
 
@@ -1888,10 +1883,10 @@
 		usage_with_options(sched_usage, sched_options);
 
 	/*
-	 * Aliased to 'perf trace' for now:
+	 * Aliased to 'perf script' for now:
 	 */
-	if (!strcmp(argv[0], "trace"))
-		return cmd_trace(argc, argv, prefix);
+	if (!strcmp(argv[0], "script"))
+		return cmd_script(argc, argv, prefix);
 
 	symbol__init();
 	if (!strncmp(argv[0], "rec", 3)) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
new file mode 100644
index 0000000..150a606
--- /dev/null
+++ b/tools/perf/builtin-script.c
@@ -0,0 +1,821 @@
+#include "builtin.h"
+
+#include "perf.h"
+#include "util/cache.h"
+#include "util/debug.h"
+#include "util/exec_cmd.h"
+#include "util/header.h"
+#include "util/parse-options.h"
+#include "util/session.h"
+#include "util/symbol.h"
+#include "util/thread.h"
+#include "util/trace-event.h"
+#include "util/parse-options.h"
+#include "util/util.h"
+
+static char const		*script_name;
+static char const		*generate_script_lang;
+static bool			debug_mode;
+static u64			last_timestamp;
+static u64			nr_unordered;
+extern const struct option	record_options[];
+
+static int default_start_script(const char *script __unused,
+				int argc __unused,
+				const char **argv __unused)
+{
+	return 0;
+}
+
+static int default_stop_script(void)
+{
+	return 0;
+}
+
+static int default_generate_script(const char *outfile __unused)
+{
+	return 0;
+}
+
+static struct scripting_ops default_scripting_ops = {
+	.start_script		= default_start_script,
+	.stop_script		= default_stop_script,
+	.process_event		= print_event,
+	.generate_script	= default_generate_script,
+};
+
+static struct scripting_ops	*scripting_ops;
+
+static void setup_scripting(void)
+{
+	setup_perl_scripting();
+	setup_python_scripting();
+
+	scripting_ops = &default_scripting_ops;
+}
+
+static int cleanup_scripting(void)
+{
+	pr_debug("\nperf script stopped\n");
+
+	return scripting_ops->stop_script();
+}
+
+static char const		*input_name = "perf.data";
+
+static int process_sample_event(event_t *event, struct sample_data *sample,
+				struct perf_session *session)
+{
+	struct thread *thread = perf_session__findnew(session, event->ip.pid);
+
+	if (thread == NULL) {
+		pr_debug("problem processing %d event, skipping it.\n",
+			 event->header.type);
+		return -1;
+	}
+
+	if (session->sample_type & PERF_SAMPLE_RAW) {
+		if (debug_mode) {
+			if (sample->time < last_timestamp) {
+				pr_err("Samples misordered, previous: %llu "
+					"this: %llu\n", last_timestamp,
+					sample->time);
+				nr_unordered++;
+			}
+			last_timestamp = sample->time;
+			return 0;
+		}
+		/*
+		 * FIXME: better resolve from pid from the struct trace_entry
+		 * field, although it should be the same than this perf
+		 * event pid
+		 */
+		scripting_ops->process_event(sample->cpu, sample->raw_data,
+					     sample->raw_size,
+					     sample->time, thread->comm);
+	}
+
+	session->hists.stats.total_period += sample->period;
+	return 0;
+}
+
+static struct perf_event_ops event_ops = {
+	.sample	= process_sample_event,
+	.comm	= event__process_comm,
+	.attr	= event__process_attr,
+	.event_type = event__process_event_type,
+	.tracing_data = event__process_tracing_data,
+	.build_id = event__process_build_id,
+	.ordering_requires_timestamps = true,
+	.ordered_samples = true,
+};
+
+extern volatile int session_done;
+
+static void sig_handler(int sig __unused)
+{
+	session_done = 1;
+}
+
+static int __cmd_script(struct perf_session *session)
+{
+	int ret;
+
+	signal(SIGINT, sig_handler);
+
+	ret = perf_session__process_events(session, &event_ops);
+
+	if (debug_mode)
+		pr_err("Misordered timestamps: %llu\n", nr_unordered);
+
+	return ret;
+}
+
+struct script_spec {
+	struct list_head	node;
+	struct scripting_ops	*ops;
+	char			spec[0];
+};
+
+static LIST_HEAD(script_specs);
+
+static struct script_spec *script_spec__new(const char *spec,
+					    struct scripting_ops *ops)
+{
+	struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
+
+	if (s != NULL) {
+		strcpy(s->spec, spec);
+		s->ops = ops;
+	}
+
+	return s;
+}
+
+static void script_spec__delete(struct script_spec *s)
+{
+	free(s->spec);
+	free(s);
+}
+
+static void script_spec__add(struct script_spec *s)
+{
+	list_add_tail(&s->node, &script_specs);
+}
+
+static struct script_spec *script_spec__find(const char *spec)
+{
+	struct script_spec *s;
+
+	list_for_each_entry(s, &script_specs, node)
+		if (strcasecmp(s->spec, spec) == 0)
+			return s;
+	return NULL;
+}
+
+static struct script_spec *script_spec__findnew(const char *spec,
+						struct scripting_ops *ops)
+{
+	struct script_spec *s = script_spec__find(spec);
+
+	if (s)
+		return s;
+
+	s = script_spec__new(spec, ops);
+	if (!s)
+		goto out_delete_spec;
+
+	script_spec__add(s);
+
+	return s;
+
+out_delete_spec:
+	script_spec__delete(s);
+
+	return NULL;
+}
+
+int script_spec_register(const char *spec, struct scripting_ops *ops)
+{
+	struct script_spec *s;
+
+	s = script_spec__find(spec);
+	if (s)
+		return -1;
+
+	s = script_spec__findnew(spec, ops);
+	if (!s)
+		return -1;
+
+	return 0;
+}
+
+static struct scripting_ops *script_spec__lookup(const char *spec)
+{
+	struct script_spec *s = script_spec__find(spec);
+	if (!s)
+		return NULL;
+
+	return s->ops;
+}
+
+static void list_available_languages(void)
+{
+	struct script_spec *s;
+
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Scripting language extensions (used in "
+		"perf script -s [spec:]script.[spec]):\n\n");
+
+	list_for_each_entry(s, &script_specs, node)
+		fprintf(stderr, "  %-42s [%s]\n", s->spec, s->ops->name);
+
+	fprintf(stderr, "\n");
+}
+
+static int parse_scriptname(const struct option *opt __used,
+			    const char *str, int unset __used)
+{
+	char spec[PATH_MAX];
+	const char *script, *ext;
+	int len;
+
+	if (strcmp(str, "lang") == 0) {
+		list_available_languages();
+		exit(0);
+	}
+
+	script = strchr(str, ':');
+	if (script) {
+		len = script - str;
+		if (len >= PATH_MAX) {
+			fprintf(stderr, "invalid language specifier");
+			return -1;
+		}
+		strncpy(spec, str, len);
+		spec[len] = '\0';
+		scripting_ops = script_spec__lookup(spec);
+		if (!scripting_ops) {
+			fprintf(stderr, "invalid language specifier");
+			return -1;
+		}
+		script++;
+	} else {
+		script = str;
+		ext = strrchr(script, '.');
+		if (!ext) {
+			fprintf(stderr, "invalid script extension");
+			return -1;
+		}
+		scripting_ops = script_spec__lookup(++ext);
+		if (!scripting_ops) {
+			fprintf(stderr, "invalid script extension");
+			return -1;
+		}
+	}
+
+	script_name = strdup(script);
+
+	return 0;
+}
+
+/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
+static int is_directory(const char *base_path, const struct dirent *dent)
+{
+	char path[PATH_MAX];
+	struct stat st;
+
+	sprintf(path, "%s/%s", base_path, dent->d_name);
+	if (stat(path, &st))
+		return 0;
+
+	return S_ISDIR(st.st_mode);
+}
+
+#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\
+	while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) &&	\
+	       lang_next)						\
+		if ((lang_dirent.d_type == DT_DIR ||			\
+		     (lang_dirent.d_type == DT_UNKNOWN &&		\
+		      is_directory(scripts_path, &lang_dirent))) &&	\
+		    (strcmp(lang_dirent.d_name, ".")) &&		\
+		    (strcmp(lang_dirent.d_name, "..")))
+
+#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\
+	while (!readdir_r(lang_dir, &script_dirent, &script_next) &&	\
+	       script_next)						\
+		if (script_dirent.d_type != DT_DIR &&			\
+		    (script_dirent.d_type != DT_UNKNOWN ||		\
+		     !is_directory(lang_path, &script_dirent)))
+
+
+#define RECORD_SUFFIX			"-record"
+#define REPORT_SUFFIX			"-report"
+
+struct script_desc {
+	struct list_head	node;
+	char			*name;
+	char			*half_liner;
+	char			*args;
+};
+
+static LIST_HEAD(script_descs);
+
+static struct script_desc *script_desc__new(const char *name)
+{
+	struct script_desc *s = zalloc(sizeof(*s));
+
+	if (s != NULL && name)
+		s->name = strdup(name);
+
+	return s;
+}
+
+static void script_desc__delete(struct script_desc *s)
+{
+	free(s->name);
+	free(s->half_liner);
+	free(s->args);
+	free(s);
+}
+
+static void script_desc__add(struct script_desc *s)
+{
+	list_add_tail(&s->node, &script_descs);
+}
+
+static struct script_desc *script_desc__find(const char *name)
+{
+	struct script_desc *s;
+
+	list_for_each_entry(s, &script_descs, node)
+		if (strcasecmp(s->name, name) == 0)
+			return s;
+	return NULL;
+}
+
+static struct script_desc *script_desc__findnew(const char *name)
+{
+	struct script_desc *s = script_desc__find(name);
+
+	if (s)
+		return s;
+
+	s = script_desc__new(name);
+	if (!s)
+		goto out_delete_desc;
+
+	script_desc__add(s);
+
+	return s;
+
+out_delete_desc:
+	script_desc__delete(s);
+
+	return NULL;
+}
+
+static const char *ends_with(const char *str, const char *suffix)
+{
+	size_t suffix_len = strlen(suffix);
+	const char *p = str;
+
+	if (strlen(str) > suffix_len) {
+		p = str + strlen(str) - suffix_len;
+		if (!strncmp(p, suffix, suffix_len))
+			return p;
+	}
+
+	return NULL;
+}
+
+static char *ltrim(char *str)
+{
+	int len = strlen(str);
+
+	while (len && isspace(*str)) {
+		len--;
+		str++;
+	}
+
+	return str;
+}
+
+static int read_script_info(struct script_desc *desc, const char *filename)
+{
+	char line[BUFSIZ], *p;
+	FILE *fp;
+
+	fp = fopen(filename, "r");
+	if (!fp)
+		return -1;
+
+	while (fgets(line, sizeof(line), fp)) {
+		p = ltrim(line);
+		if (strlen(p) == 0)
+			continue;
+		if (*p != '#')
+			continue;
+		p++;
+		if (strlen(p) && *p == '!')
+			continue;
+
+		p = ltrim(p);
+		if (strlen(p) && p[strlen(p) - 1] == '\n')
+			p[strlen(p) - 1] = '\0';
+
+		if (!strncmp(p, "description:", strlen("description:"))) {
+			p += strlen("description:");
+			desc->half_liner = strdup(ltrim(p));
+			continue;
+		}
+
+		if (!strncmp(p, "args:", strlen("args:"))) {
+			p += strlen("args:");
+			desc->args = strdup(ltrim(p));
+			continue;
+		}
+	}
+
+	fclose(fp);
+
+	return 0;
+}
+
+static int list_available_scripts(const struct option *opt __used,
+				  const char *s __used, int unset __used)
+{
+	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+	char scripts_path[MAXPATHLEN];
+	DIR *scripts_dir, *lang_dir;
+	char script_path[MAXPATHLEN];
+	char lang_path[MAXPATHLEN];
+	struct script_desc *desc;
+	char first_half[BUFSIZ];
+	char *script_root;
+	char *str;
+
+	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+
+	scripts_dir = opendir(scripts_path);
+	if (!scripts_dir)
+		return -1;
+
+	for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
+		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
+			 lang_dirent.d_name);
+		lang_dir = opendir(lang_path);
+		if (!lang_dir)
+			continue;
+
+		for_each_script(lang_path, lang_dir, script_dirent, script_next) {
+			script_root = strdup(script_dirent.d_name);
+			str = (char *)ends_with(script_root, REPORT_SUFFIX);
+			if (str) {
+				*str = '\0';
+				desc = script_desc__findnew(script_root);
+				snprintf(script_path, MAXPATHLEN, "%s/%s",
+					 lang_path, script_dirent.d_name);
+				read_script_info(desc, script_path);
+			}
+			free(script_root);
+		}
+	}
+
+	fprintf(stdout, "List of available trace scripts:\n");
+	list_for_each_entry(desc, &script_descs, node) {
+		sprintf(first_half, "%s %s", desc->name,
+			desc->args ? desc->args : "");
+		fprintf(stdout, "  %-36s %s\n", first_half,
+			desc->half_liner ? desc->half_liner : "");
+	}
+
+	exit(0);
+}
+
+static char *get_script_path(const char *script_root, const char *suffix)
+{
+	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+	char scripts_path[MAXPATHLEN];
+	char script_path[MAXPATHLEN];
+	DIR *scripts_dir, *lang_dir;
+	char lang_path[MAXPATHLEN];
+	char *str, *__script_root;
+	char *path = NULL;
+
+	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+
+	scripts_dir = opendir(scripts_path);
+	if (!scripts_dir)
+		return NULL;
+
+	for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
+		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
+			 lang_dirent.d_name);
+		lang_dir = opendir(lang_path);
+		if (!lang_dir)
+			continue;
+
+		for_each_script(lang_path, lang_dir, script_dirent, script_next) {
+			__script_root = strdup(script_dirent.d_name);
+			str = (char *)ends_with(__script_root, suffix);
+			if (str) {
+				*str = '\0';
+				if (strcmp(__script_root, script_root))
+					continue;
+				snprintf(script_path, MAXPATHLEN, "%s/%s",
+					 lang_path, script_dirent.d_name);
+				path = strdup(script_path);
+				free(__script_root);
+				break;
+			}
+			free(__script_root);
+		}
+	}
+
+	return path;
+}
+
+static bool is_top_script(const char *script_path)
+{
+	return ends_with(script_path, "top") == NULL ? false : true;
+}
+
+static int has_required_arg(char *script_path)
+{
+	struct script_desc *desc;
+	int n_args = 0;
+	char *p;
+
+	desc = script_desc__new(NULL);
+
+	if (read_script_info(desc, script_path))
+		goto out;
+
+	if (!desc->args)
+		goto out;
+
+	for (p = desc->args; *p; p++)
+		if (*p == '<')
+			n_args++;
+out:
+	script_desc__delete(desc);
+
+	return n_args;
+}
+
+static const char * const script_usage[] = {
+	"perf script [<options>]",
+	"perf script [<options>] record <script> [<record-options>] <command>",
+	"perf script [<options>] report <script> [script-args]",
+	"perf script [<options>] <script> [<record-options>] <command>",
+	"perf script [<options>] <top-script> [script-args]",
+	NULL
+};
+
+static const struct option options[] = {
+	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
+		    "dump raw trace in ASCII"),
+	OPT_INCR('v', "verbose", &verbose,
+		    "be more verbose (show symbol address, etc)"),
+	OPT_BOOLEAN('L', "Latency", &latency_format,
+		    "show latency attributes (irqs/preemption disabled, etc)"),
+	OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
+			   list_available_scripts),
+	OPT_CALLBACK('s', "script", NULL, "name",
+		     "script file name (lang:script name, script name, or *)",
+		     parse_scriptname),
+	OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
+		   "generate perf-script.xx script in specified language"),
+	OPT_STRING('i', "input", &input_name, "file",
+		    "input file name"),
+	OPT_BOOLEAN('d', "debug-mode", &debug_mode,
+		   "do various checks like samples ordering and lost events"),
+
+	OPT_END()
+};
+
+static bool have_cmd(int argc, const char **argv)
+{
+	char **__argv = malloc(sizeof(const char *) * argc);
+
+	if (!__argv)
+		die("malloc");
+	memcpy(__argv, argv, sizeof(const char *) * argc);
+	argc = parse_options(argc, (const char **)__argv, record_options,
+			     NULL, PARSE_OPT_STOP_AT_NON_OPTION);
+	free(__argv);
+
+	return argc != 0;
+}
+
+int cmd_script(int argc, const char **argv, const char *prefix __used)
+{
+	char *rec_script_path = NULL;
+	char *rep_script_path = NULL;
+	struct perf_session *session;
+	char *script_path = NULL;
+	const char **__argv;
+	bool system_wide;
+	int i, j, err;
+
+	setup_scripting();
+
+	argc = parse_options(argc, argv, options, script_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
+		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
+		if (!rec_script_path)
+			return cmd_record(argc, argv, NULL);
+	}
+
+	if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
+		rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
+		if (!rep_script_path) {
+			fprintf(stderr,
+				"Please specify a valid report script"
+				"(see 'perf script -l' for listing)\n");
+			return -1;
+		}
+	}
+
+	/* make sure PERF_EXEC_PATH is set for scripts */
+	perf_set_argv_exec_path(perf_exec_path());
+
+	if (argc && !script_name && !rec_script_path && !rep_script_path) {
+		int live_pipe[2];
+		int rep_args;
+		pid_t pid;
+
+		rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
+		rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
+
+		if (!rec_script_path && !rep_script_path) {
+			fprintf(stderr, " Couldn't find script %s\n\n See perf"
+				" script -l for available scripts.\n", argv[0]);
+			usage_with_options(script_usage, options);
+		}
+
+		if (is_top_script(argv[0])) {
+			rep_args = argc - 1;
+		} else {
+			int rec_args;
+
+			rep_args = has_required_arg(rep_script_path);
+			rec_args = (argc - 1) - rep_args;
+			if (rec_args < 0) {
+				fprintf(stderr, " %s script requires options."
+					"\n\n See perf script -l for available "
+					"scripts and options.\n", argv[0]);
+				usage_with_options(script_usage, options);
+			}
+		}
+
+		if (pipe(live_pipe) < 0) {
+			perror("failed to create pipe");
+			exit(-1);
+		}
+
+		pid = fork();
+		if (pid < 0) {
+			perror("failed to fork");
+			exit(-1);
+		}
+
+		if (!pid) {
+			system_wide = true;
+			j = 0;
+
+			dup2(live_pipe[1], 1);
+			close(live_pipe[0]);
+
+			if (!is_top_script(argv[0]))
+				system_wide = !have_cmd(argc - rep_args,
+							&argv[rep_args]);
+
+			__argv = malloc((argc + 6) * sizeof(const char *));
+			if (!__argv)
+				die("malloc");
+
+			__argv[j++] = "/bin/sh";
+			__argv[j++] = rec_script_path;
+			if (system_wide)
+				__argv[j++] = "-a";
+			__argv[j++] = "-q";
+			__argv[j++] = "-o";
+			__argv[j++] = "-";
+			for (i = rep_args + 1; i < argc; i++)
+				__argv[j++] = argv[i];
+			__argv[j++] = NULL;
+
+			execvp("/bin/sh", (char **)__argv);
+			free(__argv);
+			exit(-1);
+		}
+
+		dup2(live_pipe[0], 0);
+		close(live_pipe[1]);
+
+		__argv = malloc((argc + 4) * sizeof(const char *));
+		if (!__argv)
+			die("malloc");
+		j = 0;
+		__argv[j++] = "/bin/sh";
+		__argv[j++] = rep_script_path;
+		for (i = 1; i < rep_args + 1; i++)
+			__argv[j++] = argv[i];
+		__argv[j++] = "-i";
+		__argv[j++] = "-";
+		__argv[j++] = NULL;
+
+		execvp("/bin/sh", (char **)__argv);
+		free(__argv);
+		exit(-1);
+	}
+
+	if (rec_script_path)
+		script_path = rec_script_path;
+	if (rep_script_path)
+		script_path = rep_script_path;
+
+	if (script_path) {
+		system_wide = false;
+		j = 0;
+
+		if (rec_script_path)
+			system_wide = !have_cmd(argc - 1, &argv[1]);
+
+		__argv = malloc((argc + 2) * sizeof(const char *));
+		if (!__argv)
+			die("malloc");
+		__argv[j++] = "/bin/sh";
+		__argv[j++] = script_path;
+		if (system_wide)
+			__argv[j++] = "-a";
+		for (i = 2; i < argc; i++)
+			__argv[j++] = argv[i];
+		__argv[j++] = NULL;
+
+		execvp("/bin/sh", (char **)__argv);
+		free(__argv);
+		exit(-1);
+	}
+
+	if (symbol__init() < 0)
+		return -1;
+	if (!script_name)
+		setup_pager();
+
+	session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
+	if (session == NULL)
+		return -ENOMEM;
+
+	if (strcmp(input_name, "-") &&
+	    !perf_session__has_traces(session, "record -R"))
+		return -EINVAL;
+
+	if (generate_script_lang) {
+		struct stat perf_stat;
+
+		int input = open(input_name, O_RDONLY);
+		if (input < 0) {
+			perror("failed to open file");
+			exit(-1);
+		}
+
+		err = fstat(input, &perf_stat);
+		if (err < 0) {
+			perror("failed to stat file");
+			exit(-1);
+		}
+
+		if (!perf_stat.st_size) {
+			fprintf(stderr, "zero-sized file, nothing to do!\n");
+			exit(0);
+		}
+
+		scripting_ops = script_spec__lookup(generate_script_lang);
+		if (!scripting_ops) {
+			fprintf(stderr, "invalid language specifier");
+			return -1;
+		}
+
+		err = scripting_ops->generate_script("perf-script");
+		goto out;
+	}
+
+	if (script_name) {
+		err = scripting_ops->start_script(script_name, argc, argv);
+		if (err)
+			goto out;
+		pr_debug("perf script started with script %s\n\n", script_name);
+	}
+
+	err = __cmd_script(session);
+
+	perf_session__delete(session);
+	cleanup_scripting();
+out:
+	return err;
+}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a6b4d44..02b2d80 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,6 +43,7 @@
 #include "util/parse-options.h"
 #include "util/parse-events.h"
 #include "util/event.h"
+#include "util/evsel.h"
 #include "util/debug.h"
 #include "util/header.h"
 #include "util/cpumap.h"
@@ -52,6 +53,8 @@
 #include <math.h>
 #include <locale.h>
 
+#define DEFAULT_SEPARATOR	" "
+
 static struct perf_event_attr default_attrs[] = {
 
   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},
@@ -69,25 +72,23 @@
 };
 
 static bool			system_wide			=  false;
-static int			nr_cpus				=  0;
+static struct cpu_map		*cpus;
 static int			run_idx				=  0;
 
 static int			run_count			=  1;
 static bool			no_inherit			= false;
 static bool			scale				=  true;
+static bool			no_aggr				= false;
 static pid_t			target_pid			= -1;
 static pid_t			target_tid			= -1;
-static pid_t			*all_tids			=  NULL;
-static int			thread_num			=  0;
+static struct thread_map	*threads;
 static pid_t			child_pid			= -1;
 static bool			null_run			=  false;
-static bool			big_num				=  false;
+static bool			big_num				=  true;
+static int			big_num_opt			=  -1;
 static const char		*cpu_list;
-
-
-static int			*fd[MAX_NR_CPUS][MAX_COUNTERS];
-
-static int			event_scaled[MAX_COUNTERS];
+static const char		*csv_sep			= NULL;
+static bool			csv_output			= false;
 
 static volatile int done = 0;
 
@@ -96,6 +97,22 @@
 	double n, mean, M2;
 };
 
+struct perf_stat {
+	struct stats	  res_stats[3];
+};
+
+static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
+{
+	evsel->priv = zalloc(sizeof(struct perf_stat));
+	return evsel->priv == NULL ? -ENOMEM : 0;
+}
+
+static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
+{
+	free(evsel->priv);
+	evsel->priv = NULL;
+}
+
 static void update_stats(struct stats *stats, u64 val)
 {
 	double delta;
@@ -135,69 +152,38 @@
 	return sqrt(variance_mean);
 }
 
-struct stats			event_res_stats[MAX_COUNTERS][3];
-struct stats			runtime_nsecs_stats;
+struct stats			runtime_nsecs_stats[MAX_NR_CPUS];
+struct stats			runtime_cycles_stats[MAX_NR_CPUS];
+struct stats			runtime_branches_stats[MAX_NR_CPUS];
 struct stats			walltime_nsecs_stats;
-struct stats			runtime_cycles_stats;
-struct stats			runtime_branches_stats;
 
-#define MATCH_EVENT(t, c, counter)			\
-	(attrs[counter].type == PERF_TYPE_##t &&	\
-	 attrs[counter].config == PERF_COUNT_##c)
-
-#define ERR_PERF_OPEN \
-"Error: counter %d, sys_perf_event_open() syscall returned with %d (%s)\n"
-
-static int create_perf_stat_counter(int counter)
+static int create_perf_stat_counter(struct perf_evsel *evsel)
 {
-	struct perf_event_attr *attr = attrs + counter;
-	int thread;
-	int ncreated = 0;
+	struct perf_event_attr *attr = &evsel->attr;
 
 	if (scale)
 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
 
-	if (system_wide) {
-		int cpu;
+	if (system_wide)
+		return perf_evsel__open_per_cpu(evsel, cpus);
 
-		for (cpu = 0; cpu < nr_cpus; cpu++) {
-			fd[cpu][counter][0] = sys_perf_event_open(attr,
-					-1, cpumap[cpu], -1, 0);
-			if (fd[cpu][counter][0] < 0)
-				pr_debug(ERR_PERF_OPEN, counter,
-					 fd[cpu][counter][0], strerror(errno));
-			else
-				++ncreated;
-		}
-	} else {
-		attr->inherit = !no_inherit;
-		if (target_pid == -1 && target_tid == -1) {
-			attr->disabled = 1;
-			attr->enable_on_exec = 1;
-		}
-		for (thread = 0; thread < thread_num; thread++) {
-			fd[0][counter][thread] = sys_perf_event_open(attr,
-				all_tids[thread], -1, -1, 0);
-			if (fd[0][counter][thread] < 0)
-				pr_debug(ERR_PERF_OPEN, counter,
-					 fd[0][counter][thread],
-					 strerror(errno));
-			else
-				++ncreated;
-		}
+	attr->inherit = !no_inherit;
+	if (target_pid == -1 && target_tid == -1) {
+		attr->disabled = 1;
+		attr->enable_on_exec = 1;
 	}
 
-	return ncreated;
+	return perf_evsel__open_per_thread(evsel, threads);
 }
 
 /*
  * Does the counter have nsecs as a unit?
  */
-static inline int nsec_counter(int counter)
+static inline int nsec_counter(struct perf_evsel *evsel)
 {
-	if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) ||
-	    MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
+	if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
+	    perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
 		return 1;
 
 	return 0;
@@ -205,55 +191,19 @@
 
 /*
  * Read out the results of a single counter:
+ * aggregate counts across CPUs in system-wide mode
  */
-static void read_counter(int counter)
+static int read_counter_aggr(struct perf_evsel *counter)
 {
-	u64 count[3], single_count[3];
-	int cpu;
-	size_t res, nv;
-	int scaled;
-	int i, thread;
+	struct perf_stat *ps = counter->priv;
+	u64 *count = counter->counts->aggr.values;
+	int i;
 
-	count[0] = count[1] = count[2] = 0;
-
-	nv = scale ? 3 : 1;
-	for (cpu = 0; cpu < nr_cpus; cpu++) {
-		for (thread = 0; thread < thread_num; thread++) {
-			if (fd[cpu][counter][thread] < 0)
-				continue;
-
-			res = read(fd[cpu][counter][thread],
-					single_count, nv * sizeof(u64));
-			assert(res == nv * sizeof(u64));
-
-			close(fd[cpu][counter][thread]);
-			fd[cpu][counter][thread] = -1;
-
-			count[0] += single_count[0];
-			if (scale) {
-				count[1] += single_count[1];
-				count[2] += single_count[2];
-			}
-		}
-	}
-
-	scaled = 0;
-	if (scale) {
-		if (count[2] == 0) {
-			event_scaled[counter] = -1;
-			count[0] = 0;
-			return;
-		}
-
-		if (count[2] < count[1]) {
-			event_scaled[counter] = 1;
-			count[0] = (unsigned long long)
-				((double)count[0] * count[1] / count[2] + 0.5);
-		}
-	}
+	if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0)
+		return -1;
 
 	for (i = 0; i < 3; i++)
-		update_stats(&event_res_stats[counter][i], count[i]);
+		update_stats(&ps->res_stats[i], count[i]);
 
 	if (verbose) {
 		fprintf(stderr, "%s: %Ld %Ld %Ld\n", event_name(counter),
@@ -263,26 +213,51 @@
 	/*
 	 * Save the full runtime - to allow normalization during printout:
 	 */
-	if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
-		update_stats(&runtime_nsecs_stats, count[0]);
-	if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
-		update_stats(&runtime_cycles_stats, count[0]);
-	if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter))
-		update_stats(&runtime_branches_stats, count[0]);
+	if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
+		update_stats(&runtime_nsecs_stats[0], count[0]);
+	if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
+		update_stats(&runtime_cycles_stats[0], count[0]);
+	if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
+		update_stats(&runtime_branches_stats[0], count[0]);
+
+	return 0;
+}
+
+/*
+ * Read out the results of a single counter:
+ * do not aggregate counts across CPUs in system-wide mode
+ */
+static int read_counter(struct perf_evsel *counter)
+{
+	u64 *count;
+	int cpu;
+
+	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
+			return -1;
+
+		count = counter->counts->cpu[cpu].values;
+
+		if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
+			update_stats(&runtime_nsecs_stats[cpu], count[0]);
+		if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
+			update_stats(&runtime_cycles_stats[cpu], count[0]);
+		if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
+			update_stats(&runtime_branches_stats[cpu], count[0]);
+	}
+
+	return 0;
 }
 
 static int run_perf_stat(int argc __used, const char **argv)
 {
 	unsigned long long t0, t1;
+	struct perf_evsel *counter;
 	int status = 0;
-	int counter, ncreated = 0;
 	int child_ready_pipe[2], go_pipe[2];
 	const bool forks = (argc > 0);
 	char buf;
 
-	if (!system_wide)
-		nr_cpus = 1;
-
 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
 		perror("failed to create pipes");
 		exit(1);
@@ -322,7 +297,7 @@
 		}
 
 		if (target_tid == -1 && target_pid == -1 && !system_wide)
-			all_tids[0] = child_pid;
+			threads->map[0] = child_pid;
 
 		/*
 		 * Wait for the child to be ready to exec.
@@ -334,16 +309,23 @@
 		close(child_ready_pipe[0]);
 	}
 
-	for (counter = 0; counter < nr_counters; counter++)
-		ncreated += create_perf_stat_counter(counter);
-
-	if (ncreated == 0) {
-		pr_err("No permission to collect %sstats.\n"
-		       "Consider tweaking /proc/sys/kernel/perf_event_paranoid.\n",
-		       system_wide ? "system-wide " : "");
-		if (child_pid != -1)
-			kill(child_pid, SIGTERM);
-		return -1;
+	list_for_each_entry(counter, &evsel_list, node) {
+		if (create_perf_stat_counter(counter) < 0) {
+			if (errno == -EPERM || errno == -EACCES) {
+				error("You may not have permission to collect %sstats.\n"
+				      "\t Consider tweaking"
+				      " /proc/sys/kernel/perf_event_paranoid or running as root.",
+				      system_wide ? "system-wide " : "");
+			} else {
+				error("open_counter returned with %d (%s). "
+				      "/bin/dmesg may provide additional information.\n",
+				       errno, strerror(errno));
+			}
+			if (child_pid != -1)
+				kill(child_pid, SIGTERM);
+			die("Not all events could be opened.\n");
+			return -1;
+		}
 	}
 
 	/*
@@ -362,60 +344,97 @@
 
 	update_stats(&walltime_nsecs_stats, t1 - t0);
 
-	for (counter = 0; counter < nr_counters; counter++)
-		read_counter(counter);
+	if (no_aggr) {
+		list_for_each_entry(counter, &evsel_list, node) {
+			read_counter(counter);
+			perf_evsel__close_fd(counter, cpus->nr, 1);
+		}
+	} else {
+		list_for_each_entry(counter, &evsel_list, node) {
+			read_counter_aggr(counter);
+			perf_evsel__close_fd(counter, cpus->nr, threads->nr);
+		}
+	}
 
 	return WEXITSTATUS(status);
 }
 
-static void print_noise(int counter, double avg)
+static void print_noise(struct perf_evsel *evsel, double avg)
 {
+	struct perf_stat *ps;
+
 	if (run_count == 1)
 		return;
 
+	ps = evsel->priv;
 	fprintf(stderr, "   ( +- %7.3f%% )",
-			100 * stddev_stats(&event_res_stats[counter][0]) / avg);
+			100 * stddev_stats(&ps->res_stats[0]) / avg);
 }
 
-static void nsec_printout(int counter, double avg)
+static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
 {
 	double msecs = avg / 1e6;
+	char cpustr[16] = { '\0', };
+	const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s";
 
-	fprintf(stderr, " %18.6f  %-24s", msecs, event_name(counter));
+	if (no_aggr)
+		sprintf(cpustr, "CPU%*d%s",
+			csv_output ? 0 : -4,
+			cpus->map[cpu], csv_sep);
 
-	if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
+	fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
+
+	if (csv_output)
+		return;
+
+	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
 		fprintf(stderr, " # %10.3f CPUs ",
 				avg / avg_stats(&walltime_nsecs_stats));
-	}
 }
 
-static void abs_printout(int counter, double avg)
+static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
 {
 	double total, ratio = 0.0;
+	char cpustr[16] = { '\0', };
+	const char *fmt;
 
-	if (big_num)
-		fprintf(stderr, " %'18.0f  %-24s", avg, event_name(counter));
+	if (csv_output)
+		fmt = "%s%.0f%s%s";
+	else if (big_num)
+		fmt = "%s%'18.0f%s%-24s";
 	else
-		fprintf(stderr, " %18.0f  %-24s", avg, event_name(counter));
+		fmt = "%s%18.0f%s%-24s";
 
-	if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
-		total = avg_stats(&runtime_cycles_stats);
+	if (no_aggr)
+		sprintf(cpustr, "CPU%*d%s",
+			csv_output ? 0 : -4,
+			cpus->map[cpu], csv_sep);
+	else
+		cpu = 0;
+
+	fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
+
+	if (csv_output)
+		return;
+
+	if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
+		total = avg_stats(&runtime_cycles_stats[cpu]);
 
 		if (total)
 			ratio = avg / total;
 
 		fprintf(stderr, " # %10.3f IPC  ", ratio);
-	} else if (MATCH_EVENT(HARDWARE, HW_BRANCH_MISSES, counter) &&
-			runtime_branches_stats.n != 0) {
-		total = avg_stats(&runtime_branches_stats);
+	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
+			runtime_branches_stats[cpu].n != 0) {
+		total = avg_stats(&runtime_branches_stats[cpu]);
 
 		if (total)
 			ratio = avg * 100 / total;
 
 		fprintf(stderr, " # %10.3f %%    ", ratio);
 
-	} else if (runtime_nsecs_stats.n != 0) {
-		total = avg_stats(&runtime_nsecs_stats);
+	} else if (runtime_nsecs_stats[cpu].n != 0) {
+		total = avg_stats(&runtime_nsecs_stats[cpu]);
 
 		if (total)
 			ratio = 1000.0 * avg / total;
@@ -426,30 +445,38 @@
 
 /*
  * Print out the results of a single counter:
+ * aggregated counts in system-wide mode
  */
-static void print_counter(int counter)
+static void print_counter_aggr(struct perf_evsel *counter)
 {
-	double avg = avg_stats(&event_res_stats[counter][0]);
-	int scaled = event_scaled[counter];
+	struct perf_stat *ps = counter->priv;
+	double avg = avg_stats(&ps->res_stats[0]);
+	int scaled = counter->counts->scaled;
 
 	if (scaled == -1) {
-		fprintf(stderr, " %18s  %-24s\n",
-			"<not counted>", event_name(counter));
+		fprintf(stderr, "%*s%s%-24s\n",
+			csv_output ? 0 : 18,
+			"<not counted>", csv_sep, event_name(counter));
 		return;
 	}
 
 	if (nsec_counter(counter))
-		nsec_printout(counter, avg);
+		nsec_printout(-1, counter, avg);
 	else
-		abs_printout(counter, avg);
+		abs_printout(-1, counter, avg);
+
+	if (csv_output) {
+		fputc('\n', stderr);
+		return;
+	}
 
 	print_noise(counter, avg);
 
 	if (scaled) {
 		double avg_enabled, avg_running;
 
-		avg_enabled = avg_stats(&event_res_stats[counter][1]);
-		avg_running = avg_stats(&event_res_stats[counter][2]);
+		avg_enabled = avg_stats(&ps->res_stats[1]);
+		avg_running = avg_stats(&ps->res_stats[2]);
 
 		fprintf(stderr, "  (scaled from %.2f%%)",
 				100 * avg_running / avg_enabled);
@@ -458,40 +485,92 @@
 	fprintf(stderr, "\n");
 }
 
+/*
+ * Print out the results of a single counter:
+ * does not use aggregated count in system-wide
+ */
+static void print_counter(struct perf_evsel *counter)
+{
+	u64 ena, run, val;
+	int cpu;
+
+	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		val = counter->counts->cpu[cpu].val;
+		ena = counter->counts->cpu[cpu].ena;
+		run = counter->counts->cpu[cpu].run;
+		if (run == 0 || ena == 0) {
+			fprintf(stderr, "CPU%*d%s%*s%s%-24s",
+				csv_output ? 0 : -4,
+				cpus->map[cpu], csv_sep,
+				csv_output ? 0 : 18,
+				"<not counted>", csv_sep,
+				event_name(counter));
+
+			fprintf(stderr, "\n");
+			continue;
+		}
+
+		if (nsec_counter(counter))
+			nsec_printout(cpu, counter, val);
+		else
+			abs_printout(cpu, counter, val);
+
+		if (!csv_output) {
+			print_noise(counter, 1.0);
+
+			if (run != ena) {
+				fprintf(stderr, "  (scaled from %.2f%%)",
+					100.0 * run / ena);
+			}
+		}
+		fprintf(stderr, "\n");
+	}
+}
+
 static void print_stat(int argc, const char **argv)
 {
-	int i, counter;
+	struct perf_evsel *counter;
+	int i;
 
 	fflush(stdout);
 
-	fprintf(stderr, "\n");
-	fprintf(stderr, " Performance counter stats for ");
-	if(target_pid == -1 && target_tid == -1) {
-		fprintf(stderr, "\'%s", argv[0]);
-		for (i = 1; i < argc; i++)
-			fprintf(stderr, " %s", argv[i]);
-	} else if (target_pid != -1)
-		fprintf(stderr, "process id \'%d", target_pid);
-	else
-		fprintf(stderr, "thread id \'%d", target_tid);
+	if (!csv_output) {
+		fprintf(stderr, "\n");
+		fprintf(stderr, " Performance counter stats for ");
+		if(target_pid == -1 && target_tid == -1) {
+			fprintf(stderr, "\'%s", argv[0]);
+			for (i = 1; i < argc; i++)
+				fprintf(stderr, " %s", argv[i]);
+		} else if (target_pid != -1)
+			fprintf(stderr, "process id \'%d", target_pid);
+		else
+			fprintf(stderr, "thread id \'%d", target_tid);
 
-	fprintf(stderr, "\'");
-	if (run_count > 1)
-		fprintf(stderr, " (%d runs)", run_count);
-	fprintf(stderr, ":\n\n");
+		fprintf(stderr, "\'");
+		if (run_count > 1)
+			fprintf(stderr, " (%d runs)", run_count);
+		fprintf(stderr, ":\n\n");
+	}
 
-	for (counter = 0; counter < nr_counters; counter++)
-		print_counter(counter);
+	if (no_aggr) {
+		list_for_each_entry(counter, &evsel_list, node)
+			print_counter(counter);
+	} else {
+		list_for_each_entry(counter, &evsel_list, node)
+			print_counter_aggr(counter);
+	}
 
-	fprintf(stderr, "\n");
-	fprintf(stderr, " %18.9f  seconds time elapsed",
-			avg_stats(&walltime_nsecs_stats)/1e9);
-	if (run_count > 1) {
-		fprintf(stderr, "   ( +- %7.3f%% )",
+	if (!csv_output) {
+		fprintf(stderr, "\n");
+		fprintf(stderr, " %18.9f  seconds time elapsed",
+				avg_stats(&walltime_nsecs_stats)/1e9);
+		if (run_count > 1) {
+			fprintf(stderr, "   ( +- %7.3f%% )",
 				100*stddev_stats(&walltime_nsecs_stats) /
 				avg_stats(&walltime_nsecs_stats));
+		}
+		fprintf(stderr, "\n\n");
 	}
-	fprintf(stderr, "\n\n");
 }
 
 static volatile int signr = -1;
@@ -521,6 +600,13 @@
 	NULL
 };
 
+static int stat__set_big_num(const struct option *opt __used,
+			     const char *s __used, int unset)
+{
+	big_num_opt = unset ? 0 : 1;
+	return 0;
+}
+
 static const struct option options[] = {
 	OPT_CALLBACK('e', "event", NULL, "event",
 		     "event selector. use 'perf list' to list available events",
@@ -541,64 +627,96 @@
 		    "repeat command and print average + stddev (max: 100)"),
 	OPT_BOOLEAN('n', "null", &null_run,
 		    "null run - dont start any counters"),
-	OPT_BOOLEAN('B', "big-num", &big_num,
-		    "print large numbers with thousands\' separators"),
+	OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 
+			   "print large numbers with thousands\' separators",
+			   stat__set_big_num),
 	OPT_STRING('C', "cpu", &cpu_list, "cpu",
 		    "list of cpus to monitor in system-wide"),
+	OPT_BOOLEAN('A', "no-aggr", &no_aggr,
+		    "disable CPU count aggregation"),
+	OPT_STRING('x', "field-separator", &csv_sep, "separator",
+		   "print counts with custom separator"),
 	OPT_END()
 };
 
 int cmd_stat(int argc, const char **argv, const char *prefix __used)
 {
-	int status;
-	int i,j;
+	struct perf_evsel *pos;
+	int status = -ENOMEM;
 
 	setlocale(LC_ALL, "");
 
 	argc = parse_options(argc, argv, options, stat_usage,
 		PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (csv_sep)
+		csv_output = true;
+	else
+		csv_sep = DEFAULT_SEPARATOR;
+
+	/*
+	 * let the spreadsheet do the pretty-printing
+	 */
+	if (csv_output) {
+		/* User explicitely passed -B? */
+		if (big_num_opt == 1) {
+			fprintf(stderr, "-B option not supported with -x\n");
+			usage_with_options(stat_usage, options);
+		} else /* Nope, so disable big number formatting */
+			big_num = false;
+	} else if (big_num_opt == 0) /* User passed --no-big-num */
+		big_num = false;
+
 	if (!argc && target_pid == -1 && target_tid == -1)
 		usage_with_options(stat_usage, options);
 	if (run_count <= 0)
 		usage_with_options(stat_usage, options);
 
+	/* no_aggr is for system-wide only */
+	if (no_aggr && !system_wide)
+		usage_with_options(stat_usage, options);
+
 	/* Set attrs and nr_counters if no event is selected and !null_run */
 	if (!null_run && !nr_counters) {
-		memcpy(attrs, default_attrs, sizeof(default_attrs));
+		size_t c;
+
 		nr_counters = ARRAY_SIZE(default_attrs);
+
+		for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
+			pos = perf_evsel__new(default_attrs[c].type,
+					      default_attrs[c].config,
+					      nr_counters);
+			if (pos == NULL)
+				goto out;
+			list_add(&pos->node, &evsel_list);
+		}
+	}
+
+	if (target_pid != -1)
+		target_tid = target_pid;
+
+	threads = thread_map__new(target_pid, target_tid);
+	if (threads == NULL) {
+		pr_err("Problems finding threads of monitor\n");
+		usage_with_options(stat_usage, options);
 	}
 
 	if (system_wide)
-		nr_cpus = read_cpu_map(cpu_list);
+		cpus = cpu_map__new(cpu_list);
 	else
-		nr_cpus = 1;
+		cpus = cpu_map__dummy_new();
 
-	if (nr_cpus < 1)
+	if (cpus == NULL) {
+		perror("failed to parse CPUs map");
 		usage_with_options(stat_usage, options);
-
-	if (target_pid != -1) {
-		target_tid = target_pid;
-		thread_num = find_all_tid(target_pid, &all_tids);
-		if (thread_num <= 0) {
-			fprintf(stderr, "Can't find all threads of pid %d\n",
-					target_pid);
-			usage_with_options(stat_usage, options);
-		}
-	} else {
-		all_tids=malloc(sizeof(pid_t));
-		if (!all_tids)
-			return -ENOMEM;
-
-		all_tids[0] = target_tid;
-		thread_num = 1;
+		return -1;
 	}
 
-	for (i = 0; i < MAX_NR_CPUS; i++) {
-		for (j = 0; j < MAX_COUNTERS; j++) {
-			fd[i][j] = malloc(sizeof(int)*thread_num);
-			if (!fd[i][j])
-				return -ENOMEM;
-		}
+	list_for_each_entry(pos, &evsel_list, node) {
+		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
+		    perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
+		    perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
+			goto out_free_fd;
 	}
 
 	/*
@@ -621,6 +739,11 @@
 
 	if (status != -1)
 		print_stat(argc, argv);
-
+out_free_fd:
+	list_for_each_entry(pos, &evsel_list, node)
+		perf_evsel__free_stat_priv(pos);
+out:
+	thread_map__delete(threads);
+	threads = NULL;
 	return status;
 }
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 035b9fa..1c98434 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -119,10 +119,16 @@
 	 * end addresses too.
 	 */
 	for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
-		struct symbol *pair;
+		struct symbol *pair, *first_pair;
+		bool backwards = true;
 
 		sym  = rb_entry(nd, struct symbol, rb_node);
-		pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
+
+		if (sym->start == sym->end)
+			continue;
+
+		first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
+		pair = first_pair;
 
 		if (pair && pair->start == sym->start) {
 next_pair:
@@ -143,8 +149,10 @@
 				pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n",
 					 sym->start, sym->name, sym->end, pair->end);
 			} else {
-				struct rb_node *nnd = rb_prev(&pair->rb_node);
-
+				struct rb_node *nnd;
+detour:
+				nnd = backwards ? rb_prev(&pair->rb_node) :
+						  rb_next(&pair->rb_node);
 				if (nnd) {
 					struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
 
@@ -153,6 +161,13 @@
 						goto next_pair;
 					}
 				}
+
+				if (backwards) {
+					backwards = false;
+					pair = first_pair;
+					goto detour;
+				}
+
 				pr_debug("%#Lx: diff name v: %s k: %s\n",
 					 sym->start, sym->name, pair->name);
 			}
@@ -219,6 +234,89 @@
 	return err;
 }
 
+#include "util/evsel.h"
+#include <sys/types.h>
+
+static int trace_event__id(const char *event_name)
+{
+	char *filename;
+	int err = -1, fd;
+
+	if (asprintf(&filename,
+		     "/sys/kernel/debug/tracing/events/syscalls/%s/id",
+		     event_name) < 0)
+		return -1;
+
+	fd = open(filename, O_RDONLY);
+	if (fd >= 0) {
+		char id[16];
+		if (read(fd, id, sizeof(id)) > 0)
+			err = atoi(id);
+		close(fd);
+	}
+
+	free(filename);
+	return err;
+}
+
+static int test__open_syscall_event(void)
+{
+	int err = -1, fd;
+	struct thread_map *threads;
+	struct perf_evsel *evsel;
+	unsigned int nr_open_calls = 111, i;
+	int id = trace_event__id("sys_enter_open");
+
+	if (id < 0) {
+		pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
+		return -1;
+	}
+
+	threads = thread_map__new(-1, getpid());
+	if (threads == NULL) {
+		pr_debug("thread_map__new\n");
+		return -1;
+	}
+
+	evsel = perf_evsel__new(PERF_TYPE_TRACEPOINT, id, 0);
+	if (evsel == NULL) {
+		pr_debug("perf_evsel__new\n");
+		goto out_thread_map_delete;
+	}
+
+	if (perf_evsel__open_per_thread(evsel, threads) < 0) {
+		pr_debug("failed to open counter: %s, "
+			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
+			 strerror(errno));
+		goto out_evsel_delete;
+	}
+
+	for (i = 0; i < nr_open_calls; ++i) {
+		fd = open("/etc/passwd", O_RDONLY);
+		close(fd);
+	}
+
+	if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
+		pr_debug("perf_evsel__open_read_on_cpu\n");
+		goto out_close_fd;
+	}
+
+	if (evsel->counts->cpu[0].val != nr_open_calls) {
+		pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %Ld\n",
+			 nr_open_calls, evsel->counts->cpu[0].val);
+		goto out_close_fd;
+	}
+	
+	err = 0;
+out_close_fd:
+	perf_evsel__close_fd(evsel, 1, threads->nr);
+out_evsel_delete:
+	perf_evsel__delete(evsel);
+out_thread_map_delete:
+	thread_map__delete(threads);
+	return err;
+}
+
 static struct test {
 	const char *desc;
 	int (*func)(void);
@@ -228,6 +326,10 @@
 		.func = test__vmlinux_matches_kallsyms,
 	},
 	{
+		.desc = "detect open syscall event",
+		.func = test__open_syscall_event,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 9bcc38f..746cf03 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -32,6 +32,10 @@
 #include "util/session.h"
 #include "util/svghelper.h"
 
+#define SUPPORT_OLD_POWER_EVENTS 1
+#define PWR_EVENT_EXIT -1
+
+
 static char		const *input_name = "perf.data";
 static char		const *output_name = "output.svg";
 
@@ -272,19 +276,22 @@
 static u64 cpus_pstate_start_times[MAX_CPUS];
 static u64 cpus_pstate_state[MAX_CPUS];
 
-static int process_comm_event(event_t *event, struct perf_session *session __used)
+static int process_comm_event(event_t *event, struct sample_data *sample __used,
+			      struct perf_session *session __used)
 {
 	pid_set_comm(event->comm.tid, event->comm.comm);
 	return 0;
 }
 
-static int process_fork_event(event_t *event, struct perf_session *session __used)
+static int process_fork_event(event_t *event, struct sample_data *sample __used,
+			      struct perf_session *session __used)
 {
 	pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
 	return 0;
 }
 
-static int process_exit_event(event_t *event, struct perf_session *session __used)
+static int process_exit_event(event_t *event, struct sample_data *sample __used,
+			      struct perf_session *session __used)
 {
 	pid_exit(event->fork.pid, event->fork.time);
 	return 0;
@@ -298,12 +305,21 @@
 	int			lock_depth;
 };
 
-struct power_entry {
+#ifdef SUPPORT_OLD_POWER_EVENTS
+static int use_old_power_events;
+struct power_entry_old {
 	struct trace_entry te;
 	u64	type;
 	u64	value;
 	u64	cpu_id;
 };
+#endif
+
+struct power_processor_entry {
+	struct trace_entry te;
+	u32	state;
+	u32	cpu_id;
+};
 
 #define TASK_COMM_LEN 16
 struct wakeup_entry {
@@ -470,48 +486,65 @@
 }
 
 
-static int process_sample_event(event_t *event, struct perf_session *session)
+static int process_sample_event(event_t *event __used,
+				struct sample_data *sample,
+				struct perf_session *session)
 {
-	struct sample_data data;
 	struct trace_entry *te;
 
-	memset(&data, 0, sizeof(data));
-
-	event__parse_sample(event, session->sample_type, &data);
-
 	if (session->sample_type & PERF_SAMPLE_TIME) {
-		if (!first_time || first_time > data.time)
-			first_time = data.time;
-		if (last_time < data.time)
-			last_time = data.time;
+		if (!first_time || first_time > sample->time)
+			first_time = sample->time;
+		if (last_time < sample->time)
+			last_time = sample->time;
 	}
 
-	te = (void *)data.raw_data;
-	if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) {
+	te = (void *)sample->raw_data;
+	if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) {
 		char *event_str;
-		struct power_entry *pe;
-
-		pe = (void *)te;
-
+#ifdef SUPPORT_OLD_POWER_EVENTS
+		struct power_entry_old *peo;
+		peo = (void *)te;
+#endif
 		event_str = perf_header__find_event(te->type);
 
 		if (!event_str)
 			return 0;
 
-		if (strcmp(event_str, "power:power_start") == 0)
-			c_state_start(pe->cpu_id, data.time, pe->value);
+		if (strcmp(event_str, "power:cpu_idle") == 0) {
+			struct power_processor_entry *ppe = (void *)te;
+			if (ppe->state == (u32)PWR_EVENT_EXIT)
+				c_state_end(ppe->cpu_id, sample->time);
+			else
+				c_state_start(ppe->cpu_id, sample->time,
+					      ppe->state);
+		}
+		else if (strcmp(event_str, "power:cpu_frequency") == 0) {
+			struct power_processor_entry *ppe = (void *)te;
+			p_state_change(ppe->cpu_id, sample->time, ppe->state);
+		}
 
-		if (strcmp(event_str, "power:power_end") == 0)
-			c_state_end(pe->cpu_id, data.time);
+		else if (strcmp(event_str, "sched:sched_wakeup") == 0)
+			sched_wakeup(sample->cpu, sample->time, sample->pid, te);
 
-		if (strcmp(event_str, "power:power_frequency") == 0)
-			p_state_change(pe->cpu_id, data.time, pe->value);
+		else if (strcmp(event_str, "sched:sched_switch") == 0)
+			sched_switch(sample->cpu, sample->time, te);
 
-		if (strcmp(event_str, "sched:sched_wakeup") == 0)
-			sched_wakeup(data.cpu, data.time, data.pid, te);
+#ifdef SUPPORT_OLD_POWER_EVENTS
+		if (use_old_power_events) {
+			if (strcmp(event_str, "power:power_start") == 0)
+				c_state_start(peo->cpu_id, sample->time,
+					      peo->value);
 
-		if (strcmp(event_str, "sched:sched_switch") == 0)
-			sched_switch(data.cpu, data.time, te);
+			else if (strcmp(event_str, "power:power_end") == 0)
+				c_state_end(sample->cpu, sample->time);
+
+			else if (strcmp(event_str,
+					"power:power_frequency") == 0)
+				p_state_change(peo->cpu_id, sample->time,
+					       peo->value);
+		}
+#endif
 	}
 	return 0;
 }
@@ -937,7 +970,8 @@
 
 static int __cmd_timechart(void)
 {
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
+	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
+							 0, false, &event_ops);
 	int ret = -EINVAL;
 
 	if (session == NULL)
@@ -968,7 +1002,8 @@
 	NULL
 };
 
-static const char *record_args[] = {
+#ifdef SUPPORT_OLD_POWER_EVENTS
+static const char * const record_old_args[] = {
 	"record",
 	"-a",
 	"-R",
@@ -980,16 +1015,43 @@
 	"-e", "sched:sched_wakeup",
 	"-e", "sched:sched_switch",
 };
+#endif
+
+static const char * const record_new_args[] = {
+	"record",
+	"-a",
+	"-R",
+	"-f",
+	"-c", "1",
+	"-e", "power:cpu_frequency",
+	"-e", "power:cpu_idle",
+	"-e", "sched:sched_wakeup",
+	"-e", "sched:sched_switch",
+};
 
 static int __cmd_record(int argc, const char **argv)
 {
 	unsigned int rec_argc, i, j;
 	const char **rec_argv;
+	const char * const *record_args = record_new_args;
+	unsigned int record_elems = ARRAY_SIZE(record_new_args);
 
-	rec_argc = ARRAY_SIZE(record_args) + argc - 1;
+#ifdef SUPPORT_OLD_POWER_EVENTS
+	if (!is_valid_tracepoint("power:cpu_idle") &&
+	    is_valid_tracepoint("power:power_start")) {
+		use_old_power_events = 1;
+		record_args = record_old_args;
+		record_elems = ARRAY_SIZE(record_old_args);
+	}
+#endif
+
+	rec_argc = record_elems + argc - 1;
 	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
-	for (i = 0; i < ARRAY_SIZE(record_args); i++)
+	if (rec_argv == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < record_elems; i++)
 		rec_argv[i] = strdup(record_args[i]);
 
 	for (j = 1; j < (unsigned int)argc; j++, i++)
@@ -1018,6 +1080,8 @@
 	OPT_CALLBACK('p', "process", NULL, "process",
 		      "process selector. Pass a pid or process name.",
 		       parse_process),
+	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
+		    "Look for files with symbols relative to this directory"),
 	OPT_END()
 };
 
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index dd62580..1e67ab9 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -21,6 +21,7 @@
 #include "perf.h"
 
 #include "util/color.h"
+#include "util/evsel.h"
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
@@ -29,6 +30,7 @@
 #include "util/parse-options.h"
 #include "util/parse-events.h"
 #include "util/cpumap.h"
+#include "util/xyarray.h"
 
 #include "util/debug.h"
 
@@ -55,7 +57,7 @@
 #include <linux/unistd.h>
 #include <linux/types.h>
 
-static int			*fd[MAX_NR_CPUS][MAX_COUNTERS];
+#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 
 static bool			system_wide			=  false;
 
@@ -66,10 +68,9 @@
 
 static int			target_pid			=     -1;
 static int			target_tid			=     -1;
-static pid_t			*all_tids			=      NULL;
-static int			thread_num			=      0;
+static struct thread_map	*threads;
 static bool			inherit				=  false;
-static int			nr_cpus				=      0;
+static struct cpu_map		*cpus;
 static int			realtime_prio			=      0;
 static bool			group				=  false;
 static unsigned int		page_size;
@@ -100,6 +101,7 @@
 struct sym_entry		*sym_filter_entry_sched		=   NULL;
 static int			sym_pcnt_filter			=      5;
 static int			sym_counter			=      0;
+static struct perf_evsel	*sym_evsel			=   NULL;
 static int			display_weighted		=     -1;
 static const char		*cpu_list;
 
@@ -353,7 +355,7 @@
 		return;
 
 	symbol = sym_entry__symbol(syme);
-	printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
+	printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name);
 	printf("  Events  Pcnt (>=%d%%)\n", sym_pcnt_filter);
 
 	pthread_mutex_lock(&syme->src->lock);
@@ -460,7 +462,8 @@
 static void print_sym_table(void)
 {
 	int printed = 0, j;
-	int counter, snap = !display_weighted ? sym_counter : 0;
+	struct perf_evsel *counter;
+	int snap = !display_weighted ? sym_counter : 0;
 	float samples_per_sec = samples/delay_secs;
 	float ksamples_per_sec = kernel_samples/delay_secs;
 	float us_samples_per_sec = (us_samples)/delay_secs;
@@ -532,7 +535,9 @@
 	}
 
 	if (nr_counters == 1 || !display_weighted) {
-		printf("%Ld", (u64)attrs[0].sample_period);
+		struct perf_evsel *first;
+		first = list_entry(evsel_list.next, struct perf_evsel, node);
+		printf("%Ld", first->attr.sample_period);
 		if (freq)
 			printf("Hz ");
 		else
@@ -540,9 +545,9 @@
 	}
 
 	if (!display_weighted)
-		printf("%s", event_name(sym_counter));
-	else for (counter = 0; counter < nr_counters; counter++) {
-		if (counter)
+		printf("%s", event_name(sym_evsel));
+	else list_for_each_entry(counter, &evsel_list, node) {
+		if (counter->idx)
 			printf("/");
 
 		printf("%s", event_name(counter));
@@ -558,12 +563,12 @@
 		printf(" (all");
 
 	if (cpu_list)
-		printf(", CPU%s: %s)\n", nr_cpus > 1 ? "s" : "", cpu_list);
+		printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
 	else {
 		if (target_tid != -1)
 			printf(")\n");
 		else
-			printf(", %d CPU%s)\n", nr_cpus, nr_cpus > 1 ? "s" : "");
+			printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
 	}
 
 	printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
@@ -739,7 +744,7 @@
 	fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", print_entries);
 
 	if (nr_counters > 1)
-		fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(sym_counter));
+		fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(sym_evsel));
 
 	fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", count_filter);
 
@@ -826,19 +831,23 @@
 			break;
 		case 'E':
 			if (nr_counters > 1) {
-				int i;
-
 				fprintf(stderr, "\nAvailable events:");
-				for (i = 0; i < nr_counters; i++)
-					fprintf(stderr, "\n\t%d %s", i, event_name(i));
+
+				list_for_each_entry(sym_evsel, &evsel_list, node)
+					fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
 
 				prompt_integer(&sym_counter, "Enter details event counter");
 
 				if (sym_counter >= nr_counters) {
-					fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0));
+					sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
 					sym_counter = 0;
+					fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
 					sleep(1);
+					break;
 				}
+				list_for_each_entry(sym_evsel, &evsel_list, node)
+					if (sym_evsel->idx == sym_counter)
+						break;
 			} else sym_counter = 0;
 			break;
 		case 'f':
@@ -977,12 +986,13 @@
 }
 
 static void event__process_sample(const event_t *self,
-				 struct perf_session *session, int counter)
+				  struct sample_data *sample,
+				  struct perf_session *session,
+				  struct perf_evsel *evsel)
 {
 	u64 ip = self->ip.ip;
 	struct sym_entry *syme;
 	struct addr_location al;
-	struct sample_data data;
 	struct machine *machine;
 	u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
@@ -1025,7 +1035,7 @@
 	if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
 		exact_samples++;
 
-	if (event__preprocess_sample(self, session, &al, &data,
+	if (event__preprocess_sample(self, session, &al, sample,
 				     symbol_filter) < 0 ||
 	    al.filtered)
 		return;
@@ -1071,9 +1081,9 @@
 
 	syme = symbol__priv(al.sym);
 	if (!syme->skip) {
-		syme->count[counter]++;
+		syme->count[evsel->idx]++;
 		syme->origin = origin;
-		record_precise_ip(syme, counter, ip);
+		record_precise_ip(syme, evsel->idx, ip);
 		pthread_mutex_lock(&active_symbols_lock);
 		if (list_empty(&syme->node) || !syme->node.next)
 			__list_insert_active_sym(syme);
@@ -1082,12 +1092,24 @@
 }
 
 struct mmap_data {
-	int			counter;
 	void			*base;
 	int			mask;
 	unsigned int		prev;
 };
 
+static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
+					     int ncpus, int nthreads)
+{
+	evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
+	return evsel->priv != NULL ? 0 : -ENOMEM;
+}
+
+static void perf_evsel__free_mmap(struct perf_evsel *evsel)
+{
+	xyarray__delete(evsel->priv);
+	evsel->priv = NULL;
+}
+
 static unsigned int mmap_read_head(struct mmap_data *md)
 {
 	struct perf_event_mmap_page *pc = md->base;
@@ -1100,11 +1122,15 @@
 }
 
 static void perf_session__mmap_read_counter(struct perf_session *self,
-					    struct mmap_data *md)
+					    struct perf_evsel *evsel,
+					    int cpu, int thread_idx)
 {
+	struct xyarray *mmap_array = evsel->priv;
+	struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
 	unsigned int head = mmap_read_head(md);
 	unsigned int old = md->prev;
 	unsigned char *data = md->base + page_size;
+	struct sample_data sample;
 	int diff;
 
 	/*
@@ -1152,10 +1178,11 @@
 			event = &event_copy;
 		}
 
+		event__parse_sample(event, self, &sample);
 		if (event->header.type == PERF_RECORD_SAMPLE)
-			event__process_sample(event, self, md->counter);
+			event__process_sample(event, &sample, self, evsel);
 		else
-			event__process(event, self);
+			event__process(event, &sample, self);
 		old += size;
 	}
 
@@ -1163,36 +1190,39 @@
 }
 
 static struct pollfd *event_array;
-static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
 
 static void perf_session__mmap_read(struct perf_session *self)
 {
-	int i, counter, thread_index;
+	struct perf_evsel *counter;
+	int i, thread_index;
 
-	for (i = 0; i < nr_cpus; i++) {
-		for (counter = 0; counter < nr_counters; counter++)
+	for (i = 0; i < cpus->nr; i++) {
+		list_for_each_entry(counter, &evsel_list, node) {
 			for (thread_index = 0;
-				thread_index < thread_num;
+				thread_index < threads->nr;
 				thread_index++) {
 				perf_session__mmap_read_counter(self,
-					&mmap_array[i][counter][thread_index]);
+					counter, i, thread_index);
 			}
+		}
 	}
 }
 
 int nr_poll;
 int group_fd;
 
-static void start_counter(int i, int counter)
+static void start_counter(int i, struct perf_evsel *evsel)
 {
+	struct xyarray *mmap_array = evsel->priv;
+	struct mmap_data *mm;
 	struct perf_event_attr *attr;
 	int cpu = -1;
 	int thread_index;
 
 	if (target_tid == -1)
-		cpu = cpumap[i];
+		cpu = cpus->map[i];
 
-	attr = attrs + counter;
+	attr = &evsel->attr;
 
 	attr->sample_type	= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
 
@@ -1205,16 +1235,18 @@
 	attr->inherit		= (cpu < 0) && inherit;
 	attr->mmap		= 1;
 
-	for (thread_index = 0; thread_index < thread_num; thread_index++) {
+	for (thread_index = 0; thread_index < threads->nr; thread_index++) {
 try_again:
-		fd[i][counter][thread_index] = sys_perf_event_open(attr,
-				all_tids[thread_index], cpu, group_fd, 0);
+		FD(evsel, i, thread_index) = sys_perf_event_open(attr,
+				threads->map[thread_index], cpu, group_fd, 0);
 
-		if (fd[i][counter][thread_index] < 0) {
+		if (FD(evsel, i, thread_index) < 0) {
 			int err = errno;
 
 			if (err == EPERM || err == EACCES)
-				die("No permission - are you root?\n");
+				die("Permission error - are you root?\n"
+					"\t Consider tweaking"
+					" /proc/sys/kernel/perf_event_paranoid.\n");
 			/*
 			 * If it's cycles then fall back to hrtimer
 			 * based cpu-clock-tick sw counter, which
@@ -1231,30 +1263,30 @@
 				goto try_again;
 			}
 			printf("\n");
-			error("perfcounter syscall returned with %d (%s)\n",
-					fd[i][counter][thread_index], strerror(err));
+			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
+					FD(evsel, i, thread_index), strerror(err));
 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
 			exit(-1);
 		}
-		assert(fd[i][counter][thread_index] >= 0);
-		fcntl(fd[i][counter][thread_index], F_SETFL, O_NONBLOCK);
+		assert(FD(evsel, i, thread_index) >= 0);
+		fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
 
 		/*
 		 * First counter acts as the group leader:
 		 */
 		if (group && group_fd == -1)
-			group_fd = fd[i][counter][thread_index];
+			group_fd = FD(evsel, i, thread_index);
 
-		event_array[nr_poll].fd = fd[i][counter][thread_index];
+		event_array[nr_poll].fd = FD(evsel, i, thread_index);
 		event_array[nr_poll].events = POLLIN;
 		nr_poll++;
 
-		mmap_array[i][counter][thread_index].counter = counter;
-		mmap_array[i][counter][thread_index].prev = 0;
-		mmap_array[i][counter][thread_index].mask = mmap_pages*page_size - 1;
-		mmap_array[i][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size,
-				PROT_READ, MAP_SHARED, fd[i][counter][thread_index], 0);
-		if (mmap_array[i][counter][thread_index].base == MAP_FAILED)
+		mm = xyarray__entry(mmap_array, i, thread_index);
+		mm->prev = 0;
+		mm->mask = mmap_pages*page_size - 1;
+		mm->base = mmap(NULL, (mmap_pages+1)*page_size,
+				PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
+		if (mm->base == MAP_FAILED)
 			die("failed to mmap with %d (%s)\n", errno, strerror(errno));
 	}
 }
@@ -1262,13 +1294,13 @@
 static int __cmd_top(void)
 {
 	pthread_t thread;
-	int i, counter;
-	int ret;
+	struct perf_evsel *counter;
+	int i, ret;
 	/*
 	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
 	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
 	 */
-	struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false);
+	struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -1277,9 +1309,9 @@
 	else
 		event__synthesize_threads(event__process, session);
 
-	for (i = 0; i < nr_cpus; i++) {
+	for (i = 0; i < cpus->nr; i++) {
 		group_fd = -1;
-		for (counter = 0; counter < nr_counters; counter++)
+		list_for_each_entry(counter, &evsel_list, node)
 			start_counter(i, counter);
 	}
 
@@ -1368,8 +1400,8 @@
 
 int cmd_top(int argc, const char **argv, const char *prefix __used)
 {
-	int counter;
-	int i,j;
+	struct perf_evsel *pos;
+	int status = -ENOMEM;
 
 	page_size = sysconf(_SC_PAGE_SIZE);
 
@@ -1377,34 +1409,17 @@
 	if (argc)
 		usage_with_options(top_usage, options);
 
-	if (target_pid != -1) {
+	if (target_pid != -1)
 		target_tid = target_pid;
-		thread_num = find_all_tid(target_pid, &all_tids);
-		if (thread_num <= 0) {
-			fprintf(stderr, "Can't find all threads of pid %d\n",
-				target_pid);
-			usage_with_options(top_usage, options);
-		}
-	} else {
-		all_tids=malloc(sizeof(pid_t));
-		if (!all_tids)
-			return -ENOMEM;
 
-		all_tids[0] = target_tid;
-		thread_num = 1;
+	threads = thread_map__new(target_pid, target_tid);
+	if (threads == NULL) {
+		pr_err("Problems finding threads of monitor\n");
+		usage_with_options(top_usage, options);
 	}
 
-	for (i = 0; i < MAX_NR_CPUS; i++) {
-		for (j = 0; j < MAX_COUNTERS; j++) {
-			fd[i][j] = malloc(sizeof(int)*thread_num);
-			mmap_array[i][j] = zalloc(
-				sizeof(struct mmap_data)*thread_num);
-			if (!fd[i][j] || !mmap_array[i][j])
-				return -ENOMEM;
-		}
-	}
-	event_array = malloc(
-		sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
+	event_array = malloc((sizeof(struct pollfd) *
+			      MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
 	if (!event_array)
 		return -ENOMEM;
 
@@ -1415,15 +1430,10 @@
 		cpu_list = NULL;
 	}
 
-	if (!nr_counters)
-		nr_counters = 1;
-
-	symbol_conf.priv_size = (sizeof(struct sym_entry) +
-				 (nr_counters + 1) * sizeof(unsigned long));
-
-	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
-	if (symbol__init() < 0)
-		return -1;
+	if (!nr_counters && perf_evsel_list__create_default() < 0) {
+		pr_err("Not enough memory for event selector list\n");
+		return -ENOMEM;
+	}
 
 	if (delay_secs < 1)
 		delay_secs = 1;
@@ -1440,23 +1450,33 @@
 		exit(EXIT_FAILURE);
 	}
 
-	/*
-	 * Fill in the ones not specifically initialized via -c:
-	 */
-	for (counter = 0; counter < nr_counters; counter++) {
-		if (attrs[counter].sample_period)
+	if (target_tid != -1)
+		cpus = cpu_map__dummy_new();
+	else
+		cpus = cpu_map__new(cpu_list);
+
+	if (cpus == NULL)
+		usage_with_options(top_usage, options);
+
+	list_for_each_entry(pos, &evsel_list, node) {
+		if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
+		    perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
+			goto out_free_fd;
+		/*
+		 * Fill in the ones not specifically initialized via -c:
+		 */
+		if (pos->attr.sample_period)
 			continue;
 
-		attrs[counter].sample_period = default_interval;
+		pos->attr.sample_period = default_interval;
 	}
 
-	if (target_tid != -1)
-		nr_cpus = 1;
-	else
-		nr_cpus = read_cpu_map(cpu_list);
+	symbol_conf.priv_size = (sizeof(struct sym_entry) +
+				 (nr_counters + 1) * sizeof(unsigned long));
 
-	if (nr_cpus < 1)
-		usage_with_options(top_usage, options);
+	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
+	if (symbol__init() < 0)
+		return -1;
 
 	get_term_dimensions(&winsize);
 	if (print_entries == 0) {
@@ -1464,5 +1484,10 @@
 		signal(SIGWINCH, sig_winch_handler);
 	}
 
-	return __cmd_top();
+	status = __cmd_top();
+out_free_fd:
+	list_for_each_entry(pos, &evsel_list, node)
+		perf_evsel__free_mmap(pos);
+
+	return status;
 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
deleted file mode 100644
index 86cfe38..0000000
--- a/tools/perf/builtin-trace.c
+++ /dev/null
@@ -1,826 +0,0 @@
-#include "builtin.h"
-
-#include "perf.h"
-#include "util/cache.h"
-#include "util/debug.h"
-#include "util/exec_cmd.h"
-#include "util/header.h"
-#include "util/parse-options.h"
-#include "util/session.h"
-#include "util/symbol.h"
-#include "util/thread.h"
-#include "util/trace-event.h"
-#include "util/parse-options.h"
-#include "util/util.h"
-
-static char const		*script_name;
-static char const		*generate_script_lang;
-static bool			debug_mode;
-static u64			last_timestamp;
-static u64			nr_unordered;
-extern const struct option	record_options[];
-
-static int default_start_script(const char *script __unused,
-				int argc __unused,
-				const char **argv __unused)
-{
-	return 0;
-}
-
-static int default_stop_script(void)
-{
-	return 0;
-}
-
-static int default_generate_script(const char *outfile __unused)
-{
-	return 0;
-}
-
-static struct scripting_ops default_scripting_ops = {
-	.start_script		= default_start_script,
-	.stop_script		= default_stop_script,
-	.process_event		= print_event,
-	.generate_script	= default_generate_script,
-};
-
-static struct scripting_ops	*scripting_ops;
-
-static void setup_scripting(void)
-{
-	setup_perl_scripting();
-	setup_python_scripting();
-
-	scripting_ops = &default_scripting_ops;
-}
-
-static int cleanup_scripting(void)
-{
-	pr_debug("\nperf trace script stopped\n");
-
-	return scripting_ops->stop_script();
-}
-
-static char const		*input_name = "perf.data";
-
-static int process_sample_event(event_t *event, struct perf_session *session)
-{
-	struct sample_data data;
-	struct thread *thread;
-
-	memset(&data, 0, sizeof(data));
-	data.time = -1;
-	data.cpu = -1;
-	data.period = 1;
-
-	event__parse_sample(event, session->sample_type, &data);
-
-	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
-		    data.pid, data.tid, data.ip, data.period);
-
-	thread = perf_session__findnew(session, event->ip.pid);
-	if (thread == NULL) {
-		pr_debug("problem processing %d event, skipping it.\n",
-			 event->header.type);
-		return -1;
-	}
-
-	if (session->sample_type & PERF_SAMPLE_RAW) {
-		if (debug_mode) {
-			if (data.time < last_timestamp) {
-				pr_err("Samples misordered, previous: %llu "
-					"this: %llu\n", last_timestamp,
-					data.time);
-				nr_unordered++;
-			}
-			last_timestamp = data.time;
-			return 0;
-		}
-		/*
-		 * FIXME: better resolve from pid from the struct trace_entry
-		 * field, although it should be the same than this perf
-		 * event pid
-		 */
-		scripting_ops->process_event(data.cpu, data.raw_data,
-					     data.raw_size,
-					     data.time, thread->comm);
-	}
-
-	session->hists.stats.total_period += data.period;
-	return 0;
-}
-
-static u64 nr_lost;
-
-static int process_lost_event(event_t *event, struct perf_session *session __used)
-{
-	nr_lost += event->lost.lost;
-
-	return 0;
-}
-
-static struct perf_event_ops event_ops = {
-	.sample	= process_sample_event,
-	.comm	= event__process_comm,
-	.attr	= event__process_attr,
-	.event_type = event__process_event_type,
-	.tracing_data = event__process_tracing_data,
-	.build_id = event__process_build_id,
-	.lost = process_lost_event,
-	.ordered_samples = true,
-};
-
-extern volatile int session_done;
-
-static void sig_handler(int sig __unused)
-{
-	session_done = 1;
-}
-
-static int __cmd_trace(struct perf_session *session)
-{
-	int ret;
-
-	signal(SIGINT, sig_handler);
-
-	ret = perf_session__process_events(session, &event_ops);
-
-	if (debug_mode) {
-		pr_err("Misordered timestamps: %llu\n", nr_unordered);
-		pr_err("Lost events: %llu\n", nr_lost);
-	}
-
-	return ret;
-}
-
-struct script_spec {
-	struct list_head	node;
-	struct scripting_ops	*ops;
-	char			spec[0];
-};
-
-LIST_HEAD(script_specs);
-
-static struct script_spec *script_spec__new(const char *spec,
-					    struct scripting_ops *ops)
-{
-	struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1);
-
-	if (s != NULL) {
-		strcpy(s->spec, spec);
-		s->ops = ops;
-	}
-
-	return s;
-}
-
-static void script_spec__delete(struct script_spec *s)
-{
-	free(s->spec);
-	free(s);
-}
-
-static void script_spec__add(struct script_spec *s)
-{
-	list_add_tail(&s->node, &script_specs);
-}
-
-static struct script_spec *script_spec__find(const char *spec)
-{
-	struct script_spec *s;
-
-	list_for_each_entry(s, &script_specs, node)
-		if (strcasecmp(s->spec, spec) == 0)
-			return s;
-	return NULL;
-}
-
-static struct script_spec *script_spec__findnew(const char *spec,
-						struct scripting_ops *ops)
-{
-	struct script_spec *s = script_spec__find(spec);
-
-	if (s)
-		return s;
-
-	s = script_spec__new(spec, ops);
-	if (!s)
-		goto out_delete_spec;
-
-	script_spec__add(s);
-
-	return s;
-
-out_delete_spec:
-	script_spec__delete(s);
-
-	return NULL;
-}
-
-int script_spec_register(const char *spec, struct scripting_ops *ops)
-{
-	struct script_spec *s;
-
-	s = script_spec__find(spec);
-	if (s)
-		return -1;
-
-	s = script_spec__findnew(spec, ops);
-	if (!s)
-		return -1;
-
-	return 0;
-}
-
-static struct scripting_ops *script_spec__lookup(const char *spec)
-{
-	struct script_spec *s = script_spec__find(spec);
-	if (!s)
-		return NULL;
-
-	return s->ops;
-}
-
-static void list_available_languages(void)
-{
-	struct script_spec *s;
-
-	fprintf(stderr, "\n");
-	fprintf(stderr, "Scripting language extensions (used in "
-		"perf trace -s [spec:]script.[spec]):\n\n");
-
-	list_for_each_entry(s, &script_specs, node)
-		fprintf(stderr, "  %-42s [%s]\n", s->spec, s->ops->name);
-
-	fprintf(stderr, "\n");
-}
-
-static int parse_scriptname(const struct option *opt __used,
-			    const char *str, int unset __used)
-{
-	char spec[PATH_MAX];
-	const char *script, *ext;
-	int len;
-
-	if (strcmp(str, "lang") == 0) {
-		list_available_languages();
-		exit(0);
-	}
-
-	script = strchr(str, ':');
-	if (script) {
-		len = script - str;
-		if (len >= PATH_MAX) {
-			fprintf(stderr, "invalid language specifier");
-			return -1;
-		}
-		strncpy(spec, str, len);
-		spec[len] = '\0';
-		scripting_ops = script_spec__lookup(spec);
-		if (!scripting_ops) {
-			fprintf(stderr, "invalid language specifier");
-			return -1;
-		}
-		script++;
-	} else {
-		script = str;
-		ext = strrchr(script, '.');
-		if (!ext) {
-			fprintf(stderr, "invalid script extension");
-			return -1;
-		}
-		scripting_ops = script_spec__lookup(++ext);
-		if (!scripting_ops) {
-			fprintf(stderr, "invalid script extension");
-			return -1;
-		}
-	}
-
-	script_name = strdup(script);
-
-	return 0;
-}
-
-#define for_each_lang(scripts_dir, lang_dirent, lang_next)		\
-	while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) &&	\
-	       lang_next)						\
-		if (lang_dirent.d_type == DT_DIR &&			\
-		    (strcmp(lang_dirent.d_name, ".")) &&		\
-		    (strcmp(lang_dirent.d_name, "..")))
-
-#define for_each_script(lang_dir, script_dirent, script_next)		\
-	while (!readdir_r(lang_dir, &script_dirent, &script_next) &&	\
-	       script_next)						\
-		if (script_dirent.d_type != DT_DIR)
-
-
-#define RECORD_SUFFIX			"-record"
-#define REPORT_SUFFIX			"-report"
-
-struct script_desc {
-	struct list_head	node;
-	char			*name;
-	char			*half_liner;
-	char			*args;
-};
-
-LIST_HEAD(script_descs);
-
-static struct script_desc *script_desc__new(const char *name)
-{
-	struct script_desc *s = zalloc(sizeof(*s));
-
-	if (s != NULL && name)
-		s->name = strdup(name);
-
-	return s;
-}
-
-static void script_desc__delete(struct script_desc *s)
-{
-	free(s->name);
-	free(s->half_liner);
-	free(s->args);
-	free(s);
-}
-
-static void script_desc__add(struct script_desc *s)
-{
-	list_add_tail(&s->node, &script_descs);
-}
-
-static struct script_desc *script_desc__find(const char *name)
-{
-	struct script_desc *s;
-
-	list_for_each_entry(s, &script_descs, node)
-		if (strcasecmp(s->name, name) == 0)
-			return s;
-	return NULL;
-}
-
-static struct script_desc *script_desc__findnew(const char *name)
-{
-	struct script_desc *s = script_desc__find(name);
-
-	if (s)
-		return s;
-
-	s = script_desc__new(name);
-	if (!s)
-		goto out_delete_desc;
-
-	script_desc__add(s);
-
-	return s;
-
-out_delete_desc:
-	script_desc__delete(s);
-
-	return NULL;
-}
-
-static char *ends_with(char *str, const char *suffix)
-{
-	size_t suffix_len = strlen(suffix);
-	char *p = str;
-
-	if (strlen(str) > suffix_len) {
-		p = str + strlen(str) - suffix_len;
-		if (!strncmp(p, suffix, suffix_len))
-			return p;
-	}
-
-	return NULL;
-}
-
-static char *ltrim(char *str)
-{
-	int len = strlen(str);
-
-	while (len && isspace(*str)) {
-		len--;
-		str++;
-	}
-
-	return str;
-}
-
-static int read_script_info(struct script_desc *desc, const char *filename)
-{
-	char line[BUFSIZ], *p;
-	FILE *fp;
-
-	fp = fopen(filename, "r");
-	if (!fp)
-		return -1;
-
-	while (fgets(line, sizeof(line), fp)) {
-		p = ltrim(line);
-		if (strlen(p) == 0)
-			continue;
-		if (*p != '#')
-			continue;
-		p++;
-		if (strlen(p) && *p == '!')
-			continue;
-
-		p = ltrim(p);
-		if (strlen(p) && p[strlen(p) - 1] == '\n')
-			p[strlen(p) - 1] = '\0';
-
-		if (!strncmp(p, "description:", strlen("description:"))) {
-			p += strlen("description:");
-			desc->half_liner = strdup(ltrim(p));
-			continue;
-		}
-
-		if (!strncmp(p, "args:", strlen("args:"))) {
-			p += strlen("args:");
-			desc->args = strdup(ltrim(p));
-			continue;
-		}
-	}
-
-	fclose(fp);
-
-	return 0;
-}
-
-static int list_available_scripts(const struct option *opt __used,
-				  const char *s __used, int unset __used)
-{
-	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
-	char scripts_path[MAXPATHLEN];
-	DIR *scripts_dir, *lang_dir;
-	char script_path[MAXPATHLEN];
-	char lang_path[MAXPATHLEN];
-	struct script_desc *desc;
-	char first_half[BUFSIZ];
-	char *script_root;
-	char *str;
-
-	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
-
-	scripts_dir = opendir(scripts_path);
-	if (!scripts_dir)
-		return -1;
-
-	for_each_lang(scripts_dir, lang_dirent, lang_next) {
-		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
-			 lang_dirent.d_name);
-		lang_dir = opendir(lang_path);
-		if (!lang_dir)
-			continue;
-
-		for_each_script(lang_dir, script_dirent, script_next) {
-			script_root = strdup(script_dirent.d_name);
-			str = ends_with(script_root, REPORT_SUFFIX);
-			if (str) {
-				*str = '\0';
-				desc = script_desc__findnew(script_root);
-				snprintf(script_path, MAXPATHLEN, "%s/%s",
-					 lang_path, script_dirent.d_name);
-				read_script_info(desc, script_path);
-			}
-			free(script_root);
-		}
-	}
-
-	fprintf(stdout, "List of available trace scripts:\n");
-	list_for_each_entry(desc, &script_descs, node) {
-		sprintf(first_half, "%s %s", desc->name,
-			desc->args ? desc->args : "");
-		fprintf(stdout, "  %-36s %s\n", first_half,
-			desc->half_liner ? desc->half_liner : "");
-	}
-
-	exit(0);
-}
-
-static char *get_script_path(const char *script_root, const char *suffix)
-{
-	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
-	char scripts_path[MAXPATHLEN];
-	char script_path[MAXPATHLEN];
-	DIR *scripts_dir, *lang_dir;
-	char lang_path[MAXPATHLEN];
-	char *str, *__script_root;
-	char *path = NULL;
-
-	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
-
-	scripts_dir = opendir(scripts_path);
-	if (!scripts_dir)
-		return NULL;
-
-	for_each_lang(scripts_dir, lang_dirent, lang_next) {
-		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
-			 lang_dirent.d_name);
-		lang_dir = opendir(lang_path);
-		if (!lang_dir)
-			continue;
-
-		for_each_script(lang_dir, script_dirent, script_next) {
-			__script_root = strdup(script_dirent.d_name);
-			str = ends_with(__script_root, suffix);
-			if (str) {
-				*str = '\0';
-				if (strcmp(__script_root, script_root))
-					continue;
-				snprintf(script_path, MAXPATHLEN, "%s/%s",
-					 lang_path, script_dirent.d_name);
-				path = strdup(script_path);
-				free(__script_root);
-				break;
-			}
-			free(__script_root);
-		}
-	}
-
-	return path;
-}
-
-static bool is_top_script(const char *script_path)
-{
-	return ends_with((char *)script_path, "top") == NULL ? false : true;
-}
-
-static int has_required_arg(char *script_path)
-{
-	struct script_desc *desc;
-	int n_args = 0;
-	char *p;
-
-	desc = script_desc__new(NULL);
-
-	if (read_script_info(desc, script_path))
-		goto out;
-
-	if (!desc->args)
-		goto out;
-
-	for (p = desc->args; *p; p++)
-		if (*p == '<')
-			n_args++;
-out:
-	script_desc__delete(desc);
-
-	return n_args;
-}
-
-static const char * const trace_usage[] = {
-	"perf trace [<options>]",
-	"perf trace [<options>] record <script> [<record-options>] <command>",
-	"perf trace [<options>] report <script> [script-args]",
-	"perf trace [<options>] <script> [<record-options>] <command>",
-	"perf trace [<options>] <top-script> [script-args]",
-	NULL
-};
-
-static const struct option options[] = {
-	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
-		    "dump raw trace in ASCII"),
-	OPT_INCR('v', "verbose", &verbose,
-		    "be more verbose (show symbol address, etc)"),
-	OPT_BOOLEAN('L', "Latency", &latency_format,
-		    "show latency attributes (irqs/preemption disabled, etc)"),
-	OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
-			   list_available_scripts),
-	OPT_CALLBACK('s', "script", NULL, "name",
-		     "script file name (lang:script name, script name, or *)",
-		     parse_scriptname),
-	OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
-		   "generate perf-trace.xx script in specified language"),
-	OPT_STRING('i', "input", &input_name, "file",
-		    "input file name"),
-	OPT_BOOLEAN('d', "debug-mode", &debug_mode,
-		   "do various checks like samples ordering and lost events"),
-
-	OPT_END()
-};
-
-static bool have_cmd(int argc, const char **argv)
-{
-	char **__argv = malloc(sizeof(const char *) * argc);
-
-	if (!__argv)
-		die("malloc");
-	memcpy(__argv, argv, sizeof(const char *) * argc);
-	argc = parse_options(argc, (const char **)__argv, record_options,
-			     NULL, PARSE_OPT_STOP_AT_NON_OPTION);
-	free(__argv);
-
-	return argc != 0;
-}
-
-int cmd_trace(int argc, const char **argv, const char *prefix __used)
-{
-	char *rec_script_path = NULL;
-	char *rep_script_path = NULL;
-	struct perf_session *session;
-	char *script_path = NULL;
-	const char **__argv;
-	bool system_wide;
-	int i, j, err;
-
-	setup_scripting();
-
-	argc = parse_options(argc, argv, options, trace_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-
-	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
-		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
-		if (!rec_script_path)
-			return cmd_record(argc, argv, NULL);
-	}
-
-	if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
-		rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
-		if (!rep_script_path) {
-			fprintf(stderr,
-				"Please specify a valid report script"
-				"(see 'perf trace -l' for listing)\n");
-			return -1;
-		}
-	}
-
-	/* make sure PERF_EXEC_PATH is set for scripts */
-	perf_set_argv_exec_path(perf_exec_path());
-
-	if (argc && !script_name && !rec_script_path && !rep_script_path) {
-		int live_pipe[2];
-		int rep_args;
-		pid_t pid;
-
-		rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
-		rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
-
-		if (!rec_script_path && !rep_script_path) {
-			fprintf(stderr, " Couldn't find script %s\n\n See perf"
-				" trace -l for available scripts.\n", argv[0]);
-			usage_with_options(trace_usage, options);
-		}
-
-		if (is_top_script(argv[0])) {
-			rep_args = argc - 1;
-		} else {
-			int rec_args;
-
-			rep_args = has_required_arg(rep_script_path);
-			rec_args = (argc - 1) - rep_args;
-			if (rec_args < 0) {
-				fprintf(stderr, " %s script requires options."
-					"\n\n See perf trace -l for available "
-					"scripts and options.\n", argv[0]);
-				usage_with_options(trace_usage, options);
-			}
-		}
-
-		if (pipe(live_pipe) < 0) {
-			perror("failed to create pipe");
-			exit(-1);
-		}
-
-		pid = fork();
-		if (pid < 0) {
-			perror("failed to fork");
-			exit(-1);
-		}
-
-		if (!pid) {
-			system_wide = true;
-			j = 0;
-
-			dup2(live_pipe[1], 1);
-			close(live_pipe[0]);
-
-			if (!is_top_script(argv[0]))
-				system_wide = !have_cmd(argc - rep_args,
-							&argv[rep_args]);
-
-			__argv = malloc((argc + 6) * sizeof(const char *));
-			if (!__argv)
-				die("malloc");
-
-			__argv[j++] = "/bin/sh";
-			__argv[j++] = rec_script_path;
-			if (system_wide)
-				__argv[j++] = "-a";
-			__argv[j++] = "-q";
-			__argv[j++] = "-o";
-			__argv[j++] = "-";
-			for (i = rep_args + 1; i < argc; i++)
-				__argv[j++] = argv[i];
-			__argv[j++] = NULL;
-
-			execvp("/bin/sh", (char **)__argv);
-			free(__argv);
-			exit(-1);
-		}
-
-		dup2(live_pipe[0], 0);
-		close(live_pipe[1]);
-
-		__argv = malloc((argc + 4) * sizeof(const char *));
-		if (!__argv)
-			die("malloc");
-		j = 0;
-		__argv[j++] = "/bin/sh";
-		__argv[j++] = rep_script_path;
-		for (i = 1; i < rep_args + 1; i++)
-			__argv[j++] = argv[i];
-		__argv[j++] = "-i";
-		__argv[j++] = "-";
-		__argv[j++] = NULL;
-
-		execvp("/bin/sh", (char **)__argv);
-		free(__argv);
-		exit(-1);
-	}
-
-	if (rec_script_path)
-		script_path = rec_script_path;
-	if (rep_script_path)
-		script_path = rep_script_path;
-
-	if (script_path) {
-		system_wide = false;
-		j = 0;
-
-		if (rec_script_path)
-			system_wide = !have_cmd(argc - 1, &argv[1]);
-
-		__argv = malloc((argc + 2) * sizeof(const char *));
-		if (!__argv)
-			die("malloc");
-		__argv[j++] = "/bin/sh";
-		__argv[j++] = script_path;
-		if (system_wide)
-			__argv[j++] = "-a";
-		for (i = 2; i < argc; i++)
-			__argv[j++] = argv[i];
-		__argv[j++] = NULL;
-
-		execvp("/bin/sh", (char **)__argv);
-		free(__argv);
-		exit(-1);
-	}
-
-	if (symbol__init() < 0)
-		return -1;
-	if (!script_name)
-		setup_pager();
-
-	session = perf_session__new(input_name, O_RDONLY, 0, false);
-	if (session == NULL)
-		return -ENOMEM;
-
-	if (strcmp(input_name, "-") &&
-	    !perf_session__has_traces(session, "record -R"))
-		return -EINVAL;
-
-	if (generate_script_lang) {
-		struct stat perf_stat;
-
-		int input = open(input_name, O_RDONLY);
-		if (input < 0) {
-			perror("failed to open file");
-			exit(-1);
-		}
-
-		err = fstat(input, &perf_stat);
-		if (err < 0) {
-			perror("failed to stat file");
-			exit(-1);
-		}
-
-		if (!perf_stat.st_size) {
-			fprintf(stderr, "zero-sized file, nothing to do!\n");
-			exit(0);
-		}
-
-		scripting_ops = script_spec__lookup(generate_script_lang);
-		if (!scripting_ops) {
-			fprintf(stderr, "invalid language specifier");
-			return -1;
-		}
-
-		err = scripting_ops->generate_script("perf-trace");
-		goto out;
-	}
-
-	if (script_name) {
-		err = scripting_ops->start_script(script_name, argc, argv);
-		if (err)
-			goto out;
-		pr_debug("perf trace started with script %s\n\n", script_name);
-	}
-
-	err = __cmd_trace(session);
-
-	perf_session__delete(session);
-	cleanup_scripting();
-out:
-	return err;
-}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 921245b..c7798c7 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -27,7 +27,7 @@
 extern int cmd_stat(int argc, const char **argv, const char *prefix);
 extern int cmd_timechart(int argc, const char **argv, const char *prefix);
 extern int cmd_top(int argc, const char **argv, const char *prefix);
-extern int cmd_trace(int argc, const char **argv, const char *prefix);
+extern int cmd_script(int argc, const char **argv, const char *prefix);
 extern int cmd_version(int argc, const char **argv, const char *prefix);
 extern int cmd_probe(int argc, const char **argv, const char *prefix);
 extern int cmd_kmem(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 949d77f..16b5088 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -16,7 +16,7 @@
 perf-stat			mainporcelain common
 perf-timechart			mainporcelain common
 perf-top			mainporcelain common
-perf-trace			mainporcelain common
+perf-script			mainporcelain common
 perf-probe			mainporcelain common
 perf-kmem			mainporcelain common
 perf-lock			mainporcelain common
diff --git a/tools/perf/feature-tests.mak b/tools/perf/feature-tests.mak
index b253db6..b041ca6 100644
--- a/tools/perf/feature-tests.mak
+++ b/tools/perf/feature-tests.mak
@@ -9,8 +9,8 @@
 ifndef NO_DWARF
 define SOURCE_DWARF
 #include <dwarf.h>
-#include <libdw.h>
-#include <version.h>
+#include <elfutils/libdw.h>
+#include <elfutils/version.h>
 #ifndef _ELFUTILS_PREREQ
 #error
 #endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index cdd6c03..5b1ecd6 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -286,6 +286,8 @@
 	status = p->fn(argc, argv, prefix);
 	exit_browser(status);
 
+	perf_evsel_list__delete();
+
 	if (status)
 		return status & 0xff;
 
@@ -323,7 +325,7 @@
 		{ "top",	cmd_top,	0 },
 		{ "annotate",	cmd_annotate,	0 },
 		{ "version",	cmd_version,	0 },
-		{ "trace",	cmd_trace,	0 },
+		{ "script",	cmd_script,	0 },
 		{ "sched",	cmd_sched,	0 },
 		{ "probe",	cmd_probe,	0 },
 		{ "kmem",	cmd_kmem,	0 },
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
index 01a64ad..790ceba 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
@@ -8,7 +8,7 @@
 
 #line 1 "Context.xs"
 /*
- * Context.xs.  XS interfaces for perf trace.
+ * Context.xs.  XS interfaces for perf script.
  *
  * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
  *
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
index 549cf04..c1e2ed1 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
@@ -1,5 +1,5 @@
 /*
- * Context.xs.  XS interfaces for perf trace.
+ * Context.xs.  XS interfaces for perf script.
  *
  * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
  *
@@ -23,7 +23,7 @@
 #include "perl.h"
 #include "XSUB.h"
 #include "../../../perf.h"
-#include "../../../util/trace-event.h"
+#include "../../../util/script-event.h"
 
 MODULE = Perf::Trace::Context		PACKAGE = Perf::Trace::Context
 PROTOTYPES: ENABLE
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/README b/tools/perf/scripts/perl/Perf-Trace-Util/README
index 9a97076..2f0c7f3 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/README
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/README
@@ -1,7 +1,7 @@
 Perf-Trace-Util version 0.01
 ============================
 
-This module contains utility functions for use with perf trace.
+This module contains utility functions for use with perf script.
 
 Core.pm and Util.pm are pure Perl modules; Core.pm contains routines
 that the core perf support for Perl calls on and should always be
@@ -33,7 +33,7 @@
 
 INSTALLATION
 
-Building perf with perf trace Perl scripting should install this
+Building perf with perf script Perl scripting should install this
 module in the right place.
 
 You should make sure libperl and ExtUtils/Embed.pm are installed first
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
index 6c7f3659..4e2f6039 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
@@ -34,7 +34,7 @@
 
 =head1 SEE ALSO
 
-Perf (trace) documentation
+Perf (script) documentation
 
 =head1 AUTHOR
 
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
index 9df376a..9158458 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
@@ -163,7 +163,7 @@
 __END__
 =head1 NAME
 
-Perf::Trace::Core - Perl extension for perf trace
+Perf::Trace::Core - Perl extension for perf script
 
 =head1 SYNOPSIS
 
@@ -171,7 +171,7 @@
 
 =head1 SEE ALSO
 
-Perf (trace) documentation
+Perf (script) documentation
 
 =head1 AUTHOR
 
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
index d94b40c..0535001 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
@@ -65,7 +65,7 @@
 __END__
 =head1 NAME
 
-Perf::Trace::Util - Perl extension for perf trace
+Perf::Trace::Util - Perl extension for perf script
 
 =head1 SYNOPSIS
 
@@ -73,7 +73,7 @@
 
 =head1 SEE ALSO
 
-Perf (trace) documentation
+Perf (script) documentation
 
 =head1 AUTHOR
 
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-report b/tools/perf/scripts/perl/bin/failed-syscalls-report
index 4028d92..9f83cc1 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-report
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-report
@@ -7,4 +7,4 @@
 	shift
     fi
 fi
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/failed-syscalls.pl $comm
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/failed-syscalls.pl $comm
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report
index ba25f4d..77200b3 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-report
+++ b/tools/perf/scripts/perl/bin/rw-by-file-report
@@ -7,7 +7,4 @@
 fi
 comm=$1
 shift
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-file.pl $comm
-
-
-
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-file.pl $comm
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report
index 641a3f5..a27b9f3 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-report
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-report
@@ -1,6 +1,3 @@
 #!/bin/bash
 # description: system-wide r/w activity
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-pid.pl
-
-
-
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-pid.pl
diff --git a/tools/perf/scripts/perl/bin/rwtop-report b/tools/perf/scripts/perl/bin/rwtop-report
index 4918dba..83e11ec 100644
--- a/tools/perf/scripts/perl/bin/rwtop-report
+++ b/tools/perf/scripts/perl/bin/rwtop-report
@@ -17,7 +17,4 @@
     interval=$1
     shift
 fi
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rwtop.pl $interval
-
-
-
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rwtop.pl $interval
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report
index 49052eb..889e813 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-report
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-report
@@ -1,6 +1,3 @@
 #!/bin/bash
 # description: system-wide min/max/avg wakeup latency
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/wakeup-latency.pl
-
-
-
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/wakeup-latency.pl
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
index df0c65f..6d91411 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-report
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-report
@@ -1,7 +1,3 @@
 #!/bin/bash
 # description: workqueue stats (ins/exe/create/destroy)
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl
-
-
-
-
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl
diff --git a/tools/perf/scripts/perl/check-perf-trace.pl b/tools/perf/scripts/perl/check-perf-trace.pl
index 4e7dc0a..4e7076c 100644
--- a/tools/perf/scripts/perl/check-perf-trace.pl
+++ b/tools/perf/scripts/perl/check-perf-trace.pl
@@ -1,4 +1,4 @@
-# perf trace event handlers, generated by perf trace -g perl
+# perf script event handlers, generated by perf script -g perl
 # (c) 2009, Tom Zanussi <tzanussi@gmail.com>
 # Licensed under the terms of the GNU GPL License version 2
 
diff --git a/tools/perf/scripts/perl/rw-by-file.pl b/tools/perf/scripts/perl/rw-by-file.pl
index 2a39097..74844ee 100644
--- a/tools/perf/scripts/perl/rw-by-file.pl
+++ b/tools/perf/scripts/perl/rw-by-file.pl
@@ -18,7 +18,7 @@
 use Perf::Trace::Core;
 use Perf::Trace::Util;
 
-my $usage = "perf trace -s rw-by-file.pl <comm>\n";
+my $usage = "perf script -s rw-by-file.pl <comm>\n";
 
 my $for_comm = shift or die $usage;
 
diff --git a/tools/perf/scripts/perl/workqueue-stats.pl b/tools/perf/scripts/perl/workqueue-stats.pl
index b84b126..a8eaff5 100644
--- a/tools/perf/scripts/perl/workqueue-stats.pl
+++ b/tools/perf/scripts/perl/workqueue-stats.pl
@@ -10,7 +10,7 @@
 #     workqueue:workqueue_destruction -e workqueue:workqueue_execution
 #     -e workqueue:workqueue_insertion
 #
-#   perf trace -p -s tools/perf/scripts/perl/workqueue-stats.pl
+#   perf script -p -s tools/perf/scripts/perl/workqueue-stats.pl
 
 use 5.010000;
 use strict;
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index 957085d..315067b 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -1,5 +1,5 @@
 /*
- * Context.c.  Python interfaces for perf trace.
+ * Context.c.  Python interfaces for perf script.
  *
  * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
  *
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index aad7525..de7211e 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -1,4 +1,4 @@
-# Core.py - Python extension for perf trace, core functions
+# Core.py - Python extension for perf script, core functions
 #
 # Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
 #
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
index ae9a56e..fdd92f6 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
@@ -1,4 +1,4 @@
-# SchedGui.py - Python extension for perf trace, basic GUI code for
+# SchedGui.py - Python extension for perf script, basic GUI code for
 #		traces drawing and overview.
 #
 # Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
index 13cc02b..15c8400 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
@@ -1,4 +1,4 @@
-# Util.py - Python extension for perf trace, miscellaneous utility code
+# Util.py - Python extension for perf script, miscellaneous utility code
 #
 # Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
 #
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
index 0358702..fda5096 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
@@ -7,4 +7,4 @@
 	shift
     fi
 fi
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/futex-contention-report b/tools/perf/scripts/python/bin/futex-contention-report
index c826813..6c44271 100644
--- a/tools/perf/scripts/python/bin/futex-contention-report
+++ b/tools/perf/scripts/python/bin/futex-contention-report
@@ -1,4 +1,4 @@
 #!/bin/bash
 # description: futext contention measurement
 
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
index 4ad361b..8f75929 100644
--- a/tools/perf/scripts/python/bin/netdev-times-report
+++ b/tools/perf/scripts/python/bin/netdev-times-report
@@ -2,4 +2,4 @@
 # description: display a process of packet and processing time
 # args: [tx] [rx] [dev=] [debug]
 
-perf trace -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@
+perf script -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-report b/tools/perf/scripts/python/bin/sched-migration-report
index df1791f..68b037a 100644
--- a/tools/perf/scripts/python/bin/sched-migration-report
+++ b/tools/perf/scripts/python/bin/sched-migration-report
@@ -1,3 +1,3 @@
 #!/bin/bash
 # description: sched migration overview
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py
diff --git a/tools/perf/scripts/python/bin/sctop-report b/tools/perf/scripts/python/bin/sctop-report
index 36b409c..c32db29 100644
--- a/tools/perf/scripts/python/bin/sctop-report
+++ b/tools/perf/scripts/python/bin/sctop-report
@@ -21,4 +21,4 @@
     interval=$1
     shift
 fi
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
index 4eb88c9..16eb8d6 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
@@ -7,4 +7,4 @@
 	shift
     fi
 fi
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report
index cb2f9c5..0f0e9d4 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-report
@@ -7,4 +7,4 @@
 	shift
     fi
 fi
-perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index d9f7893..4647a76 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -1,4 +1,4 @@
-# perf trace event handlers, generated by perf trace -g python
+# perf script event handlers, generated by perf script -g python
 # (c) 2010, Tom Zanussi <tzanussi@gmail.com>
 # Licensed under the terms of the GNU GPL License version 2
 #
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index acd7848..85805fa 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -15,7 +15,7 @@
 from Core import *
 from Util import *
 
-usage = "perf trace -s syscall-counts-by-pid.py [comm|pid]\n";
+usage = "perf script -s syscall-counts-by-pid.py [comm|pid]\n";
 
 for_comm = None
 for_pid = None
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index b934383..74d55ec 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -4,7 +4,7 @@
 #
 # Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com>
 #
-# perf trace event handlers have been generated by perf trace -g python
+# perf script event handlers have been generated by perf script -g python
 #
 # This software is distributed under the terms of the GNU General
 # Public License ("GPL") version 2 as published by the Free Software
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 7a6ec2c..42c267e 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -17,7 +17,7 @@
 from Core import *
 from Util import *
 
-usage = "perf trace -s sctop.py [comm] [interval]\n";
+usage = "perf script -s sctop.py [comm] [interval]\n";
 
 for_comm = None
 default_interval = 3
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index d1ee3ec..c64d1c5 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -14,7 +14,7 @@
 from Core import *
 from Util import syscall_name
 
-usage = "perf trace -s syscall-counts-by-pid.py [comm]\n";
+usage = "perf script -s syscall-counts-by-pid.py [comm]\n";
 
 for_comm = None
 for_pid = None
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index ea183dc..b435d3f 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -15,7 +15,7 @@
 from Core import *
 from Util import syscall_name
 
-usage = "perf trace -s syscall-counts.py [comm]\n";
+usage = "perf script -s syscall-counts.py [comm]\n";
 
 for_comm = None
 
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e437edb..deffb8c 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -14,7 +14,9 @@
 #include <linux/kernel.h>
 #include "debug.h"
 
-static int build_id__mark_dso_hit(event_t *event, struct perf_session *session)
+static int build_id__mark_dso_hit(event_t *event,
+				  struct sample_data *sample __used,
+				  struct perf_session *session)
 {
 	struct addr_location al;
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -35,7 +37,8 @@
 	return 0;
 }
 
-static int event__exit_del_thread(event_t *self, struct perf_session *session)
+static int event__exit_del_thread(event_t *self, struct sample_data *sample __used,
+				  struct perf_session *session)
 {
 	struct thread *thread = perf_session__findnew(session, self->fork.tid);
 
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 0f9b8d7..3ccaa10 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -4,32 +4,53 @@
 #include <assert.h>
 #include <stdio.h>
 
-int cpumap[MAX_NR_CPUS];
-
-static int default_cpu_map(void)
+static struct cpu_map *cpu_map__default_new(void)
 {
-	int nr_cpus, i;
+	struct cpu_map *cpus;
+	int nr_cpus;
 
 	nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
-	assert(nr_cpus <= MAX_NR_CPUS);
-	assert((int)nr_cpus >= 0);
+	if (nr_cpus < 0)
+		return NULL;
 
-	for (i = 0; i < nr_cpus; ++i)
-		cpumap[i] = i;
+	cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
+	if (cpus != NULL) {
+		int i;
+		for (i = 0; i < nr_cpus; ++i)
+			cpus->map[i] = i;
 
-	return nr_cpus;
+		cpus->nr = nr_cpus;
+	}
+
+	return cpus;
 }
 
-static int read_all_cpu_map(void)
+static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
 {
+	size_t payload_size = nr_cpus * sizeof(int);
+	struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
+
+	if (cpus != NULL) {
+		cpus->nr = nr_cpus;
+		memcpy(cpus->map, tmp_cpus, payload_size);
+	}
+
+	return cpus;
+}
+
+static struct cpu_map *cpu_map__read_all_cpu_map(void)
+{
+	struct cpu_map *cpus = NULL;
 	FILE *onlnf;
 	int nr_cpus = 0;
+	int *tmp_cpus = NULL, *tmp;
+	int max_entries = 0;
 	int n, cpu, prev;
 	char sep;
 
 	onlnf = fopen("/sys/devices/system/cpu/online", "r");
 	if (!onlnf)
-		return default_cpu_map();
+		return cpu_map__default_new();
 
 	sep = 0;
 	prev = -1;
@@ -38,12 +59,28 @@
 		if (n <= 0)
 			break;
 		if (prev >= 0) {
-			assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS);
+			int new_max = nr_cpus + cpu - prev - 1;
+
+			if (new_max >= max_entries) {
+				max_entries = new_max + MAX_NR_CPUS / 2;
+				tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+				if (tmp == NULL)
+					goto out_free_tmp;
+				tmp_cpus = tmp;
+			}
+
 			while (++prev < cpu)
-				cpumap[nr_cpus++] = prev;
+				tmp_cpus[nr_cpus++] = prev;
 		}
-		assert (nr_cpus < MAX_NR_CPUS);
-		cpumap[nr_cpus++] = cpu;
+		if (nr_cpus == max_entries) {
+			max_entries += MAX_NR_CPUS;
+			tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+			if (tmp == NULL)
+				goto out_free_tmp;
+			tmp_cpus = tmp;
+		}
+
+		tmp_cpus[nr_cpus++] = cpu;
 		if (n == 2 && sep == '-')
 			prev = cpu;
 		else
@@ -51,24 +88,31 @@
 		if (n == 1 || sep == '\n')
 			break;
 	}
-	fclose(onlnf);
-	if (nr_cpus > 0)
-		return nr_cpus;
 
-	return default_cpu_map();
+	if (nr_cpus > 0)
+		cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
+	else
+		cpus = cpu_map__default_new();
+out_free_tmp:
+	free(tmp_cpus);
+	fclose(onlnf);
+	return cpus;
 }
 
-int read_cpu_map(const char *cpu_list)
+struct cpu_map *cpu_map__new(const char *cpu_list)
 {
+	struct cpu_map *cpus = NULL;
 	unsigned long start_cpu, end_cpu = 0;
 	char *p = NULL;
 	int i, nr_cpus = 0;
+	int *tmp_cpus = NULL, *tmp;
+	int max_entries = 0;
 
 	if (!cpu_list)
-		return read_all_cpu_map();
+		return cpu_map__read_all_cpu_map();
 
 	if (!isdigit(*cpu_list))
-		goto invalid;
+		goto out;
 
 	while (isdigit(*cpu_list)) {
 		p = NULL;
@@ -94,21 +138,42 @@
 		for (; start_cpu <= end_cpu; start_cpu++) {
 			/* check for duplicates */
 			for (i = 0; i < nr_cpus; i++)
-				if (cpumap[i] == (int)start_cpu)
+				if (tmp_cpus[i] == (int)start_cpu)
 					goto invalid;
 
-			assert(nr_cpus < MAX_NR_CPUS);
-			cpumap[nr_cpus++] = (int)start_cpu;
+			if (nr_cpus == max_entries) {
+				max_entries += MAX_NR_CPUS;
+				tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+				if (tmp == NULL)
+					goto invalid;
+				tmp_cpus = tmp;
+			}
+			tmp_cpus[nr_cpus++] = (int)start_cpu;
 		}
 		if (*p)
 			++p;
 
 		cpu_list = p;
 	}
-	if (nr_cpus > 0)
-		return nr_cpus;
 
-	return default_cpu_map();
+	if (nr_cpus > 0)
+		cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
+	else
+		cpus = cpu_map__default_new();
 invalid:
-	return -1;
+	free(tmp_cpus);
+out:
+	return cpus;
+}
+
+struct cpu_map *cpu_map__dummy_new(void)
+{
+	struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
+
+	if (cpus != NULL) {
+		cpus->nr = 1;
+		cpus->map[0] = -1;
+	}
+
+	return cpus;
 }
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 3e60f56..f7a4f42 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,7 +1,13 @@
 #ifndef __PERF_CPUMAP_H
 #define __PERF_CPUMAP_H
 
-extern int read_cpu_map(const char *cpu_list);
-extern int cpumap[];
+struct cpu_map {
+	int nr;
+	int map[];
+};
+
+struct cpu_map *cpu_map__new(const char *cpu_list);
+struct cpu_map *cpu_map__dummy_new(void);
+void *cpu_map__delete(struct cpu_map *map);
 
 #endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index c8d81b0..01bbe8e 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -46,20 +46,16 @@
 	return ret;
 }
 
-static int dump_printf_color(const char *fmt, const char *color, ...)
+#ifdef NO_NEWT_SUPPORT
+void ui__warning(const char *format, ...)
 {
 	va_list args;
-	int ret = 0;
 
-	if (dump_trace) {
-		va_start(args, color);
-		ret = color_vfprintf(stdout, color, fmt, args);
-		va_end(args);
-	}
-
-	return ret;
+	va_start(args, format);
+	vfprintf(stderr, format, args);
+	va_end(args);
 }
-
+#endif
 
 void trace_event(event_t *event)
 {
@@ -70,29 +66,29 @@
 	if (!dump_trace)
 		return;
 
-	dump_printf(".");
-	dump_printf_color("\n. ... raw event: size %d bytes\n", color,
-			  event->header.size);
+	printf(".");
+	color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
+		      event->header.size);
 
 	for (i = 0; i < event->header.size; i++) {
 		if ((i & 15) == 0) {
-			dump_printf(".");
-			dump_printf_color("  %04x: ", color, i);
+			printf(".");
+			color_fprintf(stdout, color, "  %04x: ", i);
 		}
 
-		dump_printf_color(" %02x", color, raw_event[i]);
+		color_fprintf(stdout, color, " %02x", raw_event[i]);
 
 		if (((i & 15) == 15) || i == event->header.size-1) {
-			dump_printf_color("  ", color);
+			color_fprintf(stdout, color, "  ");
 			for (j = 0; j < 15-(i & 15); j++)
-				dump_printf_color("   ", color);
+				color_fprintf(stdout, color, "   ");
 			for (j = i & ~15; j <= i; j++) {
-				dump_printf_color("%c", color,
-						isprint(raw_event[j]) ?
-						raw_event[j] : '.');
+				color_fprintf(stdout, color, "%c",
+					      isprint(raw_event[j]) ?
+					      raw_event[j] : '.');
 			}
-			dump_printf_color("\n", color);
+			color_fprintf(stdout, color, "\n");
 		}
 	}
-	dump_printf(".\n");
+	printf(".\n");
 }
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 7b51408..ca35fd6 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -35,4 +35,6 @@
 #include "ui/progress.h"
 #endif
 
+void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
+
 #endif	/* __PERF_DEBUG_H */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dab9e75..2302ec0 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -7,7 +7,7 @@
 #include "strlist.h"
 #include "thread.h"
 
-const char *event__name[] = {
+static const char *event__name[] = {
 	[0]			 = "TOTAL",
 	[PERF_RECORD_MMAP]	 = "MMAP",
 	[PERF_RECORD_LOST]	 = "LOST",
@@ -22,13 +22,31 @@
 	[PERF_RECORD_HEADER_EVENT_TYPE]	 = "EVENT_TYPE",
 	[PERF_RECORD_HEADER_TRACING_DATA]	 = "TRACING_DATA",
 	[PERF_RECORD_HEADER_BUILD_ID]	 = "BUILD_ID",
+	[PERF_RECORD_FINISHED_ROUND]	 = "FINISHED_ROUND",
 };
 
-static pid_t event__synthesize_comm(pid_t pid, int full,
+const char *event__get_event_name(unsigned int id)
+{
+	if (id >= ARRAY_SIZE(event__name))
+		return "INVALID";
+	if (!event__name[id])
+		return "UNKNOWN";
+	return event__name[id];
+}
+
+static struct sample_data synth_sample = {
+	.pid	   = -1,
+	.tid	   = -1,
+	.time	   = -1,
+	.stream_id = -1,
+	.cpu	   = -1,
+	.period	   = 1,
+};
+
+static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
 				    event__handler_t process,
 				    struct perf_session *session)
 {
-	event_t ev;
 	char filename[PATH_MAX];
 	char bf[BUFSIZ];
 	FILE *fp;
@@ -49,34 +67,39 @@
 		return 0;
 	}
 
-	memset(&ev.comm, 0, sizeof(ev.comm));
-	while (!ev.comm.comm[0] || !ev.comm.pid) {
-		if (fgets(bf, sizeof(bf), fp) == NULL)
-			goto out_failure;
+	memset(&event->comm, 0, sizeof(event->comm));
+
+	while (!event->comm.comm[0] || !event->comm.pid) {
+		if (fgets(bf, sizeof(bf), fp) == NULL) {
+			pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
+			goto out;
+		}
 
 		if (memcmp(bf, "Name:", 5) == 0) {
 			char *name = bf + 5;
 			while (*name && isspace(*name))
 				++name;
 			size = strlen(name) - 1;
-			memcpy(ev.comm.comm, name, size++);
+			memcpy(event->comm.comm, name, size++);
 		} else if (memcmp(bf, "Tgid:", 5) == 0) {
 			char *tgids = bf + 5;
 			while (*tgids && isspace(*tgids))
 				++tgids;
-			tgid = ev.comm.pid = atoi(tgids);
+			tgid = event->comm.pid = atoi(tgids);
 		}
 	}
 
-	ev.comm.header.type = PERF_RECORD_COMM;
+	event->comm.header.type = PERF_RECORD_COMM;
 	size = ALIGN(size, sizeof(u64));
-	ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size);
-
+	memset(event->comm.comm + size, 0, session->id_hdr_size);
+	event->comm.header.size = (sizeof(event->comm) -
+				(sizeof(event->comm.comm) - size) +
+				session->id_hdr_size);
 	if (!full) {
-		ev.comm.tid = pid;
+		event->comm.tid = pid;
 
-		process(&ev, session);
-		goto out_fclose;
+		process(event, &synth_sample, session);
+		goto out;
 	}
 
 	snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -91,22 +114,19 @@
 		if (*end)
 			continue;
 
-		ev.comm.tid = pid;
+		event->comm.tid = pid;
 
-		process(&ev, session);
+		process(event, &synth_sample, session);
 	}
+
 	closedir(tasks);
-
-out_fclose:
+out:
 	fclose(fp);
-	return tgid;
 
-out_failure:
-	pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
-	return -1;
+	return tgid;
 }
 
-static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
+static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
 					 event__handler_t process,
 					 struct perf_session *session)
 {
@@ -124,29 +144,25 @@
 		return -1;
 	}
 
+	event->header.type = PERF_RECORD_MMAP;
+	/*
+	 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
+	 */
+	event->header.misc = PERF_RECORD_MISC_USER;
+
 	while (1) {
 		char bf[BUFSIZ], *pbf = bf;
-		event_t ev = {
-			.header = {
-				.type = PERF_RECORD_MMAP,
-				/*
-				 * Just like the kernel, see __perf_event_mmap
-				 * in kernel/perf_event.c
-				 */
-				.misc = PERF_RECORD_MISC_USER,
-			 },
-		};
 		int n;
 		size_t size;
 		if (fgets(bf, sizeof(bf), fp) == NULL)
 			break;
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		n = hex2u64(pbf, &ev.mmap.start);
+		n = hex2u64(pbf, &event->mmap.start);
 		if (n < 0)
 			continue;
 		pbf += n + 1;
-		n = hex2u64(pbf, &ev.mmap.len);
+		n = hex2u64(pbf, &event->mmap.len);
 		if (n < 0)
 			continue;
 		pbf += n + 3;
@@ -161,19 +177,21 @@
 				continue;
 
 			pbf += 3;
-			n = hex2u64(pbf, &ev.mmap.pgoff);
+			n = hex2u64(pbf, &event->mmap.pgoff);
 
 			size = strlen(execname);
 			execname[size - 1] = '\0'; /* Remove \n */
-			memcpy(ev.mmap.filename, execname, size);
+			memcpy(event->mmap.filename, execname, size);
 			size = ALIGN(size, sizeof(u64));
-			ev.mmap.len -= ev.mmap.start;
-			ev.mmap.header.size = (sizeof(ev.mmap) -
-					       (sizeof(ev.mmap.filename) - size));
-			ev.mmap.pid = tgid;
-			ev.mmap.tid = pid;
+			event->mmap.len -= event->mmap.start;
+			event->mmap.header.size = (sizeof(event->mmap) -
+					        (sizeof(event->mmap.filename) - size));
+			memset(event->mmap.filename + size, 0, session->id_hdr_size);
+			event->mmap.header.size += session->id_hdr_size;
+			event->mmap.pid = tgid;
+			event->mmap.tid = pid;
 
-			process(&ev, session);
+			process(event, &synth_sample, session);
 		}
 	}
 
@@ -187,20 +205,27 @@
 {
 	struct rb_node *nd;
 	struct map_groups *kmaps = &machine->kmaps;
-	u16 misc;
+	event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
+
+	if (event == NULL) {
+		pr_debug("Not enough memory synthesizing mmap event "
+			 "for kernel modules\n");
+		return -1;
+	}
+
+	event->header.type = PERF_RECORD_MMAP;
 
 	/*
 	 * kernel uses 0 for user space maps, see kernel/perf_event.c
 	 * __perf_event_mmap
 	 */
 	if (machine__is_host(machine))
-		misc = PERF_RECORD_MISC_KERNEL;
+		event->header.misc = PERF_RECORD_MISC_KERNEL;
 	else
-		misc = PERF_RECORD_MISC_GUEST_KERNEL;
+		event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
 
 	for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
 	     nd; nd = rb_next(nd)) {
-		event_t ev;
 		size_t size;
 		struct map *pos = rb_entry(nd, struct map, rb_node);
 
@@ -208,39 +233,78 @@
 			continue;
 
 		size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
-		memset(&ev, 0, sizeof(ev));
-		ev.mmap.header.misc = misc;
-		ev.mmap.header.type = PERF_RECORD_MMAP;
-		ev.mmap.header.size = (sizeof(ev.mmap) -
-				        (sizeof(ev.mmap.filename) - size));
-		ev.mmap.start = pos->start;
-		ev.mmap.len   = pos->end - pos->start;
-		ev.mmap.pid   = machine->pid;
+		event->mmap.header.type = PERF_RECORD_MMAP;
+		event->mmap.header.size = (sizeof(event->mmap) -
+				        (sizeof(event->mmap.filename) - size));
+		memset(event->mmap.filename + size, 0, session->id_hdr_size);
+		event->mmap.header.size += session->id_hdr_size;
+		event->mmap.start = pos->start;
+		event->mmap.len   = pos->end - pos->start;
+		event->mmap.pid   = machine->pid;
 
-		memcpy(ev.mmap.filename, pos->dso->long_name,
+		memcpy(event->mmap.filename, pos->dso->long_name,
 		       pos->dso->long_name_len + 1);
-		process(&ev, session);
+		process(event, &synth_sample, session);
 	}
 
+	free(event);
 	return 0;
 }
 
+static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
+				      pid_t pid, event__handler_t process,
+				      struct perf_session *session)
+{
+	pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
+					    session);
+	if (tgid == -1)
+		return -1;
+	return event__synthesize_mmap_events(mmap_event, pid, tgid,
+					     process, session);
+}
+
 int event__synthesize_thread(pid_t pid, event__handler_t process,
 			     struct perf_session *session)
 {
-	pid_t tgid = event__synthesize_comm(pid, 1, process, session);
-	if (tgid == -1)
-		return -1;
-	return event__synthesize_mmap_events(pid, tgid, process, session);
+	event_t *comm_event, *mmap_event;
+	int err = -1;
+
+	comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
+	if (comm_event == NULL)
+		goto out;
+
+	mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
+	if (mmap_event == NULL)
+		goto out_free_comm;
+
+	err = __event__synthesize_thread(comm_event, mmap_event, pid,
+					 process, session);
+	free(mmap_event);
+out_free_comm:
+	free(comm_event);
+out:
+	return err;
 }
 
-void event__synthesize_threads(event__handler_t process,
-			       struct perf_session *session)
+int event__synthesize_threads(event__handler_t process,
+			      struct perf_session *session)
 {
 	DIR *proc;
 	struct dirent dirent, *next;
+	event_t *comm_event, *mmap_event;
+	int err = -1;
+
+	comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
+	if (comm_event == NULL)
+		goto out;
+
+	mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
+	if (mmap_event == NULL)
+		goto out_free_comm;
 
 	proc = opendir("/proc");
+	if (proc == NULL)
+		goto out_free_mmap;
 
 	while (!readdir_r(proc, &dirent, &next) && next) {
 		char *end;
@@ -249,10 +313,18 @@
 		if (*end) /* only interested in proper numerical dirents */
 			continue;
 
-		event__synthesize_thread(pid, process, session);
+		__event__synthesize_thread(comm_event, mmap_event, pid,
+					   process, session);
 	}
 
 	closedir(proc);
+	err = 0;
+out_free_mmap:
+	free(mmap_event);
+out_free_comm:
+	free(comm_event);
+out:
+	return err;
 }
 
 struct process_symbol_args {
@@ -260,7 +332,8 @@
 	u64	   start;
 };
 
-static int find_symbol_cb(void *arg, const char *name, char type, u64 start)
+static int find_symbol_cb(void *arg, const char *name, char type,
+			  u64 start, u64 end __used)
 {
 	struct process_symbol_args *args = arg;
 
@@ -286,18 +359,20 @@
 	char path[PATH_MAX];
 	char name_buff[PATH_MAX];
 	struct map *map;
-
-	event_t ev = {
-		.header = {
-			.type = PERF_RECORD_MMAP,
-		},
-	};
+	int err;
 	/*
 	 * We should get this from /sys/kernel/sections/.text, but till that is
 	 * available use this, and after it is use this as a fallback for older
 	 * kernels.
 	 */
 	struct process_symbol_args args = { .name = symbol_name, };
+	event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
+
+	if (event == NULL) {
+		pr_debug("Not enough memory synthesizing mmap event "
+			 "for kernel modules\n");
+		return -1;
+	}
 
 	mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
 	if (machine__is_host(machine)) {
@@ -305,10 +380,10 @@
 		 * kernel uses PERF_RECORD_MISC_USER for user space maps,
 		 * see kernel/perf_event.c __perf_event_mmap
 		 */
-		ev.header.misc = PERF_RECORD_MISC_KERNEL;
+		event->header.misc = PERF_RECORD_MISC_KERNEL;
 		filename = "/proc/kallsyms";
 	} else {
-		ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
+		event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
 		if (machine__is_default_guest(machine))
 			filename = (char *) symbol_conf.default_guest_kallsyms;
 		else {
@@ -321,17 +396,21 @@
 		return -ENOENT;
 
 	map = machine->vmlinux_maps[MAP__FUNCTION];
-	size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename),
+	size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
 			"%s%s", mmap_name, symbol_name) + 1;
 	size = ALIGN(size, sizeof(u64));
-	ev.mmap.header.size = (sizeof(ev.mmap) -
-			(sizeof(ev.mmap.filename) - size));
-	ev.mmap.pgoff = args.start;
-	ev.mmap.start = map->start;
-	ev.mmap.len   = map->end - ev.mmap.start;
-	ev.mmap.pid   = machine->pid;
+	event->mmap.header.type = PERF_RECORD_MMAP;
+	event->mmap.header.size = (sizeof(event->mmap) -
+			(sizeof(event->mmap.filename) - size) + session->id_hdr_size);
+	event->mmap.pgoff = args.start;
+	event->mmap.start = map->start;
+	event->mmap.len   = map->end - event->mmap.start;
+	event->mmap.pid   = machine->pid;
 
-	return process(&ev, session);
+	err = process(event, &synth_sample, session);
+	free(event);
+
+	return err;
 }
 
 static void thread__comm_adjust(struct thread *self, struct hists *hists)
@@ -361,7 +440,8 @@
 	return 0;
 }
 
-int event__process_comm(event_t *self, struct perf_session *session)
+int event__process_comm(event_t *self, struct sample_data *sample __used,
+			struct perf_session *session)
 {
 	struct thread *thread = perf_session__findnew(session, self->comm.tid);
 
@@ -376,7 +456,8 @@
 	return 0;
 }
 
-int event__process_lost(event_t *self, struct perf_session *session)
+int event__process_lost(event_t *self, struct sample_data *sample __used,
+			struct perf_session *session)
 {
 	dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
 	session->hists.stats.total_lost += self->lost.lost;
@@ -392,7 +473,7 @@
 	 * a zero sized synthesized MMAP event for the kernel.
 	 */
 	if (maps[MAP__FUNCTION]->end == 0)
-		maps[MAP__FUNCTION]->end = ~0UL;
+		maps[MAP__FUNCTION]->end = ~0ULL;
 }
 
 static int event__process_kernel_mmap(event_t *self,
@@ -485,7 +566,8 @@
 	return -1;
 }
 
-int event__process_mmap(event_t *self, struct perf_session *session)
+int event__process_mmap(event_t *self, struct sample_data *sample __used,
+			struct perf_session *session)
 {
 	struct machine *machine;
 	struct thread *thread;
@@ -526,7 +608,8 @@
 	return 0;
 }
 
-int event__process_task(event_t *self, struct perf_session *session)
+int event__process_task(event_t *self, struct sample_data *sample __used,
+			struct perf_session *session)
 {
 	struct thread *thread = perf_session__findnew(session, self->fork.tid);
 	struct thread *parent = perf_session__findnew(session, self->fork.ptid);
@@ -548,18 +631,19 @@
 	return 0;
 }
 
-int event__process(event_t *event, struct perf_session *session)
+int event__process(event_t *event, struct sample_data *sample,
+		   struct perf_session *session)
 {
 	switch (event->header.type) {
 	case PERF_RECORD_COMM:
-		event__process_comm(event, session);
+		event__process_comm(event, sample, session);
 		break;
 	case PERF_RECORD_MMAP:
-		event__process_mmap(event, session);
+		event__process_mmap(event, sample, session);
 		break;
 	case PERF_RECORD_FORK:
 	case PERF_RECORD_EXIT:
-		event__process_task(event, session);
+		event__process_task(event, sample, session);
 		break;
 	default:
 		break;
@@ -674,32 +758,8 @@
 			     symbol_filter_t filter)
 {
 	u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-	struct thread *thread;
+	struct thread *thread = perf_session__findnew(session, self->ip.pid);
 
-	event__parse_sample(self, session->sample_type, data);
-
-	dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n",
-		    self->header.misc, data->pid, data->tid, data->ip,
-		    data->period, data->cpu);
-
-	if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
-		unsigned int i;
-
-		dump_printf("... chain: nr:%Lu\n", data->callchain->nr);
-
-		if (!ip_callchain__valid(data->callchain, self)) {
-			pr_debug("call-chain problem with event, "
-				 "skipping it.\n");
-			goto out_filtered;
-		}
-
-		if (dump_trace) {
-			for (i = 0; i < data->callchain->nr; i++)
-				dump_printf("..... %2d: %016Lx\n",
-					    i, data->callchain->ips[i]);
-		}
-	}
-	thread = perf_session__findnew(session, self->ip.pid);
 	if (thread == NULL)
 		return -1;
 
@@ -766,9 +826,65 @@
 	return 0;
 }
 
-int event__parse_sample(const event_t *event, u64 type, struct sample_data *data)
+static int event__parse_id_sample(const event_t *event,
+				  struct perf_session *session,
+				  struct sample_data *sample)
 {
-	const u64 *array = event->sample.array;
+	const u64 *array;
+	u64 type;
+
+	sample->cpu = sample->pid = sample->tid = -1;
+	sample->stream_id = sample->id = sample->time = -1ULL;
+
+	if (!session->sample_id_all)
+		return 0;
+
+	array = event->sample.array;
+	array += ((event->header.size -
+		   sizeof(event->header)) / sizeof(u64)) - 1;
+	type = session->sample_type;
+
+	if (type & PERF_SAMPLE_CPU) {
+		u32 *p = (u32 *)array;
+		sample->cpu = *p;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_STREAM_ID) {
+		sample->stream_id = *array;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_ID) {
+		sample->id = *array;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_TIME) {
+		sample->time = *array;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_TID) {
+		u32 *p = (u32 *)array;
+		sample->pid = p[0];
+		sample->tid = p[1];
+	}
+
+	return 0;
+}
+
+int event__parse_sample(const event_t *event, struct perf_session *session,
+			struct sample_data *data)
+{
+	const u64 *array;
+	u64 type;
+
+	if (event->header.type != PERF_RECORD_SAMPLE)
+		return event__parse_id_sample(event, session, data);
+
+	array = event->sample.array;
+	type = session->sample_type;
 
 	if (type & PERF_SAMPLE_IP) {
 		data->ip = event->ip.ip;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8e790da..2b7e919 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -85,6 +85,7 @@
 };
 
 enum perf_user_event_type { /* above any possible kernel type */
+	PERF_RECORD_USER_TYPE_START		= 64,
 	PERF_RECORD_HEADER_ATTR			= 64,
 	PERF_RECORD_HEADER_EVENT_TYPE		= 65,
 	PERF_RECORD_HEADER_TRACING_DATA		= 66,
@@ -135,12 +136,15 @@
 
 struct perf_session;
 
-typedef int (*event__handler_t)(event_t *event, struct perf_session *session);
+typedef int (*event__handler_synth_t)(event_t *event, 
+				      struct perf_session *session);
+typedef int (*event__handler_t)(event_t *event, struct sample_data *sample,
+				struct perf_session *session);
 
 int event__synthesize_thread(pid_t pid, event__handler_t process,
 			     struct perf_session *session);
-void event__synthesize_threads(event__handler_t process,
-			       struct perf_session *session);
+int event__synthesize_threads(event__handler_t process,
+			      struct perf_session *session);
 int event__synthesize_kernel_mmap(event__handler_t process,
 				struct perf_session *session,
 				struct machine *machine,
@@ -150,18 +154,24 @@
 			      struct perf_session *session,
 			      struct machine *machine);
 
-int event__process_comm(event_t *self, struct perf_session *session);
-int event__process_lost(event_t *self, struct perf_session *session);
-int event__process_mmap(event_t *self, struct perf_session *session);
-int event__process_task(event_t *self, struct perf_session *session);
-int event__process(event_t *event, struct perf_session *session);
+int event__process_comm(event_t *self, struct sample_data *sample,
+			struct perf_session *session);
+int event__process_lost(event_t *self, struct sample_data *sample,
+			struct perf_session *session);
+int event__process_mmap(event_t *self, struct sample_data *sample,
+			struct perf_session *session);
+int event__process_task(event_t *self, struct sample_data *sample,
+			struct perf_session *session);
+int event__process(event_t *event, struct sample_data *sample,
+		   struct perf_session *session);
 
 struct addr_location;
 int event__preprocess_sample(const event_t *self, struct perf_session *session,
 			     struct addr_location *al, struct sample_data *data,
 			     symbol_filter_t filter);
-int event__parse_sample(const event_t *event, u64 type, struct sample_data *data);
+int event__parse_sample(const event_t *event, struct perf_session *session,
+			struct sample_data *sample);
 
-extern const char *event__name[];
+const char *event__get_event_name(unsigned int id);
 
 #endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
new file mode 100644
index 0000000..c95267e
--- /dev/null
+++ b/tools/perf/util/evsel.c
@@ -0,0 +1,186 @@
+#include "evsel.h"
+#include "../perf.h"
+#include "util.h"
+#include "cpumap.h"
+#include "thread.h"
+
+#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+
+struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx)
+{
+	struct perf_evsel *evsel = zalloc(sizeof(*evsel));
+
+	if (evsel != NULL) {
+		evsel->idx	   = idx;
+		evsel->attr.type   = type;
+		evsel->attr.config = config;
+		INIT_LIST_HEAD(&evsel->node);
+	}
+
+	return evsel;
+}
+
+int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
+{
+	evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
+	return evsel->fd != NULL ? 0 : -ENOMEM;
+}
+
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
+{
+	evsel->counts = zalloc((sizeof(*evsel->counts) +
+				(ncpus * sizeof(struct perf_counts_values))));
+	return evsel->counts != NULL ? 0 : -ENOMEM;
+}
+
+void perf_evsel__free_fd(struct perf_evsel *evsel)
+{
+	xyarray__delete(evsel->fd);
+	evsel->fd = NULL;
+}
+
+void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
+{
+	int cpu, thread;
+
+	for (cpu = 0; cpu < ncpus; cpu++)
+		for (thread = 0; thread < nthreads; ++thread) {
+			close(FD(evsel, cpu, thread));
+			FD(evsel, cpu, thread) = -1;
+		}
+}
+
+void perf_evsel__delete(struct perf_evsel *evsel)
+{
+	assert(list_empty(&evsel->node));
+	xyarray__delete(evsel->fd);
+	free(evsel);
+}
+
+int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
+			      int cpu, int thread, bool scale)
+{
+	struct perf_counts_values count;
+	size_t nv = scale ? 3 : 1;
+
+	if (FD(evsel, cpu, thread) < 0)
+		return -EINVAL;
+
+	if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
+		return -ENOMEM;
+
+	if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
+		return -errno;
+
+	if (scale) {
+		if (count.run == 0)
+			count.val = 0;
+		else if (count.run < count.ena)
+			count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
+	} else
+		count.ena = count.run = 0;
+
+	evsel->counts->cpu[cpu] = count;
+	return 0;
+}
+
+int __perf_evsel__read(struct perf_evsel *evsel,
+		       int ncpus, int nthreads, bool scale)
+{
+	size_t nv = scale ? 3 : 1;
+	int cpu, thread;
+	struct perf_counts_values *aggr = &evsel->counts->aggr, count;
+
+	aggr->val = 0;
+
+	for (cpu = 0; cpu < ncpus; cpu++) {
+		for (thread = 0; thread < nthreads; thread++) {
+			if (FD(evsel, cpu, thread) < 0)
+				continue;
+
+			if (readn(FD(evsel, cpu, thread),
+				  &count, nv * sizeof(u64)) < 0)
+				return -errno;
+
+			aggr->val += count.val;
+			if (scale) {
+				aggr->ena += count.ena;
+				aggr->run += count.run;
+			}
+		}
+	}
+
+	evsel->counts->scaled = 0;
+	if (scale) {
+		if (aggr->run == 0) {
+			evsel->counts->scaled = -1;
+			aggr->val = 0;
+			return 0;
+		}
+
+		if (aggr->run < aggr->ena) {
+			evsel->counts->scaled = 1;
+			aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
+		}
+	} else
+		aggr->ena = aggr->run = 0;
+
+	return 0;
+}
+
+int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus)
+{
+	int cpu;
+
+	if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, cpus->nr, 1) < 0)
+		return -1;
+
+	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		FD(evsel, cpu, 0) = sys_perf_event_open(&evsel->attr, -1,
+							cpus->map[cpu], -1, 0);
+		if (FD(evsel, cpu, 0) < 0)
+			goto out_close;
+	}
+
+	return 0;
+
+out_close:
+	while (--cpu >= 0) {
+		close(FD(evsel, cpu, 0));
+		FD(evsel, cpu, 0) = -1;
+	}
+	return -1;
+}
+
+int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads)
+{
+	int thread;
+
+	if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, 1, threads->nr))
+		return -1;
+
+	for (thread = 0; thread < threads->nr; thread++) {
+		FD(evsel, 0, thread) = sys_perf_event_open(&evsel->attr,
+							   threads->map[thread], -1, -1, 0);
+		if (FD(evsel, 0, thread) < 0)
+			goto out_close;
+	}
+
+	return 0;
+
+out_close:
+	while (--thread >= 0) {
+		close(FD(evsel, 0, thread));
+		FD(evsel, 0, thread) = -1;
+	}
+	return -1;
+}
+
+int perf_evsel__open(struct perf_evsel *evsel, 
+		     struct cpu_map *cpus, struct thread_map *threads)
+{
+	if (threads == NULL)
+		return perf_evsel__open_per_cpu(evsel, cpus);
+
+	return perf_evsel__open_per_thread(evsel, threads);
+}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
new file mode 100644
index 0000000..a0ccd69
--- /dev/null
+++ b/tools/perf/util/evsel.h
@@ -0,0 +1,115 @@
+#ifndef __PERF_EVSEL_H
+#define __PERF_EVSEL_H 1
+
+#include <linux/list.h>
+#include <stdbool.h>
+#include "../../../include/linux/perf_event.h"
+#include "types.h"
+#include "xyarray.h"
+ 
+struct perf_counts_values {
+	union {
+		struct {
+			u64 val;
+			u64 ena;
+			u64 run;
+		};
+		u64 values[3];
+	};
+};
+
+struct perf_counts {
+	s8		   	  scaled;
+	struct perf_counts_values aggr;
+	struct perf_counts_values cpu[];
+};
+
+struct perf_evsel {
+	struct list_head	node;
+	struct perf_event_attr	attr;
+	char			*filter;
+	struct xyarray		*fd;
+	struct perf_counts	*counts;
+	int			idx;
+	void			*priv;
+};
+
+struct cpu_map;
+struct thread_map;
+
+struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx);
+void perf_evsel__delete(struct perf_evsel *evsel);
+
+int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
+void perf_evsel__free_fd(struct perf_evsel *evsel);
+void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
+
+int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus);
+int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads);
+int perf_evsel__open(struct perf_evsel *evsel, 
+		     struct cpu_map *cpus, struct thread_map *threads);
+
+#define perf_evsel__match(evsel, t, c)		\
+	(evsel->attr.type == PERF_TYPE_##t &&	\
+	 evsel->attr.config == PERF_COUNT_##c)
+
+int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
+			      int cpu, int thread, bool scale);
+
+/**
+ * perf_evsel__read_on_cpu - Read out the results on a CPU and thread
+ *
+ * @evsel - event selector to read value
+ * @cpu - CPU of interest
+ * @thread - thread of interest
+ */
+static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel,
+					  int cpu, int thread)
+{
+	return __perf_evsel__read_on_cpu(evsel, cpu, thread, false);
+}
+
+/**
+ * perf_evsel__read_on_cpu_scaled - Read out the results on a CPU and thread, scaled
+ *
+ * @evsel - event selector to read value
+ * @cpu - CPU of interest
+ * @thread - thread of interest
+ */
+static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
+						 int cpu, int thread)
+{
+	return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
+}
+
+int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads,
+		       bool scale);
+
+/**
+ * perf_evsel__read - Read the aggregate results on all CPUs
+ *
+ * @evsel - event selector to read value
+ * @ncpus - Number of cpus affected, from zero
+ * @nthreads - Number of threads affected, from zero
+ */
+static inline int perf_evsel__read(struct perf_evsel *evsel,
+				    int ncpus, int nthreads)
+{
+	return __perf_evsel__read(evsel, ncpus, nthreads, false);
+}
+
+/**
+ * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled
+ *
+ * @evsel - event selector to read value
+ * @ncpus - Number of cpus affected, from zero
+ * @nthreads - Number of threads affected, from zero
+ */
+static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
+					  int ncpus, int nthreads)
+{
+	return __perf_evsel__read(evsel, ncpus, nthreads, true);
+}
+
+#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7cba055..989fa2d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -152,6 +152,11 @@
 	set_bit(feat, self->adds_features);
 }
 
+void perf_header__clear_feat(struct perf_header *self, int feat)
+{
+	clear_bit(feat, self->adds_features);
+}
+
 bool perf_header__has_feat(const struct perf_header *self, int feat)
 {
 	return test_bit(feat, self->adds_features);
@@ -433,8 +438,10 @@
 	int idx = 0, err;
 
 	session = container_of(self, struct perf_session, header);
-	if (perf_session__read_build_ids(session, true))
-		perf_header__set_feat(self, HEADER_BUILD_ID);
+
+	if (perf_header__has_feat(self, HEADER_BUILD_ID &&
+	    !perf_session__read_build_ids(session, true)))
+		perf_header__clear_feat(self, HEADER_BUILD_ID);
 
 	nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
 	if (!nr_sections)
@@ -456,7 +463,7 @@
 
 		/* Write trace info */
 		trace_sec->offset = lseek(fd, 0, SEEK_CUR);
-		read_tracing_data(fd, attrs, nr_counters);
+		read_tracing_data(fd, &evsel_list);
 		trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
 	}
 
@@ -599,7 +606,7 @@
 static int perf_header__getbuffer64(struct perf_header *self,
 				    int fd, void *buf, size_t size)
 {
-	if (do_read(fd, buf, size) <= 0)
+	if (readn(fd, buf, size) <= 0)
 		return -1;
 
 	if (self->needs_swap)
@@ -655,7 +662,7 @@
 {
 	lseek(fd, 0, SEEK_SET);
 
-	if (do_read(fd, self, sizeof(*self)) <= 0 ||
+	if (readn(fd, self, sizeof(*self)) <= 0 ||
 	    memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
 		return -1;
 
@@ -816,7 +823,7 @@
 				       struct perf_header *ph, int fd,
 				       bool repipe)
 {
-	if (do_read(fd, self, sizeof(*self)) <= 0 ||
+	if (readn(fd, self, sizeof(*self)) <= 0 ||
 	    memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
 		return -1;
 
@@ -941,6 +948,24 @@
 	return type;
 }
 
+bool perf_header__sample_id_all(const struct perf_header *header)
+{
+	bool value = false, first = true;
+	int i;
+
+	for (i = 0; i < header->attrs; i++) {
+		struct perf_header_attr *attr = header->attr[i];
+
+		if (first) {
+			value = attr->attr.sample_id_all;
+			first = false;
+		} else if (value != attr->attr.sample_id_all)
+			die("non matching sample_id_all");
+	}
+
+	return value;
+}
+
 struct perf_event_attr *
 perf_header__find_attr(u64 id, struct perf_header *header)
 {
@@ -987,21 +1012,23 @@
 
 	ev = malloc(size);
 
+	if (ev == NULL)
+		return -ENOMEM;
+
 	ev->attr.attr = *attr;
 	memcpy(ev->attr.id, id, ids * sizeof(u64));
 
 	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
 	ev->attr.header.size = size;
 
-	err = process(ev, session);
+	err = process(ev, NULL, session);
 
 	free(ev);
 
 	return err;
 }
 
-int event__synthesize_attrs(struct perf_header *self,
-			    event__handler_t process,
+int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
 			    struct perf_session *session)
 {
 	struct perf_header_attr	*attr;
@@ -1071,7 +1098,7 @@
 	ev.event_type.header.size = sizeof(ev.event_type) -
 		(sizeof(ev.event_type.event_type.name) - size);
 
-	err = process(&ev, session);
+	err = process(&ev, NULL, session);
 
 	return err;
 }
@@ -1106,8 +1133,7 @@
 	return 0;
 }
 
-int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
-				   int nb_events,
+int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
 				   event__handler_t process,
 				   struct perf_session *session __unused)
 {
@@ -1118,7 +1144,7 @@
 	memset(&ev, 0, sizeof(ev));
 
 	ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
-	size = read_tracing_data_size(fd, pattrs, nb_events);
+	size = read_tracing_data_size(fd, pattrs);
 	if (size <= 0)
 		return size;
 	aligned_size = ALIGN(size, sizeof(u64));
@@ -1126,9 +1152,9 @@
 	ev.tracing_data.header.size = sizeof(ev.tracing_data);
 	ev.tracing_data.size = aligned_size;
 
-	process(&ev, session);
+	process(&ev, NULL, session);
 
-	err = read_tracing_data(fd, pattrs, nb_events);
+	err = read_tracing_data(fd, pattrs);
 	write_padded(fd, NULL, 0, padding);
 
 	return aligned_size;
@@ -1186,7 +1212,7 @@
 	ev.build_id.header.size = sizeof(ev.build_id) + len;
 	memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
 
-	err = process(&ev, session);
+	err = process(&ev, NULL, session);
 
 	return err;
 }
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 402ac24..33f16be 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -81,9 +81,11 @@
 int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
 
 u64 perf_header__sample_type(struct perf_header *header);
+bool perf_header__sample_id_all(const struct perf_header *header);
 struct perf_event_attr *
 perf_header__find_attr(u64 id, struct perf_header *header);
 void perf_header__set_feat(struct perf_header *self, int feat);
+void perf_header__clear_feat(struct perf_header *self, int feat);
 bool perf_header__has_feat(const struct perf_header *self, int feat);
 
 int perf_header__process_sections(struct perf_header *self, int fd,
@@ -111,8 +113,7 @@
 int event__process_event_type(event_t *self,
 			      struct perf_session *session);
 
-int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
-				   int nb_events,
+int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
 				   event__handler_t process,
 				   struct perf_session *session);
 int event__process_tracing_data(event_t *self,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 2022e87..c749ba6 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -356,7 +356,7 @@
 
 static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
 				     int depth, int depth_mask, int period,
-				     u64 total_samples, int hits,
+				     u64 total_samples, u64 hits,
 				     int left_margin)
 {
 	int i;
@@ -1092,6 +1092,12 @@
 	FILE *file;
 	int err = 0;
 	u64 len;
+	char symfs_filename[PATH_MAX];
+
+	if (filename) {
+		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
+			 symbol_conf.symfs, filename);
+	}
 
 	if (filename == NULL) {
 		if (dso->has_build_id) {
@@ -1100,9 +1106,9 @@
 			return -ENOMEM;
 		}
 		goto fallback;
-	} else if (readlink(filename, command, sizeof(command)) < 0 ||
+	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
 		   strstr(command, "[kernel.kallsyms]") ||
-		   access(filename, R_OK)) {
+		   access(symfs_filename, R_OK)) {
 		free(filename);
 fallback:
 		/*
@@ -1111,6 +1117,8 @@
 		 * DSO is the same as when 'perf record' ran.
 		 */
 		filename = dso->long_name;
+		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
+			 symbol_conf.symfs, filename);
 		free_filename = false;
 	}
 
@@ -1137,7 +1145,7 @@
 		 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand",
 		 map__rip_2objdump(map, sym->start),
 		 map__rip_2objdump(map, sym->end),
-		 filename, filename);
+		 symfs_filename, filename);
 
 	pr_debug("Executing: %s\n", command);
 
@@ -1168,10 +1176,13 @@
 	size_t ret = 0;
 
 	for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
-		if (!event__name[i])
+		const char *name = event__get_event_name(i);
+
+		if (!strcmp(name, "UNKNOWN"))
 			continue;
-		ret += fprintf(fp, "%10s events: %10d\n",
-			       event__name[i], self->stats.nr_events[i]);
+
+		ret += fprintf(fp, "%16s events: %10d\n", name,
+			       self->stats.nr_events[i]);
 	}
 
 	return ret;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 587d375..ee78985 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,8 +52,10 @@
 struct events_stats {
 	u64 total_period;
 	u64 total_lost;
+	u64 total_invalid_chains;
 	u32 nr_events[PERF_RECORD_HEADER_MAX];
 	u32 nr_unknown_events;
+	u32 nr_invalid_chains;
 };
 
 enum hist_column {
diff --git a/tools/perf/util/include/asm/cpufeature.h b/tools/perf/util/include/asm/cpufeature.h
new file mode 100644
index 0000000..acffd5e
--- /dev/null
+++ b/tools/perf/util/include/asm/cpufeature.h
@@ -0,0 +1,9 @@
+
+#ifndef PERF_CPUFEATURE_H
+#define PERF_CPUFEATURE_H
+
+/* cpufeature.h ... dummy header file for including arch/x86/lib/memcpy_64.S */
+
+#define X86_FEATURE_REP_GOOD 0
+
+#endif	/* PERF_CPUFEATURE_H */
diff --git a/tools/perf/util/include/asm/dwarf2.h b/tools/perf/util/include/asm/dwarf2.h
new file mode 100644
index 0000000..bb4198e
--- /dev/null
+++ b/tools/perf/util/include/asm/dwarf2.h
@@ -0,0 +1,11 @@
+
+#ifndef PERF_DWARF2_H
+#define PERF_DWARF2_H
+
+/* dwarf2.h ... dummy header file for including arch/x86/lib/memcpy_64.S */
+
+#define CFI_STARTPROC
+#define CFI_ENDPROC
+
+#endif	/* PERF_DWARF2_H */
+
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index bb4ac2e..8be0b96 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -13,6 +13,11 @@
 	addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
 }
 
+static inline void clear_bit(int nr, unsigned long *addr)
+{
+	addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
+}
+
 static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
 {
 	return ((1UL << (nr % BITS_PER_LONG)) &
diff --git a/tools/perf/util/include/linux/linkage.h b/tools/perf/util/include/linux/linkage.h
new file mode 100644
index 0000000..06387cf
--- /dev/null
+++ b/tools/perf/util/include/linux/linkage.h
@@ -0,0 +1,13 @@
+
+#ifndef PERF_LINUX_LINKAGE_H_
+#define PERF_LINUX_LINKAGE_H_
+
+/* linkage.h ... for including arch/x86/lib/memcpy_64.S */
+
+#define ENTRY(name)				\
+	.globl name;				\
+	name:
+
+#define ENDPROC(name)
+
+#endif	/* PERF_LINUX_LINKAGE_H_ */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4af5bd5..649083f 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
 #include "../../../include/linux/hw_breakpoint.h"
 #include "util.h"
 #include "../perf.h"
+#include "evsel.h"
 #include "parse-options.h"
 #include "parse-events.h"
 #include "exec_cmd.h"
@@ -12,8 +13,7 @@
 
 int				nr_counters;
 
-struct perf_event_attr		attrs[MAX_COUNTERS];
-char				*filters[MAX_COUNTERS];
+LIST_HEAD(evsel_list);
 
 struct event_symbol {
 	u8		type;
@@ -266,10 +266,10 @@
 	return name;
 }
 
-const char *event_name(int counter)
+const char *event_name(struct perf_evsel *evsel)
 {
-	u64 config = attrs[counter].config;
-	int type = attrs[counter].type;
+	u64 config = evsel->attr.config;
+	int type = evsel->attr.type;
 
 	return __event_name(type, config);
 }
@@ -434,7 +434,7 @@
 	id = atoll(id_buf);
 	attr->config = id;
 	attr->type = PERF_TYPE_TRACEPOINT;
-	*strp = evt_name + evt_length;
+	*strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
 
 	attr->sample_type |= PERF_SAMPLE_RAW;
 	attr->sample_type |= PERF_SAMPLE_TIME;
@@ -495,7 +495,7 @@
 				    struct perf_event_attr *attr)
 {
 	const char *evt_name;
-	char *flags;
+	char *flags = NULL, *comma_loc;
 	char sys_name[MAX_EVENT_LENGTH];
 	unsigned int sys_length, evt_length;
 
@@ -514,6 +514,11 @@
 	sys_name[sys_length] = '\0';
 	evt_name = evt_name + 1;
 
+	comma_loc = strchr(evt_name, ',');
+	if (comma_loc) {
+		/* take the event name up to the comma */
+		evt_name = strndup(evt_name, comma_loc - evt_name);
+	}
 	flags = strchr(evt_name, ':');
 	if (flags) {
 		/* split it out: */
@@ -524,9 +529,8 @@
 	evt_length = strlen(evt_name);
 	if (evt_length >= MAX_EVENT_LENGTH)
 		return EVT_FAILED;
-
 	if (strpbrk(evt_name, "*?")) {
-		*strp = evt_name + evt_length;
+		*strp += strlen(sys_name) + evt_length;
 		return parse_multiple_tracepoint_event(sys_name, evt_name,
 						       flags);
 	} else
@@ -810,9 +814,6 @@
 			return -1;
 
 	for (;;) {
-		if (nr_counters == MAX_COUNTERS)
-			return -1;
-
 		memset(&attr, 0, sizeof(attr));
 		ret = parse_event_symbols(&str, &attr);
 		if (ret == EVT_FAILED)
@@ -822,8 +823,13 @@
 			return -1;
 
 		if (ret != EVT_HANDLED_ALL) {
-			attrs[nr_counters] = attr;
-			nr_counters++;
+			struct perf_evsel *evsel;
+			evsel = perf_evsel__new(attr.type, attr.config,
+						nr_counters);
+			if (evsel == NULL)
+				return -1;
+			list_add_tail(&evsel->node, &evsel_list);
+			++nr_counters;
 		}
 
 		if (*str == 0)
@@ -840,21 +846,22 @@
 int parse_filter(const struct option *opt __used, const char *str,
 		 int unset __used)
 {
-	int i = nr_counters - 1;
-	int len = strlen(str);
+	struct perf_evsel *last = NULL;
 
-	if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) {
+	if (!list_empty(&evsel_list))
+		last = list_entry(evsel_list.prev, struct perf_evsel, node);
+
+	if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
 		fprintf(stderr,
 			"-F option should follow a -e tracepoint option\n");
 		return -1;
 	}
 
-	filters[i] = malloc(len + 1);
-	if (!filters[i]) {
+	last->filter = strdup(str);
+	if (last->filter == NULL) {
 		fprintf(stderr, "not enough memory to hold filter string\n");
 		return -1;
 	}
-	strcpy(filters[i], str);
 
 	return 0;
 }
@@ -906,6 +913,47 @@
 }
 
 /*
+ * Check whether event is in <debugfs_mount_point>/tracing/events
+ */
+
+int is_valid_tracepoint(const char *event_string)
+{
+	DIR *sys_dir, *evt_dir;
+	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+	char evt_path[MAXPATHLEN];
+	char dir_path[MAXPATHLEN];
+
+	if (debugfs_valid_mountpoint(debugfs_path))
+		return 0;
+
+	sys_dir = opendir(debugfs_path);
+	if (!sys_dir)
+		return 0;
+
+	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
+
+		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
+			 sys_dirent.d_name);
+		evt_dir = opendir(dir_path);
+		if (!evt_dir)
+			continue;
+
+		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
+			snprintf(evt_path, MAXPATHLEN, "%s:%s",
+				 sys_dirent.d_name, evt_dirent.d_name);
+			if (!strcmp(evt_path, event_string)) {
+				closedir(evt_dir);
+				closedir(sys_dir);
+				return 1;
+			}
+		}
+		closedir(evt_dir);
+	}
+	closedir(sys_dir);
+	return 0;
+}
+
+/*
  * Print the help text for the event symbols:
  */
 void print_events(void)
@@ -963,3 +1011,26 @@
 
 	exit(129);
 }
+
+int perf_evsel_list__create_default(void)
+{
+	struct perf_evsel *evsel = perf_evsel__new(PERF_TYPE_HARDWARE,
+						   PERF_COUNT_HW_CPU_CYCLES, 0);
+	if (evsel == NULL)
+		return -ENOMEM;
+
+	list_add(&evsel->node, &evsel_list);
+	++nr_counters;
+	return 0;
+}
+
+void perf_evsel_list__delete(void)
+{
+	struct perf_evsel *pos, *n;
+
+	list_for_each_entry_safe(pos, n, &evsel_list, node) {
+		list_del_init(&pos->node);
+		perf_evsel__delete(pos);
+	}
+	nr_counters = 0;
+}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index fc4ab3f..b82cafb 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -4,6 +4,16 @@
  * Parse symbolic events/counts passed in as options:
  */
 
+#include "../../../include/linux/perf_event.h"
+
+struct list_head;
+struct perf_evsel;
+
+extern struct list_head evsel_list;
+
+int perf_evsel_list__create_default(void);
+void perf_evsel_list__delete(void);
+
 struct option;
 
 struct tracepoint_path {
@@ -13,14 +23,11 @@
 };
 
 extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
-extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events);
+extern bool have_tracepoints(struct list_head *evsel_list);
 
 extern int			nr_counters;
 
-extern struct perf_event_attr attrs[MAX_COUNTERS];
-extern char *filters[MAX_COUNTERS];
-
-extern const char *event_name(int ctr);
+const char *event_name(struct perf_evsel *event);
 extern const char *__event_name(int type, u64 config);
 
 extern int parse_events(const struct option *opt, const char *str, int unset);
@@ -29,9 +36,9 @@
 #define EVENTS_HELP_MAX (128*1024)
 
 extern void print_events(void);
+extern int is_valid_tracepoint(const char *event_string);
 
 extern char debugfs_path[];
 extern int valid_debugfs_mount(const char *debugfs);
 
-
 #endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index c7d72dc..abc31a1 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -119,6 +119,10 @@
 	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
 #define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
 	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
+#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
+	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
+	.value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
+	.flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
 
 /* parse_options() will filter out the processed options and leave the
  * non-option argments in argv[].
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 61191c6..128aaab 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -95,7 +95,7 @@
 		goto out;
 
 	if (machine__create_kernel_maps(&machine) < 0) {
-		pr_debug("machine__create_kernel_maps ");
+		pr_debug("machine__create_kernel_maps() failed.\n");
 		goto out;
 	}
 out:
@@ -149,7 +149,8 @@
 {
 	const char *path = kernel_get_module_path(module);
 	if (!path) {
-		pr_err("Failed to find path of %s module", module ?: "kernel");
+		pr_err("Failed to find path of %s module.\n",
+		       module ?: "kernel");
 		return -ENOENT;
 	}
 	pr_debug("Try to open %s\n", path);
@@ -226,7 +227,7 @@
 		pr_warning("Warning: No dwarf info found in the vmlinux - "
 			"please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
 		if (!need_dwarf) {
-			pr_debug("Trying to use symbols.\nn");
+			pr_debug("Trying to use symbols.\n");
 			return 0;
 		}
 	}
@@ -295,42 +296,49 @@
 #define LINEBUF_SIZE 256
 #define NR_ADDITIONAL_LINES 2
 
-static int show_one_line(FILE *fp, int l, bool skip, bool show_num)
+static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
 {
 	char buf[LINEBUF_SIZE];
-	const char *color = PERF_COLOR_BLUE;
+	const char *color = show_num ? "" : PERF_COLOR_BLUE;
+	const char *prefix = NULL;
 
-	if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
-		goto error;
-	if (!skip) {
-		if (show_num)
-			fprintf(stdout, "%7d  %s", l, buf);
-		else
-			color_fprintf(stdout, color, "         %s", buf);
-	}
-
-	while (strlen(buf) == LINEBUF_SIZE - 1 &&
-	       buf[LINEBUF_SIZE - 2] != '\n') {
+	do {
 		if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
 			goto error;
-		if (!skip) {
-			if (show_num)
-				fprintf(stdout, "%s", buf);
-			else
-				color_fprintf(stdout, color, "%s", buf);
+		if (skip)
+			continue;
+		if (!prefix) {
+			prefix = show_num ? "%7d  " : "         ";
+			color_fprintf(stdout, color, prefix, l);
 		}
-	}
+		color_fprintf(stdout, color, "%s", buf);
 
-	return 0;
+	} while (strchr(buf, '\n') == NULL);
+
+	return 1;
 error:
-	if (feof(fp))
-		pr_warning("Source file is shorter than expected.\n");
-	else
+	if (ferror(fp)) {
 		pr_warning("File read error: %s\n", strerror(errno));
-
-	return -1;
+		return -1;
+	}
+	return 0;
 }
 
+static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
+{
+	int rv = __show_one_line(fp, l, skip, show_num);
+	if (rv == 0) {
+		pr_warning("Source file is shorter than expected.\n");
+		rv = -1;
+	}
+	return rv;
+}
+
+#define show_one_line_with_num(f,l)	_show_one_line(f,l,false,true)
+#define show_one_line(f,l)		_show_one_line(f,l,false,false)
+#define skip_one_line(f,l)		_show_one_line(f,l,true,false)
+#define show_one_line_or_eof(f,l)	__show_one_line(f,l,false,false)
+
 /*
  * Show line-range always requires debuginfo to find source file and
  * line number.
@@ -379,7 +387,7 @@
 		fprintf(stdout, "<%s:%d>\n", lr->function,
 			lr->start - lr->offset);
 	else
-		fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
+		fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
 
 	fp = fopen(lr->path, "r");
 	if (fp == NULL) {
@@ -388,26 +396,30 @@
 		return -errno;
 	}
 	/* Skip to starting line number */
-	while (l < lr->start && ret >= 0)
-		ret = show_one_line(fp, l++, true, false);
-	if (ret < 0)
-		goto end;
+	while (l < lr->start) {
+		ret = skip_one_line(fp, l++);
+		if (ret < 0)
+			goto end;
+	}
 
 	list_for_each_entry(ln, &lr->line_list, list) {
-		while (ln->line > l && ret >= 0)
-			ret = show_one_line(fp, (l++) - lr->offset,
-					    false, false);
-		if (ret >= 0)
-			ret = show_one_line(fp, (l++) - lr->offset,
-					    false, true);
+		for (; ln->line > l; l++) {
+			ret = show_one_line(fp, l - lr->offset);
+			if (ret < 0)
+				goto end;
+		}
+		ret = show_one_line_with_num(fp, l++ - lr->offset);
 		if (ret < 0)
 			goto end;
 	}
 
 	if (lr->end == INT_MAX)
 		lr->end = l + NR_ADDITIONAL_LINES;
-	while (l <= lr->end && !feof(fp) && ret >= 0)
-		ret = show_one_line(fp, (l++) - lr->offset, false, false);
+	while (l <= lr->end) {
+		ret = show_one_line_or_eof(fp, l++ - lr->offset);
+		if (ret <= 0)
+			break;
+	}
 end:
 	fclose(fp);
 	return ret;
@@ -466,7 +478,7 @@
 
 	fd = open_vmlinux(module);
 	if (fd < 0) {
-		pr_warning("Failed to open debuginfo file.\n");
+		pr_warning("Failed to open debug information file.\n");
 		return fd;
 	}
 
@@ -526,56 +538,87 @@
 }
 #endif
 
+static int parse_line_num(char **ptr, int *val, const char *what)
+{
+	const char *start = *ptr;
+
+	errno = 0;
+	*val = strtol(*ptr, ptr, 0);
+	if (errno || *ptr == start) {
+		semantic_error("'%s' is not a valid number.\n", what);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Stuff 'lr' according to the line range described by 'arg'.
+ * The line range syntax is described by:
+ *
+ *         SRC[:SLN[+NUM|-ELN]]
+ *         FNC[:SLN[+NUM|-ELN]]
+ */
 int parse_line_range_desc(const char *arg, struct line_range *lr)
 {
-	const char *ptr;
-	char *tmp;
-	/*
-	 * <Syntax>
-	 * SRC:SLN[+NUM|-ELN]
-	 * FUNC[:SLN[+NUM|-ELN]]
-	 */
-	ptr = strchr(arg, ':');
-	if (ptr) {
-		lr->start = (int)strtoul(ptr + 1, &tmp, 0);
-		if (*tmp == '+') {
-			lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0);
-			lr->end--;	/*
-					 * Adjust the number of lines here.
-					 * If the number of lines == 1, the
-					 * the end of line should be equal to
-					 * the start of line.
-					 */
-		} else if (*tmp == '-')
-			lr->end = (int)strtoul(tmp + 1, &tmp, 0);
-		else
-			lr->end = INT_MAX;
+	char *range, *name = strdup(arg);
+	int err;
+
+	if (!name)
+		return -ENOMEM;
+
+	lr->start = 0;
+	lr->end = INT_MAX;
+
+	range = strchr(name, ':');
+	if (range) {
+		*range++ = '\0';
+
+		err = parse_line_num(&range, &lr->start, "start line");
+		if (err)
+			goto err;
+
+		if (*range == '+' || *range == '-') {
+			const char c = *range++;
+
+			err = parse_line_num(&range, &lr->end, "end line");
+			if (err)
+				goto err;
+
+			if (c == '+') {
+				lr->end += lr->start;
+				/*
+				 * Adjust the number of lines here.
+				 * If the number of lines == 1, the
+				 * the end of line should be equal to
+				 * the start of line.
+				 */
+				lr->end--;
+			}
+		}
+
 		pr_debug("Line range is %d to %d\n", lr->start, lr->end);
+
+		err = -EINVAL;
 		if (lr->start > lr->end) {
 			semantic_error("Start line must be smaller"
 				       " than end line.\n");
-			return -EINVAL;
+			goto err;
 		}
-		if (*tmp != '\0') {
-			semantic_error("Tailing with invalid character '%d'.\n",
-				       *tmp);
-			return -EINVAL;
+		if (*range != '\0') {
+			semantic_error("Tailing with invalid str '%s'.\n", range);
+			goto err;
 		}
-		tmp = strndup(arg, (ptr - arg));
-	} else {
-		tmp = strdup(arg);
-		lr->end = INT_MAX;
 	}
 
-	if (tmp == NULL)
-		return -ENOMEM;
-
-	if (strchr(tmp, '.'))
-		lr->file = tmp;
+	if (strchr(name, '.'))
+		lr->file = name;
 	else
-		lr->function = tmp;
+		lr->function = name;
 
 	return 0;
+err:
+	free(name);
+	return err;
 }
 
 /* Check the name is good for event/group */
@@ -699,39 +742,40 @@
 
 	/* Exclusion check */
 	if (pp->lazy_line && pp->line) {
-		semantic_error("Lazy pattern can't be used with line number.");
+		semantic_error("Lazy pattern can't be used with"
+			       " line number.\n");
 		return -EINVAL;
 	}
 
 	if (pp->lazy_line && pp->offset) {
-		semantic_error("Lazy pattern can't be used with offset.");
+		semantic_error("Lazy pattern can't be used with offset.\n");
 		return -EINVAL;
 	}
 
 	if (pp->line && pp->offset) {
-		semantic_error("Offset can't be used with line number.");
+		semantic_error("Offset can't be used with line number.\n");
 		return -EINVAL;
 	}
 
 	if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
 		semantic_error("File always requires line number or "
-			       "lazy pattern.");
+			       "lazy pattern.\n");
 		return -EINVAL;
 	}
 
 	if (pp->offset && !pp->function) {
-		semantic_error("Offset requires an entry function.");
+		semantic_error("Offset requires an entry function.\n");
 		return -EINVAL;
 	}
 
 	if (pp->retprobe && !pp->function) {
-		semantic_error("Return probe requires an entry function.");
+		semantic_error("Return probe requires an entry function.\n");
 		return -EINVAL;
 	}
 
 	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
 		semantic_error("Offset/Line/Lazy pattern can't be used with "
-			       "return probe.");
+			       "return probe.\n");
 		return -EINVAL;
 	}
 
@@ -1005,7 +1049,7 @@
 
 	return tmp - buf;
 error:
-	pr_debug("Failed to synthesize perf probe argument: %s",
+	pr_debug("Failed to synthesize perf probe argument: %s\n",
 		 strerror(-ret));
 	return ret;
 }
@@ -1033,13 +1077,13 @@
 			goto error;
 	}
 	if (pp->file) {
-		len = strlen(pp->file) - 31;
-		if (len < 0)
-			len = 0;
-		tmp = strchr(pp->file + len, '/');
-		if (!tmp)
-			tmp = pp->file + len;
-		ret = e_snprintf(file, 32, "@%s", tmp + 1);
+		tmp = pp->file;
+		len = strlen(tmp);
+		if (len > 30) {
+			tmp = strchr(pp->file + len - 30, '/');
+			tmp = tmp ? tmp + 1 : pp->file + len - 30;
+		}
+		ret = e_snprintf(file, 32, "@%s", tmp);
 		if (ret <= 0)
 			goto error;
 	}
@@ -1055,7 +1099,7 @@
 
 	return buf;
 error:
-	pr_debug("Failed to synthesize perf probe point: %s",
+	pr_debug("Failed to synthesize perf probe point: %s\n",
 		 strerror(-ret));
 	if (buf)
 		free(buf);
@@ -1796,7 +1840,7 @@
 
 	ret = e_snprintf(buf, 128, "%s:%s", group, event);
 	if (ret < 0) {
-		pr_err("Failed to copy event.");
+		pr_err("Failed to copy event.\n");
 		return ret;
 	}
 
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ddf4d45..ab83b6a 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -652,8 +652,8 @@
 	regs = get_arch_regstr(regn);
 	if (!regs) {
 		/* This should be a bug in DWARF or this tool */
-		pr_warning("Mapping for DWARF register number %u "
-			   "missing on this architecture.", regn);
+		pr_warning("Mapping for the register number %u "
+			   "missing on this architecture.\n", regn);
 		return -ERANGE;
 	}
 
@@ -699,13 +699,14 @@
 		if (ret != DW_TAG_pointer_type &&
 		    ret != DW_TAG_array_type) {
 			pr_warning("Failed to cast into string: "
-				   "%s(%s) is not a pointer nor array.",
+				   "%s(%s) is not a pointer nor array.\n",
 				   dwarf_diename(vr_die), dwarf_diename(&type));
 			return -EINVAL;
 		}
 		if (ret == DW_TAG_pointer_type) {
 			if (die_get_real_type(&type, &type) == NULL) {
-				pr_warning("Failed to get a type information.");
+				pr_warning("Failed to get a type"
+					   " information.\n");
 				return -ENOENT;
 			}
 			while (*ref_ptr)
@@ -720,7 +721,7 @@
 		if (!die_compare_name(&type, "char") &&
 		    !die_compare_name(&type, "unsigned char")) {
 			pr_warning("Failed to cast into string: "
-				   "%s is not (unsigned) char *.",
+				   "%s is not (unsigned) char *.\n",
 				   dwarf_diename(vr_die));
 			return -EINVAL;
 		}
@@ -830,8 +831,8 @@
 			return -EINVAL;
 		}
 		if (field->name[0] == '[') {
-			pr_err("Semantic error: %s is not a pointor nor array.",
-			       varname);
+			pr_err("Semantic error: %s is not a pointor"
+			       " nor array.\n", varname);
 			return -EINVAL;
 		}
 		if (field->ref) {
@@ -978,7 +979,7 @@
 	name = dwarf_diename(sp_die);
 	if (name) {
 		if (dwarf_entrypc(sp_die, &eaddr) != 0) {
-			pr_warning("Failed to get entry pc of %s\n",
+			pr_warning("Failed to get entry address of %s\n",
 				   dwarf_diename(sp_die));
 			return -ENOENT;
 		}
@@ -994,7 +995,7 @@
 	if (retprobe) {
 		if (eaddr != paddr) {
 			pr_warning("Return probe must be on the head of"
-				   " a real function\n");
+				   " a real function.\n");
 			return -EINVAL;
 		}
 		tp->retprobe = true;
@@ -1033,7 +1034,7 @@
 		Dwarf_Frame *frame;
 		if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
 		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
-			pr_warning("Failed to get CFA on 0x%jx\n",
+			pr_warning("Failed to get call frame on 0x%jx\n",
 				   (uintmax_t)pf->addr);
 			return -ENOENT;
 		}
@@ -1060,7 +1061,7 @@
 	int ret = 0;
 
 	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
-		pr_warning("No source lines found in this CU.\n");
+		pr_warning("No source lines found.\n");
 		return -ENOENT;
 	}
 
@@ -1162,7 +1163,7 @@
 	}
 
 	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
-		pr_warning("No source lines found in this CU.\n");
+		pr_warning("No source lines found.\n");
 		return -ENOENT;
 	}
 
@@ -1220,7 +1221,7 @@
 	else {
 		/* Get probe address */
 		if (dwarf_entrypc(in_die, &addr) != 0) {
-			pr_warning("Failed to get entry pc of %s.\n",
+			pr_warning("Failed to get entry address of %s.\n",
 				   dwarf_diename(in_die));
 			param->retval = -ENOENT;
 			return DWARF_CB_ABORT;
@@ -1261,8 +1262,8 @@
 			param->retval = find_probe_point_lazy(sp_die, pf);
 		else {
 			if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
-				pr_warning("Failed to get entry pc of %s.\n",
-					   dwarf_diename(sp_die));
+				pr_warning("Failed to get entry address of "
+					   "%s.\n", dwarf_diename(sp_die));
 				param->retval = -ENOENT;
 				return DWARF_CB_ABORT;
 			}
@@ -1304,7 +1305,7 @@
 
 	dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
 	if (!dbg) {
-		pr_warning("No dwarf info found in the vmlinux - "
+		pr_warning("No debug information found in the vmlinux - "
 			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
 		return -EBADF;
 	}
@@ -1549,7 +1550,7 @@
 	/* Open the live linux kernel */
 	dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
 	if (!dbg) {
-		pr_warning("No dwarf info found in the vmlinux - "
+		pr_warning("No debug information found in the vmlinux - "
 			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
 		ret = -EINVAL;
 		goto end;
@@ -1559,7 +1560,8 @@
 	addr += bias;
 	/* Find cu die */
 	if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
-		pr_warning("No CU DIE is found at %lx\n", addr);
+		pr_warning("Failed to find debug information for address %lx\n",
+			   addr);
 		ret = -EINVAL;
 		goto end;
 	}
@@ -1684,7 +1686,7 @@
 
 	line_list__init(&lf->lr->line_list);
 	if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
-		pr_warning("No source lines found in this CU.\n");
+		pr_warning("No source lines found.\n");
 		return -ENOENT;
 	}
 
@@ -1809,7 +1811,7 @@
 
 	dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
 	if (!dbg) {
-		pr_warning("No dwarf info found in the vmlinux - "
+		pr_warning("No debug information found in the vmlinux - "
 			"please rebuild with CONFIG_DEBUG_INFO=y.\n");
 		return -EBADF;
 	}
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index bba69d4..beaefc3 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -34,9 +34,9 @@
 				  bool externs);
 
 #include <dwarf.h>
-#include <libdw.h>
-#include <libdwfl.h>
-#include <version.h>
+#include <elfutils/libdw.h>
+#include <elfutils/libdwfl.h>
+#include <elfutils/version.h>
 
 struct probe_finder {
 	struct perf_probe_event	*pev;		/* Target probe event */
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b059dc5..9368081 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -1,5 +1,5 @@
 /*
- * trace-event-perl.  Feed perf trace events to an embedded Perl interpreter.
+ * trace-event-perl.  Feed perf script events to an embedded Perl interpreter.
  *
  * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
  *
@@ -411,8 +411,8 @@
 		return -1;
 	}
 
-	fprintf(ofp, "# perf trace event handlers, "
-		"generated by perf trace -g perl\n");
+	fprintf(ofp, "# perf script event handlers, "
+		"generated by perf script -g perl\n");
 
 	fprintf(ofp, "# Licensed under the terms of the GNU GPL"
 		" License version 2\n\n");
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 33a6325..c6d9933 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -442,8 +442,8 @@
 		fprintf(stderr, "couldn't open %s\n", fname);
 		return -1;
 	}
-	fprintf(ofp, "# perf trace event handlers, "
-		"generated by perf trace -g python\n");
+	fprintf(ofp, "# perf script event handlers, "
+		"generated by perf script -g python\n");
 
 	fprintf(ofp, "# Licensed under the terms of the GNU GPL"
 		" License version 2\n\n");
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fa9d652..6fb4694 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -65,9 +65,49 @@
 	return -1;
 }
 
+static void perf_session__id_header_size(struct perf_session *session)
+{
+       struct sample_data *data;
+       u64 sample_type = session->sample_type;
+       u16 size = 0;
+
+	if (!session->sample_id_all)
+		goto out;
+
+       if (sample_type & PERF_SAMPLE_TID)
+               size += sizeof(data->tid) * 2;
+
+       if (sample_type & PERF_SAMPLE_TIME)
+               size += sizeof(data->time);
+
+       if (sample_type & PERF_SAMPLE_ID)
+               size += sizeof(data->id);
+
+       if (sample_type & PERF_SAMPLE_STREAM_ID)
+               size += sizeof(data->stream_id);
+
+       if (sample_type & PERF_SAMPLE_CPU)
+               size += sizeof(data->cpu) * 2;
+out:
+       session->id_hdr_size = size;
+}
+
+void perf_session__set_sample_id_all(struct perf_session *session, bool value)
+{
+	session->sample_id_all = value;
+	perf_session__id_header_size(session);
+}
+
+void perf_session__set_sample_type(struct perf_session *session, u64 type)
+{
+	session->sample_type = type;
+}
+
 void perf_session__update_sample_type(struct perf_session *self)
 {
 	self->sample_type = perf_header__sample_type(&self->header);
+	self->sample_id_all = perf_header__sample_id_all(&self->header);
+	perf_session__id_header_size(self);
 }
 
 int perf_session__create_kernel_maps(struct perf_session *self)
@@ -85,7 +125,9 @@
 	machines__destroy_guest_kernel_maps(&self->machines);
 }
 
-struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe)
+struct perf_session *perf_session__new(const char *filename, int mode,
+				       bool force, bool repipe,
+				       struct perf_event_ops *ops)
 {
 	size_t len = filename ? strlen(filename) + 1 : 0;
 	struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -101,10 +143,20 @@
 	INIT_LIST_HEAD(&self->dead_threads);
 	self->hists_tree = RB_ROOT;
 	self->last_match = NULL;
-	self->mmap_window = 32;
+	/*
+	 * On 64bit we can mmap the data file in one go. No need for tiny mmap
+	 * slices. On 32bit we use 32MB.
+	 */
+#if BITS_PER_LONG == 64
+	self->mmap_window = ULLONG_MAX;
+#else
+	self->mmap_window = 32 * 1024 * 1024ULL;
+#endif
 	self->machines = RB_ROOT;
 	self->repipe = repipe;
-	INIT_LIST_HEAD(&self->ordered_samples.samples_head);
+	INIT_LIST_HEAD(&self->ordered_samples.samples);
+	INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
+	INIT_LIST_HEAD(&self->ordered_samples.to_free);
 	machine__init(&self->host_machine, "", HOST_KERNEL_ID);
 
 	if (mode == O_RDONLY) {
@@ -120,6 +172,13 @@
 	}
 
 	perf_session__update_sample_type(self);
+
+	if (ops && ops->ordering_requires_timestamps &&
+	    ops->ordered_samples && !self->sample_id_all) {
+		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
+		ops->ordered_samples = false;
+	}
+
 out:
 	return self;
 out_free:
@@ -230,7 +289,15 @@
 	return syms;
 }
 
+static int process_event_synth_stub(event_t *event __used,
+				    struct perf_session *session __used)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 static int process_event_stub(event_t *event __used,
+			      struct sample_data *sample __used,
 			      struct perf_session *session __used)
 {
 	dump_printf(": unhandled!\n");
@@ -262,7 +329,7 @@
 	if (handler->exit == NULL)
 		handler->exit = process_event_stub;
 	if (handler->lost == NULL)
-		handler->lost = process_event_stub;
+		handler->lost = event__process_lost;
 	if (handler->read == NULL)
 		handler->read = process_event_stub;
 	if (handler->throttle == NULL)
@@ -270,13 +337,13 @@
 	if (handler->unthrottle == NULL)
 		handler->unthrottle = process_event_stub;
 	if (handler->attr == NULL)
-		handler->attr = process_event_stub;
+		handler->attr = process_event_synth_stub;
 	if (handler->event_type == NULL)
-		handler->event_type = process_event_stub;
+		handler->event_type = process_event_synth_stub;
 	if (handler->tracing_data == NULL)
-		handler->tracing_data = process_event_stub;
+		handler->tracing_data = process_event_synth_stub;
 	if (handler->build_id == NULL)
-		handler->build_id = process_event_stub;
+		handler->build_id = process_event_synth_stub;
 	if (handler->finished_round == NULL) {
 		if (handler->ordered_samples)
 			handler->finished_round = process_finished_round;
@@ -386,33 +453,61 @@
 
 struct sample_queue {
 	u64			timestamp;
-	struct sample_event	*event;
+	u64			file_offset;
+	event_t			*event;
 	struct list_head	list;
 };
 
+static void perf_session_free_sample_buffers(struct perf_session *session)
+{
+	struct ordered_samples *os = &session->ordered_samples;
+
+	while (!list_empty(&os->to_free)) {
+		struct sample_queue *sq;
+
+		sq = list_entry(os->to_free.next, struct sample_queue, list);
+		list_del(&sq->list);
+		free(sq);
+	}
+}
+
+static int perf_session_deliver_event(struct perf_session *session,
+				      event_t *event,
+				      struct sample_data *sample,
+				      struct perf_event_ops *ops,
+				      u64 file_offset);
+
 static void flush_sample_queue(struct perf_session *s,
 			       struct perf_event_ops *ops)
 {
-	struct list_head *head = &s->ordered_samples.samples_head;
-	u64 limit = s->ordered_samples.next_flush;
+	struct ordered_samples *os = &s->ordered_samples;
+	struct list_head *head = &os->samples;
 	struct sample_queue *tmp, *iter;
+	struct sample_data sample;
+	u64 limit = os->next_flush;
+	u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
 
 	if (!ops->ordered_samples || !limit)
 		return;
 
 	list_for_each_entry_safe(iter, tmp, head, list) {
 		if (iter->timestamp > limit)
-			return;
+			break;
 
-		if (iter == s->ordered_samples.last_inserted)
-			s->ordered_samples.last_inserted = NULL;
+		event__parse_sample(iter->event, s, &sample);
+		perf_session_deliver_event(s, iter->event, &sample, ops,
+					   iter->file_offset);
 
-		ops->sample((event_t *)iter->event, s);
-
-		s->ordered_samples.last_flush = iter->timestamp;
+		os->last_flush = iter->timestamp;
 		list_del(&iter->list);
-		free(iter->event);
-		free(iter);
+		list_add(&iter->list, &os->sample_cache);
+	}
+
+	if (list_empty(head)) {
+		os->last_sample = NULL;
+	} else if (last_ts <= limit) {
+		os->last_sample =
+			list_entry(head->prev, struct sample_queue, list);
 	}
 }
 
@@ -465,178 +560,265 @@
 	return 0;
 }
 
-static void __queue_sample_end(struct sample_queue *new, struct list_head *head)
-{
-	struct sample_queue *iter;
-
-	list_for_each_entry_reverse(iter, head, list) {
-		if (iter->timestamp < new->timestamp) {
-			list_add(&new->list, &iter->list);
-			return;
-		}
-	}
-
-	list_add(&new->list, head);
-}
-
-static void __queue_sample_before(struct sample_queue *new,
-				  struct sample_queue *iter,
-				  struct list_head *head)
-{
-	list_for_each_entry_continue_reverse(iter, head, list) {
-		if (iter->timestamp < new->timestamp) {
-			list_add(&new->list, &iter->list);
-			return;
-		}
-	}
-
-	list_add(&new->list, head);
-}
-
-static void __queue_sample_after(struct sample_queue *new,
-				 struct sample_queue *iter,
-				 struct list_head *head)
-{
-	list_for_each_entry_continue(iter, head, list) {
-		if (iter->timestamp > new->timestamp) {
-			list_add_tail(&new->list, &iter->list);
-			return;
-		}
-	}
-	list_add_tail(&new->list, head);
-}
-
 /* The queue is ordered by time */
-static void __queue_sample_event(struct sample_queue *new,
-				 struct perf_session *s)
+static void __queue_event(struct sample_queue *new, struct perf_session *s)
 {
-	struct sample_queue *last_inserted = s->ordered_samples.last_inserted;
-	struct list_head *head = &s->ordered_samples.samples_head;
+	struct ordered_samples *os = &s->ordered_samples;
+	struct sample_queue *sample = os->last_sample;
+	u64 timestamp = new->timestamp;
+	struct list_head *p;
 
+	os->last_sample = new;
 
-	if (!last_inserted) {
-		__queue_sample_end(new, head);
+	if (!sample) {
+		list_add(&new->list, &os->samples);
+		os->max_timestamp = timestamp;
 		return;
 	}
 
 	/*
-	 * Most of the time the current event has a timestamp
-	 * very close to the last event inserted, unless we just switched
-	 * to another event buffer. Having a sorting based on a list and
-	 * on the last inserted event that is close to the current one is
-	 * probably more efficient than an rbtree based sorting.
+	 * last_sample might point to some random place in the list as it's
+	 * the last queued event. We expect that the new event is close to
+	 * this.
 	 */
-	if (last_inserted->timestamp >= new->timestamp)
-		__queue_sample_before(new, last_inserted, head);
-	else
-		__queue_sample_after(new, last_inserted, head);
+	if (sample->timestamp <= timestamp) {
+		while (sample->timestamp <= timestamp) {
+			p = sample->list.next;
+			if (p == &os->samples) {
+				list_add_tail(&new->list, &os->samples);
+				os->max_timestamp = timestamp;
+				return;
+			}
+			sample = list_entry(p, struct sample_queue, list);
+		}
+		list_add_tail(&new->list, &sample->list);
+	} else {
+		while (sample->timestamp > timestamp) {
+			p = sample->list.prev;
+			if (p == &os->samples) {
+				list_add(&new->list, &os->samples);
+				return;
+			}
+			sample = list_entry(p, struct sample_queue, list);
+		}
+		list_add(&new->list, &sample->list);
+	}
 }
 
-static int queue_sample_event(event_t *event, struct sample_data *data,
-			      struct perf_session *s)
+#define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct sample_queue))
+
+static int perf_session_queue_event(struct perf_session *s, event_t *event,
+				    struct sample_data *data, u64 file_offset)
 {
+	struct ordered_samples *os = &s->ordered_samples;
+	struct list_head *sc = &os->sample_cache;
 	u64 timestamp = data->time;
 	struct sample_queue *new;
 
+	if (!timestamp || timestamp == ~0ULL)
+		return -ETIME;
 
 	if (timestamp < s->ordered_samples.last_flush) {
 		printf("Warning: Timestamp below last timeslice flush\n");
 		return -EINVAL;
 	}
 
-	new = malloc(sizeof(*new));
-	if (!new)
-		return -ENOMEM;
+	if (!list_empty(sc)) {
+		new = list_entry(sc->next, struct sample_queue, list);
+		list_del(&new->list);
+	} else if (os->sample_buffer) {
+		new = os->sample_buffer + os->sample_buffer_idx;
+		if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
+			os->sample_buffer = NULL;
+	} else {
+		os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
+		if (!os->sample_buffer)
+			return -ENOMEM;
+		list_add(&os->sample_buffer->list, &os->to_free);
+		os->sample_buffer_idx = 2;
+		new = os->sample_buffer + 1;
+	}
 
 	new->timestamp = timestamp;
+	new->file_offset = file_offset;
+	new->event = event;
 
-	new->event = malloc(event->header.size);
-	if (!new->event) {
-		free(new);
-		return -ENOMEM;
+	__queue_event(new, s);
+
+	return 0;
+}
+
+static void callchain__printf(struct sample_data *sample)
+{
+	unsigned int i;
+
+	printf("... chain: nr:%Lu\n", sample->callchain->nr);
+
+	for (i = 0; i < sample->callchain->nr; i++)
+		printf("..... %2d: %016Lx\n", i, sample->callchain->ips[i]);
+}
+
+static void perf_session__print_tstamp(struct perf_session *session,
+				       event_t *event,
+				       struct sample_data *sample)
+{
+	if (event->header.type != PERF_RECORD_SAMPLE &&
+	    !session->sample_id_all) {
+		fputs("-1 -1 ", stdout);
+		return;
 	}
 
-	memcpy(new->event, event, event->header.size);
+	if ((session->sample_type & PERF_SAMPLE_CPU))
+		printf("%u ", sample->cpu);
 
-	__queue_sample_event(new, s);
-	s->ordered_samples.last_inserted = new;
-
-	if (new->timestamp > s->ordered_samples.max_timestamp)
-		s->ordered_samples.max_timestamp = new->timestamp;
-
-	return 0;
+	if (session->sample_type & PERF_SAMPLE_TIME)
+		printf("%Lu ", sample->time);
 }
 
-static int perf_session__process_sample(event_t *event, struct perf_session *s,
-					struct perf_event_ops *ops)
+static void dump_event(struct perf_session *session, event_t *event,
+		       u64 file_offset, struct sample_data *sample)
 {
-	struct sample_data data;
+	if (!dump_trace)
+		return;
 
-	if (!ops->ordered_samples)
-		return ops->sample(event, s);
+	printf("\n%#Lx [%#x]: event: %d\n", file_offset, event->header.size,
+	       event->header.type);
 
-	bzero(&data, sizeof(struct sample_data));
-	event__parse_sample(event, s->sample_type, &data);
-
-	queue_sample_event(event, &data, s);
-
-	return 0;
-}
-
-static int perf_session__process_event(struct perf_session *self,
-				       event_t *event,
-				       struct perf_event_ops *ops,
-				       u64 offset, u64 head)
-{
 	trace_event(event);
 
-	if (event->header.type < PERF_RECORD_HEADER_MAX) {
-		dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
-			    offset + head, event->header.size,
-			    event__name[event->header.type]);
-		hists__inc_nr_events(&self->hists, event->header.type);
-	}
+	if (sample)
+		perf_session__print_tstamp(session, event, sample);
 
-	if (self->header.needs_swap && event__swap_ops[event->header.type])
-		event__swap_ops[event->header.type](event);
+	printf("%#Lx [%#x]: PERF_RECORD_%s", file_offset, event->header.size,
+	       event__get_event_name(event->header.type));
+}
+
+static void dump_sample(struct perf_session *session, event_t *event,
+			struct sample_data *sample)
+{
+	if (!dump_trace)
+		return;
+
+	printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
+	       sample->pid, sample->tid, sample->ip, sample->period);
+
+	if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
+		callchain__printf(sample);
+}
+
+static int perf_session_deliver_event(struct perf_session *session,
+				      event_t *event,
+				      struct sample_data *sample,
+				      struct perf_event_ops *ops,
+				      u64 file_offset)
+{
+	dump_event(session, event, file_offset, sample);
 
 	switch (event->header.type) {
 	case PERF_RECORD_SAMPLE:
-		return perf_session__process_sample(event, self, ops);
+		dump_sample(session, event, sample);
+		return ops->sample(event, sample, session);
 	case PERF_RECORD_MMAP:
-		return ops->mmap(event, self);
+		return ops->mmap(event, sample, session);
 	case PERF_RECORD_COMM:
-		return ops->comm(event, self);
+		return ops->comm(event, sample, session);
 	case PERF_RECORD_FORK:
-		return ops->fork(event, self);
+		return ops->fork(event, sample, session);
 	case PERF_RECORD_EXIT:
-		return ops->exit(event, self);
+		return ops->exit(event, sample, session);
 	case PERF_RECORD_LOST:
-		return ops->lost(event, self);
+		return ops->lost(event, sample, session);
 	case PERF_RECORD_READ:
-		return ops->read(event, self);
+		return ops->read(event, sample, session);
 	case PERF_RECORD_THROTTLE:
-		return ops->throttle(event, self);
+		return ops->throttle(event, sample, session);
 	case PERF_RECORD_UNTHROTTLE:
-		return ops->unthrottle(event, self);
-	case PERF_RECORD_HEADER_ATTR:
-		return ops->attr(event, self);
-	case PERF_RECORD_HEADER_EVENT_TYPE:
-		return ops->event_type(event, self);
-	case PERF_RECORD_HEADER_TRACING_DATA:
-		/* setup for reading amidst mmap */
-		lseek(self->fd, offset + head, SEEK_SET);
-		return ops->tracing_data(event, self);
-	case PERF_RECORD_HEADER_BUILD_ID:
-		return ops->build_id(event, self);
-	case PERF_RECORD_FINISHED_ROUND:
-		return ops->finished_round(event, self, ops);
+		return ops->unthrottle(event, sample, session);
 	default:
-		++self->hists.stats.nr_unknown_events;
+		++session->hists.stats.nr_unknown_events;
 		return -1;
 	}
 }
 
+static int perf_session__preprocess_sample(struct perf_session *session,
+					   event_t *event, struct sample_data *sample)
+{
+	if (event->header.type != PERF_RECORD_SAMPLE ||
+	    !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
+		return 0;
+
+	if (!ip_callchain__valid(sample->callchain, event)) {
+		pr_debug("call-chain problem with event, skipping it.\n");
+		++session->hists.stats.nr_invalid_chains;
+		session->hists.stats.total_invalid_chains += sample->period;
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int perf_session__process_user_event(struct perf_session *session, event_t *event,
+					    struct perf_event_ops *ops, u64 file_offset)
+{
+	dump_event(session, event, file_offset, NULL);
+
+	/* These events are processed right away */
+	switch (event->header.type) {
+	case PERF_RECORD_HEADER_ATTR:
+		return ops->attr(event, session);
+	case PERF_RECORD_HEADER_EVENT_TYPE:
+		return ops->event_type(event, session);
+	case PERF_RECORD_HEADER_TRACING_DATA:
+		/* setup for reading amidst mmap */
+		lseek(session->fd, file_offset, SEEK_SET);
+		return ops->tracing_data(event, session);
+	case PERF_RECORD_HEADER_BUILD_ID:
+		return ops->build_id(event, session);
+	case PERF_RECORD_FINISHED_ROUND:
+		return ops->finished_round(event, session, ops);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int perf_session__process_event(struct perf_session *session,
+				       event_t *event,
+				       struct perf_event_ops *ops,
+				       u64 file_offset)
+{
+	struct sample_data sample;
+	int ret;
+
+	if (session->header.needs_swap && event__swap_ops[event->header.type])
+		event__swap_ops[event->header.type](event);
+
+	if (event->header.type >= PERF_RECORD_HEADER_MAX)
+		return -EINVAL;
+
+	hists__inc_nr_events(&session->hists, event->header.type);
+
+	if (event->header.type >= PERF_RECORD_USER_TYPE_START)
+		return perf_session__process_user_event(session, event, ops, file_offset);
+
+	/*
+	 * For all kernel events we get the sample data
+	 */
+	event__parse_sample(event, session, &sample);
+
+	/* Preprocess sample records - precheck callchains */
+	if (perf_session__preprocess_sample(session, event, &sample))
+		return 0;
+
+	if (ops->ordered_samples) {
+		ret = perf_session_queue_event(session, event, &sample,
+					       file_offset);
+		if (ret != -ETIME)
+			return ret;
+	}
+
+	return perf_session_deliver_event(session, event, &sample, ops,
+					  file_offset);
+}
+
 void perf_event_header__bswap(struct perf_event_header *self)
 {
 	self->type = bswap_32(self->type);
@@ -656,21 +838,33 @@
 	return thread;
 }
 
-int do_read(int fd, void *buf, size_t size)
+static void perf_session__warn_about_errors(const struct perf_session *session,
+					    const struct perf_event_ops *ops)
 {
-	void *buf_start = buf;
-
-	while (size) {
-		int ret = read(fd, buf, size);
-
-		if (ret <= 0)
-			return ret;
-
-		size -= ret;
-		buf += ret;
+	if (ops->lost == event__process_lost &&
+	    session->hists.stats.total_lost != 0) {
+		ui__warning("Processed %Lu events and LOST %Lu!\n\n"
+			    "Check IO/CPU overload!\n\n",
+			    session->hists.stats.total_period,
+			    session->hists.stats.total_lost);
 	}
 
-	return buf - buf_start;
+	if (session->hists.stats.nr_unknown_events != 0) {
+		ui__warning("Found %u unknown events!\n\n"
+			    "Is this an older tool processing a perf.data "
+			    "file generated by a more recent tool?\n\n"
+			    "If that is not the case, consider "
+			    "reporting to linux-kernel@vger.kernel.org.\n\n",
+			    session->hists.stats.nr_unknown_events);
+	}
+
+ 	if (session->hists.stats.nr_invalid_chains != 0) {
+ 		ui__warning("Found invalid callchains!\n\n"
+ 			    "%u out of %u events were discarded for this reason.\n\n"
+ 			    "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
+ 			    session->hists.stats.nr_invalid_chains,
+ 			    session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
+ 	}
 }
 
 #define session_done()	(*(volatile int *)(&session_done))
@@ -690,7 +884,7 @@
 
 	head = 0;
 more:
-	err = do_read(self->fd, &event, sizeof(struct perf_event_header));
+	err = readn(self->fd, &event, sizeof(struct perf_event_header));
 	if (err <= 0) {
 		if (err == 0)
 			goto done;
@@ -710,8 +904,7 @@
 	p += sizeof(struct perf_event_header);
 
 	if (size - sizeof(struct perf_event_header)) {
-		err = do_read(self->fd, p,
-			      size - sizeof(struct perf_event_header));
+		err = readn(self->fd, p, size - sizeof(struct perf_event_header));
 		if (err <= 0) {
 			if (err == 0) {
 				pr_err("unexpected end of event stream\n");
@@ -724,8 +917,7 @@
 	}
 
 	if (size == 0 ||
-	    (skip = perf_session__process_event(self, &event, ops,
-						0, head)) < 0) {
+	    (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
 		dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
 			    head, event.header.size, event.header.type);
 		/*
@@ -740,9 +932,6 @@
 
 	head += size;
 
-	dump_printf("\n%#Lx [%#x]: event: %d\n",
-		    head, event.header.size, event.header.type);
-
 	if (skip > 0)
 		head += skip;
 
@@ -751,82 +940,91 @@
 done:
 	err = 0;
 out_err:
+	perf_session__warn_about_errors(self, ops);
+	perf_session_free_sample_buffers(self);
 	return err;
 }
 
-int __perf_session__process_events(struct perf_session *self,
+int __perf_session__process_events(struct perf_session *session,
 				   u64 data_offset, u64 data_size,
 				   u64 file_size, struct perf_event_ops *ops)
 {
-	int err, mmap_prot, mmap_flags;
-	u64 head, shift;
-	u64 offset = 0;
-	size_t	page_size;
+	u64 head, page_offset, file_offset, file_pos, progress_next;
+	int err, mmap_prot, mmap_flags, map_idx = 0;
+	struct ui_progress *progress;
+	size_t	page_size, mmap_size;
+	char *buf, *mmaps[8];
 	event_t *event;
 	uint32_t size;
-	char *buf;
-	struct ui_progress *progress = ui_progress__new("Processing events...",
-							self->size);
-	if (progress == NULL)
-		return -1;
 
 	perf_event_ops__fill_defaults(ops);
 
 	page_size = sysconf(_SC_PAGESIZE);
 
-	head = data_offset;
-	shift = page_size * (head / page_size);
-	offset += shift;
-	head -= shift;
+	page_offset = page_size * (data_offset / page_size);
+	file_offset = page_offset;
+	head = data_offset - page_offset;
+
+	if (data_offset + data_size < file_size)
+		file_size = data_offset + data_size;
+
+	progress_next = file_size / 16;
+	progress = ui_progress__new("Processing events...", file_size);
+	if (progress == NULL)
+		return -1;
+
+	mmap_size = session->mmap_window;
+	if (mmap_size > file_size)
+		mmap_size = file_size;
+
+	memset(mmaps, 0, sizeof(mmaps));
 
 	mmap_prot  = PROT_READ;
 	mmap_flags = MAP_SHARED;
 
-	if (self->header.needs_swap) {
+	if (session->header.needs_swap) {
 		mmap_prot  |= PROT_WRITE;
 		mmap_flags = MAP_PRIVATE;
 	}
 remap:
-	buf = mmap(NULL, page_size * self->mmap_window, mmap_prot,
-		   mmap_flags, self->fd, offset);
+	buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd,
+		   file_offset);
 	if (buf == MAP_FAILED) {
 		pr_err("failed to mmap file\n");
 		err = -errno;
 		goto out_err;
 	}
+	mmaps[map_idx] = buf;
+	map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
+	file_pos = file_offset + head;
 
 more:
 	event = (event_t *)(buf + head);
-	ui_progress__update(progress, offset);
 
-	if (self->header.needs_swap)
+	if (session->header.needs_swap)
 		perf_event_header__bswap(&event->header);
 	size = event->header.size;
 	if (size == 0)
 		size = 8;
 
-	if (head + event->header.size >= page_size * self->mmap_window) {
-		int munmap_ret;
+	if (head + event->header.size >= mmap_size) {
+		if (mmaps[map_idx]) {
+			munmap(mmaps[map_idx], mmap_size);
+			mmaps[map_idx] = NULL;
+		}
 
-		shift = page_size * (head / page_size);
-
-		munmap_ret = munmap(buf, page_size * self->mmap_window);
-		assert(munmap_ret == 0);
-
-		offset += shift;
-		head -= shift;
+		page_offset = page_size * (head / page_size);
+		file_offset += page_offset;
+		head -= page_offset;
 		goto remap;
 	}
 
 	size = event->header.size;
 
-	dump_printf("\n%#Lx [%#x]: event: %d\n",
-		    offset + head, event->header.size, event->header.type);
-
 	if (size == 0 ||
-	    perf_session__process_event(self, event, ops, offset, head) < 0) {
+	    perf_session__process_event(session, event, ops, file_pos) < 0) {
 		dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
-			    offset + head, event->header.size,
+			    file_offset + head, event->header.size,
 			    event->header.type);
 		/*
 		 * assume we lost track of the stream, check alignment, and
@@ -839,19 +1037,24 @@
 	}
 
 	head += size;
+	file_pos += size;
 
-	if (offset + head >= data_offset + data_size)
-		goto done;
+	if (file_pos >= progress_next) {
+		progress_next += file_size / 16;
+		ui_progress__update(progress, file_pos);
+	}
 
-	if (offset + head < file_size)
+	if (file_pos < file_size)
 		goto more;
-done:
+
 	err = 0;
 	/* do the final flush for ordered samples */
-	self->ordered_samples.next_flush = ULLONG_MAX;
-	flush_sample_queue(self, ops);
+	session->ordered_samples.next_flush = ULLONG_MAX;
+	flush_sample_queue(session, ops);
 out_err:
 	ui_progress__delete(progress);
+	perf_session__warn_about_errors(session, ops);
+	perf_session_free_sample_buffers(session);
 	return err;
 }
 
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 9fa0fc2..decd83f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -17,8 +17,12 @@
 	u64			last_flush;
 	u64			next_flush;
 	u64			max_timestamp;
-	struct list_head	samples_head;
-	struct sample_queue	*last_inserted;
+	struct list_head	samples;
+	struct list_head	sample_cache;
+	struct list_head	to_free;
+	struct sample_queue	*sample_buffer;
+	struct sample_queue	*last_sample;
+	int			sample_buffer_idx;
 };
 
 struct perf_session {
@@ -42,6 +46,8 @@
 	int			fd;
 	bool			fd_pipe;
 	bool			repipe;
+	bool			sample_id_all;
+	u16			id_hdr_size;
 	int			cwdlen;
 	char			*cwd;
 	struct ordered_samples	ordered_samples;
@@ -50,7 +56,9 @@
 
 struct perf_event_ops;
 
-typedef int (*event_op)(event_t *self, struct perf_session *session);
+typedef int (*event_op)(event_t *self, struct sample_data *sample,
+			struct perf_session *session);
+typedef int (*event_synth_op)(event_t *self, struct perf_session *session);
 typedef int (*event_op2)(event_t *self, struct perf_session *session,
 			 struct perf_event_ops *ops);
 
@@ -63,16 +71,19 @@
 			lost,
 			read,
 			throttle,
-			unthrottle,
-			attr,
+			unthrottle;
+	event_synth_op	attr,
 			event_type,
 			tracing_data,
 			build_id;
 	event_op2	finished_round;
 	bool		ordered_samples;
+	bool		ordering_requires_timestamps;
 };
 
-struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe);
+struct perf_session *perf_session__new(const char *filename, int mode,
+				       bool force, bool repipe,
+				       struct perf_event_ops *ops);
 void perf_session__delete(struct perf_session *self);
 
 void perf_event_header__bswap(struct perf_event_header *self);
@@ -98,8 +109,9 @@
 
 int perf_session__create_kernel_maps(struct perf_session *self);
 
-int do_read(int fd, void *buf, size_t size);
 void perf_session__update_sample_type(struct perf_session *self);
+void perf_session__set_sample_id_all(struct perf_session *session, bool value);
+void perf_session__set_sample_type(struct perf_session *session, u64 type);
 void perf_session__remove_thread(struct perf_session *self, struct thread *th);
 
 static inline
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b62a553..f44fa54 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -170,7 +170,7 @@
 		return repsep_snprintf(bf, size, "%-*s", width, dso_name);
 	}
 
-	return repsep_snprintf(bf, size, "%*Lx", width, self->ip);
+	return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
 }
 
 /* --sort symbol */
@@ -196,7 +196,7 @@
 
 	if (verbose) {
 		char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
-		ret += repsep_snprintf(bf, size, "%*Lx %c ",
+		ret += repsep_snprintf(bf, size, "%-#*llx %c ",
 				       BITS_PER_LONG / 4, self->ip, o);
 	}
 
@@ -205,7 +205,7 @@
 		ret += repsep_snprintf(bf + ret, size - ret, "%s",
 				       self->ms.sym->name);
 	else
-		ret += repsep_snprintf(bf + ret, size - ret, "%*Lx",
+		ret += repsep_snprintf(bf + ret, size - ret, "%-#*llx",
 				       BITS_PER_LONG / 4, self->ip);
 
 	return ret;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 439ab94..15ccfba 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -22,6 +22,10 @@
 #include <limits.h>
 #include <sys/utsname.h>
 
+#ifndef KSYM_NAME_LEN
+#define KSYM_NAME_LEN 128
+#endif
+
 #ifndef NT_GNU_BUILD_ID
 #define NT_GNU_BUILD_ID 3
 #endif
@@ -41,6 +45,7 @@
 	.exclude_other	  = true,
 	.use_modules	  = true,
 	.try_vmlinux_path = true,
+	.symfs            = "",
 };
 
 int dso__name_len(const struct dso *self)
@@ -92,7 +97,7 @@
 		prev = curr;
 		curr = rb_entry(nd, struct symbol, rb_node);
 
-		if (prev->end == prev->start)
+		if (prev->end == prev->start && prev->end != curr->start)
 			prev->end = curr->start - 1;
 	}
 
@@ -121,7 +126,7 @@
 	 * We still haven't the actual symbols, so guess the
 	 * last map final address.
 	 */
-	curr->end = ~0UL;
+	curr->end = ~0ULL;
 }
 
 static void map_groups__fixup_end(struct map_groups *self)
@@ -425,16 +430,25 @@
 
 int kallsyms__parse(const char *filename, void *arg,
 		    int (*process_symbol)(void *arg, const char *name,
-						     char type, u64 start))
+					  char type, u64 start, u64 end))
 {
 	char *line = NULL;
 	size_t n;
-	int err = 0;
+	int err = -1;
+	u64 prev_start = 0;
+	char prev_symbol_type = 0;
+	char *prev_symbol_name;
 	FILE *file = fopen(filename, "r");
 
 	if (file == NULL)
 		goto out_failure;
 
+	prev_symbol_name = malloc(KSYM_NAME_LEN);
+	if (prev_symbol_name == NULL)
+		goto out_close;
+
+	err = 0;
+
 	while (!feof(file)) {
 		u64 start;
 		int line_len, len;
@@ -454,14 +468,33 @@
 			continue;
 
 		symbol_type = toupper(line[len]);
-		symbol_name = line + len + 2;
+		len += 2;
+		symbol_name = line + len;
+		len = line_len - len;
 
-		err = process_symbol(arg, symbol_name, symbol_type, start);
-		if (err)
+		if (len >= KSYM_NAME_LEN) {
+			err = -1;
 			break;
+		}
+
+		if (prev_symbol_type) {
+			u64 end = start;
+			if (end != prev_start)
+				--end;
+			err = process_symbol(arg, prev_symbol_name,
+					     prev_symbol_type, prev_start, end);
+			if (err)
+				break;
+		}
+
+		memcpy(prev_symbol_name, symbol_name, len + 1);
+		prev_symbol_type = symbol_type;
+		prev_start = start;
 	}
 
+	free(prev_symbol_name);
 	free(line);
+out_close:
 	fclose(file);
 	return err;
 
@@ -483,7 +516,7 @@
 }
 
 static int map__process_kallsym_symbol(void *arg, const char *name,
-				       char type, u64 start)
+				       char type, u64 start, u64 end)
 {
 	struct symbol *sym;
 	struct process_kallsyms_args *a = arg;
@@ -492,11 +525,8 @@
 	if (!symbol_type__is_a(type, a->map->type))
 		return 0;
 
-	/*
-	 * Will fix up the end later, when we have all symbols sorted.
-	 */
-	sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
-
+	sym = symbol__new(start, end - start + 1,
+			  kallsyms2elf_type(type), name);
 	if (sym == NULL)
 		return -ENOMEM;
 	/*
@@ -649,7 +679,6 @@
 	if (dso__load_all_kallsyms(self, filename, map) < 0)
 		return -1;
 
-	symbols__fixup_end(&self->symbols[map->type]);
 	if (self->kernel == DSO_TYPE_GUEST_KERNEL)
 		self->origin = DSO__ORIG_GUEST_KERNEL;
 	else
@@ -839,8 +868,11 @@
 	char sympltname[1024];
 	Elf *elf;
 	int nr = 0, symidx, fd, err = 0;
+	char name[PATH_MAX];
 
-	fd = open(self->long_name, O_RDONLY);
+	snprintf(name, sizeof(name), "%s%s",
+		 symbol_conf.symfs, self->long_name);
+	fd = open(name, O_RDONLY);
 	if (fd < 0)
 		goto out;
 
@@ -1452,16 +1484,19 @@
 	     self->origin++) {
 		switch (self->origin) {
 		case DSO__ORIG_BUILD_ID_CACHE:
-			if (dso__build_id_filename(self, name, size) == NULL)
+			/* skip the locally configured cache if a symfs is given */
+			if (symbol_conf.symfs[0] ||
+			    (dso__build_id_filename(self, name, size) == NULL)) {
 				continue;
+			}
 			break;
 		case DSO__ORIG_FEDORA:
-			snprintf(name, size, "/usr/lib/debug%s.debug",
-				 self->long_name);
+			snprintf(name, size, "%s/usr/lib/debug%s.debug",
+				 symbol_conf.symfs, self->long_name);
 			break;
 		case DSO__ORIG_UBUNTU:
-			snprintf(name, size, "/usr/lib/debug%s",
-				 self->long_name);
+			snprintf(name, size, "%s/usr/lib/debug%s",
+				 symbol_conf.symfs, self->long_name);
 			break;
 		case DSO__ORIG_BUILDID: {
 			char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -1473,19 +1508,26 @@
 					  sizeof(self->build_id),
 					  build_id_hex);
 			snprintf(name, size,
-				 "/usr/lib/debug/.build-id/%.2s/%s.debug",
-				 build_id_hex, build_id_hex + 2);
+				 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
+				 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
 			}
 			break;
 		case DSO__ORIG_DSO:
-			snprintf(name, size, "%s", self->long_name);
+			snprintf(name, size, "%s%s",
+			     symbol_conf.symfs, self->long_name);
 			break;
 		case DSO__ORIG_GUEST_KMODULE:
 			if (map->groups && map->groups->machine)
 				root_dir = map->groups->machine->root_dir;
 			else
 				root_dir = "";
-			snprintf(name, size, "%s%s", root_dir, self->long_name);
+			snprintf(name, size, "%s%s%s", symbol_conf.symfs,
+				 root_dir, self->long_name);
+			break;
+
+		case DSO__ORIG_KMODULE:
+			snprintf(name, size, "%s%s", symbol_conf.symfs,
+				 self->long_name);
 			break;
 
 		default:
@@ -1784,17 +1826,20 @@
 		      const char *vmlinux, symbol_filter_t filter)
 {
 	int err = -1, fd;
+	char symfs_vmlinux[PATH_MAX];
 
-	fd = open(vmlinux, O_RDONLY);
+	snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s",
+		 symbol_conf.symfs, vmlinux);
+	fd = open(symfs_vmlinux, O_RDONLY);
 	if (fd < 0)
 		return -1;
 
 	dso__set_loaded(self, map->type);
-	err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0);
+	err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
 	close(fd);
 
 	if (err > 0)
-		pr_debug("Using %s for symbols\n", vmlinux);
+		pr_debug("Using %s for symbols\n", symfs_vmlinux);
 
 	return err;
 }
@@ -1836,8 +1881,8 @@
 	const char *kallsyms_filename = NULL;
 	char *kallsyms_allocated_filename = NULL;
 	/*
-	 * Step 1: if the user specified a vmlinux filename, use it and only
-	 * it, reporting errors to the user if it cannot be used.
+	 * Step 1: if the user specified a kallsyms or vmlinux filename, use
+	 * it and only it, reporting errors to the user if it cannot be used.
 	 *
 	 * For instance, try to analyse an ARM perf.data file _without_ a
 	 * build-id, or if the user specifies the wrong path to the right
@@ -1850,6 +1895,11 @@
 	 * validation in dso__load_vmlinux and will bail out if they don't
 	 * match.
 	 */
+	if (symbol_conf.kallsyms_name != NULL) {
+		kallsyms_filename = symbol_conf.kallsyms_name;
+		goto do_kallsyms;
+	}
+
 	if (symbol_conf.vmlinux_name != NULL) {
 		err = dso__load_vmlinux(self, map,
 					symbol_conf.vmlinux_name, filter);
@@ -1867,6 +1917,10 @@
 			goto out_fixup;
 	}
 
+	/* do not try local files if a symfs was given */
+	if (symbol_conf.symfs[0] != 0)
+		return -1;
+
 	/*
 	 * Say the kernel DSO was created when processing the build-id header table,
 	 * we have a build-id, so check if it is the same as the running kernel,
@@ -2136,7 +2190,7 @@
 };
 
 static int symbol__in_kernel(void *arg, const char *name,
-			     char type __used, u64 start)
+			     char type __used, u64 start, u64 end __used)
 {
 	struct process_args *args = arg;
 
@@ -2257,9 +2311,6 @@
 	struct utsname uts;
 	char bf[PATH_MAX];
 
-	if (uname(&uts) < 0)
-		return -1;
-
 	vmlinux_path = malloc(sizeof(char *) * 5);
 	if (vmlinux_path == NULL)
 		return -1;
@@ -2272,6 +2323,14 @@
 	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
 		goto out_fail;
 	++vmlinux_path__nr_entries;
+
+	/* only try running kernel version if no symfs was given */
+	if (symbol_conf.symfs[0] != 0)
+		return 0;
+
+	if (uname(&uts) < 0)
+		return -1;
+
 	snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
 	vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
 	if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
@@ -2331,6 +2390,8 @@
 
 int symbol__init(void)
 {
+	const char *symfs;
+
 	if (symbol_conf.initialized)
 		return 0;
 
@@ -2359,6 +2420,18 @@
 		       symbol_conf.sym_list_str, "symbol") < 0)
 		goto out_free_comm_list;
 
+	/*
+	 * A path to symbols of "/" is identical to ""
+	 * reset here for simplicity.
+	 */
+	symfs = realpath(symbol_conf.symfs, NULL);
+	if (symfs == NULL)
+		symfs = symbol_conf.symfs;
+	if (strcmp(symfs, "/") == 0)
+		symbol_conf.symfs = "";
+	if (symfs != symbol_conf.symfs)
+		free((void *)symfs);
+
 	symbol_conf.initialized = true;
 	return 0;
 
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6c6eafd..670cd1c 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -72,6 +72,7 @@
 			show_cpu_utilization,
 			initialized;
 	const char	*vmlinux_name,
+			*kallsyms_name,
 			*source_prefix,
 			*field_sep;
 	const char	*default_guest_vmlinux_name,
@@ -85,6 +86,7 @@
        struct strlist	*dso_list,
 			*comm_list,
 			*sym_list;
+	const char	*symfs;
 };
 
 extern struct symbol_conf symbol_conf;
@@ -215,7 +217,7 @@
 int build_id__sprintf(const u8 *self, int len, char *bf);
 int kallsyms__parse(const char *filename, void *arg,
 		    int (*process_symbol)(void *arg, const char *name,
-					  char type, u64 start));
+					  char type, u64 start, u64 end));
 
 void machine__destroy_kernel_maps(struct machine *self);
 int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 8c72d88..00f4ead 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -16,35 +16,50 @@
 		return 1;
 }
 
-int find_all_tid(int pid, pid_t ** all_tid)
+struct thread_map *thread_map__new_by_pid(pid_t pid)
 {
+	struct thread_map *threads;
 	char name[256];
 	int items;
 	struct dirent **namelist = NULL;
-	int ret = 0;
 	int i;
 
 	sprintf(name, "/proc/%d/task", pid);
 	items = scandir(name, &namelist, filter, NULL);
 	if (items <= 0)
-                return -ENOENT;
-	*all_tid = malloc(sizeof(pid_t) * items);
-	if (!*all_tid) {
-		ret = -ENOMEM;
-		goto failure;
+                return NULL;
+
+	threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
+	if (threads != NULL) {
+		for (i = 0; i < items; i++)
+			threads->map[i] = atoi(namelist[i]->d_name);
+		threads->nr = items;
 	}
 
-	for (i = 0; i < items; i++)
-		(*all_tid)[i] = atoi(namelist[i]->d_name);
-
-	ret = items;
-
-failure:
 	for (i=0; i<items; i++)
 		free(namelist[i]);
 	free(namelist);
 
-	return ret;
+	return threads;
+}
+
+struct thread_map *thread_map__new_by_tid(pid_t tid)
+{
+	struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
+
+	if (threads != NULL) {
+		threads->map[0] = tid;
+		threads->nr	= 1;
+	}
+
+	return threads;
+}
+
+struct thread_map *thread_map__new(pid_t pid, pid_t tid)
+{
+	if (pid != -1)
+		return thread_map__new_by_pid(pid);
+	return thread_map__new_by_tid(tid);
 }
 
 static struct thread *thread__new(pid_t pid)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 688500f..d757410 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,11 +18,24 @@
 	int			comm_len;
 };
 
+struct thread_map {
+	int nr;
+	int map[];
+};
+
 struct perf_session;
 
 void thread__delete(struct thread *self);
 
-int find_all_tid(int pid, pid_t ** all_tid);
+struct thread_map *thread_map__new_by_pid(pid_t pid);
+struct thread_map *thread_map__new_by_tid(pid_t tid);
+struct thread_map *thread_map__new(pid_t pid, pid_t tid);
+
+static inline void thread_map__delete(struct thread_map *threads)
+{
+	free(threads);
+}
+
 int thread__set_comm(struct thread *self, const char *comm);
 int thread__comm_len(struct thread *self);
 struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index b157260..35729f4 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -34,11 +34,13 @@
 #include <ctype.h>
 #include <errno.h>
 #include <stdbool.h>
+#include <linux/list.h>
 #include <linux/kernel.h>
 
 #include "../perf.h"
 #include "trace-event.h"
 #include "debugfs.h"
+#include "evsel.h"
 
 #define VERSION "0.5"
 
@@ -469,16 +471,17 @@
 }
 
 static struct tracepoint_path *
-get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
+get_tracepoints_path(struct list_head *pattrs)
 {
 	struct tracepoint_path path, *ppath = &path;
-	int i, nr_tracepoints = 0;
+	struct perf_evsel *pos;
+	int nr_tracepoints = 0;
 
-	for (i = 0; i < nb_events; i++) {
-		if (pattrs[i].type != PERF_TYPE_TRACEPOINT)
+	list_for_each_entry(pos, pattrs, node) {
+		if (pos->attr.type != PERF_TYPE_TRACEPOINT)
 			continue;
 		++nr_tracepoints;
-		ppath->next = tracepoint_id_to_path(pattrs[i].config);
+		ppath->next = tracepoint_id_to_path(pos->attr.config);
 		if (!ppath->next)
 			die("%s\n", "No memory to alloc tracepoints list");
 		ppath = ppath->next;
@@ -487,21 +490,21 @@
 	return nr_tracepoints > 0 ? path.next : NULL;
 }
 
-bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events)
+bool have_tracepoints(struct list_head *pattrs)
 {
-	int i;
+	struct perf_evsel *pos;
 
-	for (i = 0; i < nb_events; i++)
-		if (pattrs[i].type == PERF_TYPE_TRACEPOINT)
+	list_for_each_entry(pos, pattrs, node)
+		if (pos->attr.type == PERF_TYPE_TRACEPOINT)
 			return true;
 
 	return false;
 }
 
-int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
+int read_tracing_data(int fd, struct list_head *pattrs)
 {
 	char buf[BUFSIZ];
-	struct tracepoint_path *tps = get_tracepoints_path(pattrs, nb_events);
+	struct tracepoint_path *tps = get_tracepoints_path(pattrs);
 
 	/*
 	 * What? No tracepoints? No sense writing anything here, bail out.
@@ -545,14 +548,13 @@
 	return 0;
 }
 
-ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
-			       int nb_events)
+ssize_t read_tracing_data_size(int fd, struct list_head *pattrs)
 {
 	ssize_t size;
 	int err = 0;
 
 	calc_data_size = 1;
-	err = read_tracing_data(fd, pattrs, nb_events);
+	err = read_tracing_data(fd, pattrs);
 	size = calc_data_size - 1;
 	calc_data_size = 0;
 
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b3e86b1..b5f12ca 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -262,9 +262,8 @@
 void *raw_field_ptr(struct event *event, const char *name, void *data);
 unsigned long long eval_flag(const char *flag);
 
-int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
-ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
-			       int nb_events);
+int read_tracing_data(int fd, struct list_head *pattrs);
+ssize_t read_tracing_data_size(int fd, struct list_head *pattrs);
 
 /* taken from kernel/trace/trace.h */
 enum trace_flag_type {
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 056c695..7b5a892 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -104,10 +104,24 @@
 	return rc;
 }
 
-static const char yes[] = "Yes", no[] = "No";
+static const char yes[] = "Yes", no[] = "No",
+		  warning_str[] = "Warning!", ok[] = "Ok";
 
 bool ui__dialog_yesno(const char *msg)
 {
 	/* newtWinChoice should really be accepting const char pointers... */
 	return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1;
 }
+
+void ui__warning(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	if (use_browser > 0)
+		newtWinMessagev((char *)warning_str, (char *)ok,
+				(char *)format, args);
+	else
+		vfprintf(stderr, format, args);
+	va_end(args);
+}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 2142656..5b3ea49 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -114,3 +114,20 @@
 
 	return value;
 }
+
+int readn(int fd, void *buf, size_t n)
+{
+	void *buf_start = buf;
+
+	while (n) {
+		int ret = read(fd, buf, n);
+
+		if (ret <= 0)
+			return ret;
+
+		n -= ret;
+		buf += ret;
+	}
+
+	return buf - buf_start;
+}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 7562707..e833f26 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -265,6 +265,7 @@
 bool strglobmatch(const char *str, const char *pat);
 bool strlazymatch(const char *str, const char *pat);
 unsigned long convert_unit(unsigned long value, char *unit);
+int readn(int fd, void *buf, size_t size);
 
 #define _STR(x) #x
 #define STR(x) _STR(x)
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
new file mode 100644
index 0000000..22afbf6
--- /dev/null
+++ b/tools/perf/util/xyarray.c
@@ -0,0 +1,20 @@
+#include "xyarray.h"
+#include "util.h"
+
+struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
+{
+	size_t row_size = ylen * entry_size;
+	struct xyarray *xy = zalloc(sizeof(*xy) + xlen * row_size);
+
+	if (xy != NULL) {
+		xy->entry_size = entry_size;
+		xy->row_size   = row_size;
+	}
+
+	return xy;
+}
+
+void xyarray__delete(struct xyarray *xy)
+{
+	free(xy);
+}
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
new file mode 100644
index 0000000..c488a07
--- /dev/null
+++ b/tools/perf/util/xyarray.h
@@ -0,0 +1,20 @@
+#ifndef _PERF_XYARRAY_H_
+#define _PERF_XYARRAY_H_ 1
+
+#include <sys/types.h>
+
+struct xyarray {
+	size_t row_size;
+	size_t entry_size;
+	char contents[];
+};
+
+struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
+void xyarray__delete(struct xyarray *xy);
+
+static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
+{
+	return &xy->contents[x * xy->row_size + y * xy->entry_size];
+}
+
+#endif /* _PERF_XYARRAY_H_ */